知識(shí)模塊:
一.方法引用a.方法概述b.方法引用格式
二.Stream流1.Stream流概述2.Stream流操作步驟一.方法引用a.方法概述/*方法引用概述:當(dāng)我們使用已有類中的方法作為Lambda表達(dá)式對(duì)應(yīng)的接口中的抽象方法實(shí)現(xiàn)我們可以用方法引用來簡化Lambda表達(dá)式*/
import org.junit.Test;import java.util.function.Consumer;/*方法引用概述:當(dāng)我們使用已有類中的方法作為Lambda表達(dá)式對(duì)應(yīng)的接口中的抽象方法實(shí)現(xiàn)我們可以用方法引用來簡化Lambda表達(dá)式*/
public class MethodRef01 {@Testpublic void test01() {Consumer<String> c = str -> System.out.println(str);c.accept("abc");System.out.println(System.out);//java.io.PrintStream@f5f2bb7}@Testpublic void test02() {//Consumer<String> c = str -> System.out.println(str);Consumer<String>c=System.out::println; //System.out代表了我們要引用的類//::后面的println代表我們引用的方法c.accept("abc");}}
/*class MethodRefDemo$$Lambda$1 implements Consumer<sTRING>{public void accept(String str){System.out.println(str);//我們使用是PrintStream類中的println(String str)方法//作為str->System.out.println(str)對(duì)應(yīng)的Consumer<String>//中accept(String str)的實(shí)現(xiàn)}}*/
b.方法引用格式方法引用使用的前提:(適用于1,2)引用的方法和Lambda表達(dá)式對(duì)應(yīng)接口中的抽象方法中的形參類型保持一致
1.成員方法引用a.引用非靜態(tài)成員方法/*非靜態(tài)成員引用對(duì)象名::方法名*/
import java.util.Objects;public class Person {private String name;public Person(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +'}';}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (!(o instanceof Person person)) return false;return name.equals(person.name);}@Overridepublic int hashCode() {return Objects.hash(name);}
}
import org.junit.Test;import java.util.function.Consumer;
import java.util.function.Supplier;/*方法引用使用的前提:引用的方法和Lambda表達(dá)式對(duì)應(yīng)接口中的抽象方法中的形參類型保持一致非靜態(tài)成員引用對(duì)象名::方法名*/
public class MethodRefDemo02 {Person p = new Person("老王");@Testpublic void test01() {//Supplier<String >s=()->p.getName();Supplier<String> s = p::getName;System.out.println(s.get());}@Testpublic void test02() {//Consumer<String> c = name -> p.setName(name);Consumer<String>c=p::setName;c.accept("老李");System.out.println(p);}@Testpublic void test03() {String str = "abc";//Supplier<Integer> s = () -> str.length();Supplier<Integer> s = str::length;System.out.println(s.get());}@Testpublic void test04() {String str = "abc";//Supplier<Character> s = () -> str.charAt(1);/* Supplier<Character>s=str::charAt; //一個(gè)有參,一個(gè)無參,不能簡化System.out.println(s.get());*/}
}
b.引用靜態(tài)成員方法/*靜態(tài)方法引用類名::靜態(tài)方法名Arrays,CollectionsArrays類中static String toString(int[] a)返回指定數(shù)組內(nèi)容的字符串表示形式。Collections類public static <T extends Comparable<? super T>> void sort(List<T> list)根據(jù)元素的自然順序 對(duì)指定列表按升序進(jìn)行排序*/
import org.junit.Test;import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;/*靜態(tài)方法引用類名::靜態(tài)方法名Arrays,CollectionsArrays類中static String toString(int[] a)返回指定數(shù)組內(nèi)容的字符串表示形式。Collections類public static <T extends Comparable<? super T>> void sort(List<T> list)根據(jù)元素的自然順序 對(duì)指定列表按升序進(jìn)行排序*/
public class MethodRefDemo03 {@Testpublic void test01() {int[] arr = {3, 7, 9};//Function<int[], String> f = array -> Arrays.toString(array);Function<int[],String>f=Arrays::toString;System.out.println(f.apply(arr));}@Testpublic void test02() {List<Integer> integers = Arrays.asList(1, 7, 12, 5, 23);//Consumer<List<Integer>> c = list -> Collections.sort(list);Consumer<List<Integer>> c = Collections::sort;c.accept(integers);System.out.println(integers);}
}
2.構(gòu)造方法引用/*構(gòu)造方法引用格式:類名::new*/
??????3.數(shù)組對(duì)象引用數(shù)組對(duì)象引用格式類型[]::new
import org.junit.Test;import java.util.function.Function;/*構(gòu)造方法引用格式:類名::new數(shù)組對(duì)象引用格式類型[]::new*/
public class MethodRefDemo04 {@Testpublic void test01() {//創(chuàng)建一個(gè)Person類的對(duì)象,獲取這個(gè)對(duì)象//Function<String, Person> f = name -> new Person(name);Function<String, Person> f = Person::new;System.out.println(f.apply("三豐"));}@Testpublic void test02() {//創(chuàng)建一個(gè)指定長度的數(shù)組,返回這個(gè)數(shù)組對(duì)象//Function<Integer, int[]> f = n -> new int[n];Function<Integer, int[]> f=int[]::new;System.out.println(f.apply(4).length);}
}
4.特殊的非靜態(tài)方法/*特殊的非靜態(tài)方法的引用格式:類名::非靜態(tài)方法名***1.不再適用于放啊引用的前提條件2.當(dāng)Lambda表達(dá)式第一個(gè)參數(shù),作為實(shí)例(非靜態(tài))方法的調(diào)用者,第二個(gè)參數(shù)作為實(shí)例對(duì)象的參數(shù),可以受用 類名::非靜態(tài)方法名3.當(dāng)Lambda表達(dá)式的參數(shù)作為一個(gè)空參實(shí)例方法的調(diào)用者時(shí)候,也可使用 類名::非靜態(tài)方法名*/
import org.junit.Test;import java.util.function.BiPredicate;
import java.util.function.Function;/*特殊的非靜態(tài)方法的引用格式:類名::非靜態(tài)方法名1.不再適用于放啊引用的前提條件2.當(dāng)Lambda表達(dá)式第一個(gè)參數(shù),作為實(shí)例(非靜態(tài))方法的調(diào)用者,第二個(gè)參數(shù)作為實(shí)例對(duì)象的參數(shù),可以受用 類名::非靜態(tài)方法名3.當(dāng)Lambda表達(dá)式的參數(shù)作為一個(gè)空參實(shí)例方法的調(diào)用者時(shí)候,也可使用 類名::非靜態(tài)方法名*/
public class MethodRefDemo05 {@Testpublic void test01() {Person p1 = new Person("老王");Person p2 = new Person("老李");//BiPredicate<Person, Person> bp = (person1, person2) -> person1.equals(person2);BiPredicate<Person, Person> bp = Person::equals;System.out.println(bp.test(p1, p2));}@Testpublic void test02() {Person p1 = new Person("老王");//Function<Person, String> f = person -> person.getName();Function<Person, String> f = Person::getName;System.out.println(f.apply(p1));}
}
二.Stream流1.Stream流概述Strean流的出現(xiàn)是為了增強(qiáng)集合和數(shù)組的操作,Stream流更專注于數(shù)據(jù)的轉(zhuǎn)換,過濾,獲取等一系列操作同時(shí)Stream流提高了操作集合和數(shù)組的小籠包,簡化了代碼
import org.junit.Test;import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;/*Stream流的概述統(tǒng)計(jì)后綴名為.txt文件名稱的個(gè)數(shù)*/
public class StreamDemo01 {@Testpublic void test01() {ArrayList<String> al = new ArrayList<String>();al.add("1.txt");al.add("2.txt");al.add("3.pdf");al.add("4.docx");int count=0;for (String s : al) {if (s.endsWith(".txt")) {count++;}}System.out.println(count);}@Testpublic void test02() {List<String> list = Arrays.asList("1.txt", "2.txt", "3.pdf", "4.docx");/*long count = list.stream().filter(str -> str.endsWith(".txt")).count();System.out.println(count);*/System.out.println(list.stream().filter(str -> str.endsWith(".txt")).count());}
}
2.Stream流操作步驟1.根據(jù)數(shù)據(jù)源獲取一個(gè)Stream對(duì)象/*集合或數(shù)組流對(duì)象的獲取集合:Collection體系:都是通過Stream()方法來獲取一個(gè)流對(duì)象ListSetMap體系: 需要轉(zhuǎn)換到Collection體系的集合,才能調(diào)用stream()方法獲取一個(gè)流對(duì)象HashMap數(shù)組:static <T> Stream<T> of(T... values)返回一個(gè)元素為指定值的順序排列的流。*/
import org.junit.Test;import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.stream.Stream;/*集合或數(shù)組流對(duì)象的獲取集合:Collection體系:都是通過Stream()方法來獲取一個(gè)流對(duì)象ListSetMap體系: 需要轉(zhuǎn)換到Collection體系的集合,才能調(diào)用stream()方法獲取一個(gè)流對(duì)象HashMap數(shù)組:static <T> Stream<T> of(T... values)返回一個(gè)元素為指定值的順序排列的流。*/
public class StreamDemo02 {@Testpublic void test01() {Stream<Stream> stream1 = new ArrayList<Stream>().stream();//Stream流上的泛型和集合中元素的類型相對(duì)應(yīng)//當(dāng)我們通過集合對(duì)象來調(diào)用stream()方法,相當(dāng)于//將集合中的元素添加到Stream流中等待操作Stream<Integer> stream2 = new HashSet<Integer>().stream();//Stream流上的泛型和集合中元素的類型相對(duì)應(yīng)}@Testpublic void test02() {new HashMap<Integer,Stream>().keySet().stream();//需要將Map轉(zhuǎn)換成Collection體系的集合,就可以使用stream()方法獲取流對(duì)象//將一個(gè)個(gè)key添加到stream中new HashMap<Integer,String>().entrySet().stream();//將一個(gè)entry對(duì)象{key=value}添加到stream流中}@Testpublic void test03() {int[] arr = {1, 3, 9};Stream<int[]> stream1 = Stream.of(arr);//如果通過基本類型數(shù)組獲取一個(gè)流對(duì)象,此時(shí)六種只有一個(gè)元素:這個(gè)數(shù)組對(duì)象Integer[] arr2 = {1, 3, 9};Stream<Integer> stream2 = Stream.of(arr2);//我們通過基本類型對(duì)應(yīng)的包裝類的引用類型數(shù)組,獲取流對(duì)象,此時(shí)相當(dāng)于將數(shù)組中的元素添加到流中Stream<String> stream3 = Stream.of("abc", "def", "ghk");//通過一串?dāng)?shù)據(jù)獲取流對(duì)象Stream<Integer> stream4 = Stream.of(3, 5, 7);}
}
2.通過Stream對(duì)象可以進(jìn)行0次或多次中間操作/*中間操作:過濾操作filter:傳入一個(gè)Predicate,根據(jù)Predicate中的條件對(duì)流中的元素做一個(gè)篩選,滿足條件保留,不滿足的剔除排序操作:sorted:可以根據(jù)指定的規(guī)則,將流中的元素從小到大排序去重操作distinct:去除流中重復(fù)的元素截取操作limit:根據(jù)傳入的值,來決定截取流總元素的個(gè)數(shù)skip: 根據(jù)傳入的值,決定跳過流中的元素個(gè)數(shù)映射操作map:講義中數(shù)據(jù)根據(jù)指定操作映射成另一種數(shù)據(jù)mapToIntmapToDoublemapToLong*/
public class Student {//學(xué)生姓名private String name;//語文成績private double chineseScore;//數(shù)學(xué)成績private double mathScore;public Student(String name, double chineseScore, double mathScore) {this.name = name;this.chineseScore = chineseScore;this.mathScore = mathScore;}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getChineseScore() {return chineseScore;}public void setChineseScore(double chineseScore) {this.chineseScore = chineseScore;}public double getMathScore() {return mathScore;}public void setMathScore(double mathScore) {this.mathScore = mathScore;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", chineseScore=" + chineseScore +", mathScore=" + mathScore +'}';}
}
/*中間操作:過濾操作filter:傳入一個(gè)Predicate,根據(jù)Predicate中的條件對(duì)流中的元素做一個(gè)篩選,滿足條件保留,不滿足的剔除排序操作:sorted:可以根據(jù)指定的規(guī)則,將流中的元素從小到大排序去重操作distinct:去除流中重復(fù)的元素截取操作limit:根據(jù)傳入的值,來決定截取流總元素的個(gè)數(shù)skip: 根據(jù)傳入的值,決定跳過流中的元素個(gè)數(shù)映射操作map:講義中數(shù)據(jù)根據(jù)指定操作映射成另一種數(shù)據(jù)mapToIntmapToDoublemapToLong班級(jí)中有5個(gè)人姓名,語文成績,數(shù)學(xué)成績分別如下李雷, 70, 90韓梅梅, 30, 100李寧, 85, 80王松,70,60張家界,90,73需求:1.打印語文成績>80的學(xué)生信息2.打印數(shù)學(xué)成績前三名的學(xué)生信息3.打印數(shù)學(xué)成績倒數(shù)第一和倒數(shù)第二的學(xué)生信息4.獲取全班數(shù)學(xué)的平均成績5.獲取全班語文成績(不包含重復(fù)成績)6.將語文成績或數(shù)學(xué)成績?cè)赱80,90]之間的學(xué)生的姓名收集到一個(gè)集合中*/import org.junit.Before;
import org.junit.Test;import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;public class StreamDemo04 {//@Before會(huì)在所有的@Test注解之前執(zhí)行List<Student> students;@Beforepublic void init() {//初始化數(shù)據(jù)源students= Arrays.asList(new Student("李雷", 70, 90),new Student("韓梅梅", 30, 100),new Student("李寧", 85, 80),new Student("王松", 70, 60),new Student("張家界", 90, 73));}@Testpublic void test02() {//1.打印語文成績>80的學(xué)生信息students.stream().filter(stu -> stu.getChineseScore() > 80).forEach(System.out::println);}@Testpublic void test03() {//2.打印數(shù)學(xué)成績前三名的學(xué)生信息/*a.首先需要對(duì)學(xué)生的成績從大到小排序b.獲取前三名的信息*/students.stream().sorted((stu1,stu2)->(int)(stu2.getMathScore()-stu1.getMathScore())).limit(3)//截取流中的前三個(gè)元素.forEach(System.out::println);}@Testpublic void test04() {// 3.打印數(shù)學(xué)成績倒數(shù)第一和倒數(shù)第二的學(xué)生信息/*a.首先需要對(duì)學(xué)生的數(shù)學(xué)成績從大到小排序b.獲取倒數(shù)第一和倒數(shù)第二*/students.stream().sorted((stu1, stu2) -> (int) (stu2.getMathScore() - stu1.getMathScore())).skip(students.size() - 2).forEach(System.out::println);}@Testpublic void test05() {//4.獲取全班數(shù)學(xué)的平均成績//將流中的以惡搞個(gè)學(xué)生對(duì)象映射成每個(gè)學(xué)生對(duì)應(yīng)的數(shù)學(xué)成績double avgScore = students.stream().mapToDouble(stu -> stu.getMathScore()).average().getAsDouble();System.out.println(avgScore);}@Testpublic void test06() {// 5.獲取全班語文成績(不包含重復(fù)成績)// 需要使用mapToDouble//students.stream().mapToDouble(stu->stu.getChineseScore()).distinct().forEach(System.out::println);//students.stream().map(stu->stu.getChineseScore()).distinct().forEach(System.out::println);students.stream().map(Student::getChineseScore).distinct().forEach(System.out::println);}@Testpublic void test07() {// 6.將語文成績或數(shù)學(xué)成績?cè)赱80,90]之間的學(xué)生的姓名收集到一個(gè)集合中//a.語文成績?cè)赱80,90]之間的學(xué)生(Predicate) 或者 數(shù)學(xué)成績?cè)赱80,90]之間(Predicate)//b.將過濾后的一個(gè)個(gè)學(xué)生對(duì)象映射成一個(gè)個(gè)學(xué)生姓名//c.將過濾和映射中間操作后的數(shù)據(jù)收集到以惡搞集合中Predicate<Student>p1=stu->stu.getChineseScore()>=80&&stu.getChineseScore()<=90;Predicate<Student>p2=stu->stu.getMathScore()>=80&&stu.getMathScore()<=90;List<String> names = students.stream().filter(p1.or(p2)).map(Student::getName).collect(Collectors.toList());System.out.println(names);}
}
3.進(jìn)行一次最終操作獲取最終結(jié)果/*Stream流的最終操作:1.迭代forEach:逐個(gè)消費(fèi)流中的元素2.統(tǒng)計(jì)count:統(tǒng)計(jì)流中元素的個(gè)數(shù)max :按照一定比較規(guī)則(Comparator接口實(shí)現(xiàn)規(guī)則),來獲取流中最大元素min :按照一定比較規(guī)則(Comparator接口實(shí)現(xiàn)規(guī)則),來獲取流中最小元素3.查找findFirst4.匹配allMatch:只有流中所有的元素都滿足Predicate(條件),allMatch方法才返回true,否則返回falseanyMatch:只有流中有一個(gè)元素滿足Predicate(條件),anyMatch方法才返回true,否則返回falsenoneMatch:只有流中所有的元素都不滿足Predicate(條件),noneMatch方法才返回true,否則返回false5.收集collect:我們可以將最終操作結(jié)果收集到一個(gè)集合(List,Set,Map)我們主要通過Collections.toList(),Collections.toSet(),Collections.toMap(),將最終操作結(jié)果收集到不同集合中中間操作:sorted*/
import org.junit.Test;import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;/*Stream流的最終操作:1.迭代forEach:逐個(gè)消費(fèi)流中的元素2.統(tǒng)計(jì)count:統(tǒng)計(jì)流中元素的個(gè)數(shù)max :按照一定比較規(guī)則(Comparator接口實(shí)現(xiàn)規(guī)則),來獲取流中最大元素min :按照一定比較規(guī)則(Comparator接口實(shí)現(xiàn)規(guī)則),來獲取流中最小元素3.查找findFirst4.匹配allMatch:只有流中所有的元素都滿足Predicate(條件),allMatch方法才返回true,否則返回falseanyMatch:只有流中有一個(gè)元素滿足Predicate(條件),anyMatch方法才返回true,否則返回falsenoneMatch:只有流中所有的元素都不滿足Predicate(條件),noneMatch方法才返回true,否則返回false5.收集collect:我們可以將最終操作結(jié)果收集到一個(gè)集合(List,Set,Map)我們主要通過Collections.toList(),Collections.toSet(),Collections.toMap(),將最終操作結(jié)果收集到不同集合中中間操作:sorted*/
public class StreamDemo03 {List<String> list = Arrays.asList("zhangsan", "lisi", "laowang");@Testpublic void test01() {//list.stream().forEach(str-> System.out.println(str));list.stream().forEach(System.out::println);}@Testpublic void test02() {long count = list.stream().count();System.out.println(count);}@Testpublic void test03() {list.stream().sorted().forEach(System.out::println);//字符串的默認(rèn)排序方式是字典順序System.out.println("------------");/*Comparator接口的int compare(T o1, T o2);如果compare方法返回一個(gè)正數(shù),默認(rèn)為o1>o2如果compare方法返回一個(gè)負(fù)數(shù),默認(rèn)為o1<o2如果compare方法返回0,默認(rèn)為o1=o2sorted方法默認(rèn)按照元素從小到大排序比較流程:str1="lisi"str2="zhangsan"str1.length() - str2.length()<0 => "lisi"<"zhangsan"第二種情況:str2.length() - str1.length() >0 =>"lisi">"zhangsan"str1="laowang"str2="zhangsan"str1.lemgth() - str2.length() => "laowang"<"zhangsan"第二種情況: str2.length() - str1.length()>0 =>"laowang">"zhangsan"str1="laowang"str2="lisi"str1.length() - str2.length() => "laiwang">"lisi"第二種情況: str2.length() - str1.length()<0 => "laowang"<"kisi"最終結(jié)果: list<laowang<zhangsan第二種情況最終結(jié)果: zhangsan<laowang<lisi*/list.stream().sorted((str1, str2) -> str1.length() - str2.length()).forEach(System.out::println);System.out.println("-------------------");list.stream().sorted((str1, str2) -> str2.length() - str1.length()).forEach(System.out::println);}//List<String> list = Arrays.asList("zhangsan", "lisi", "laowang");@Testpublic void test04() {//獲取最大長度的字符串System.out.println(list.stream().max((str1, str2) -> str1.length() - str2.length()).get());//獲取最小長度字符串System.out.println(list.stream().min((str1, str2) -> str1.length() - str2.length()).get());}@Testpublic void test05() {System.out.println(list.stream().findFirst().get());}@Testpublic void test06() {System.out.println(list.stream().allMatch(str -> str.length() > 4));//falseSystem.out.println(list.stream().anyMatch(str -> str.length() > 4));//trueSystem.out.println(list.stream().noneMatch(str -> str.length() > 4));//true}@Testpublic void test07() {Stream<String> stream = list.stream();List<String> l = stream.collect(Collectors.toList());//將流中的數(shù)據(jù)收集到List集合中System.out.println(l.getClass());System.out.println(l.size());}@Testpublic void test08() {Set<String> set = list.stream().collect(Collectors.toSet());System.out.println(set);}@Testpublic void test09() {//將字符串的長度作為ley,字符串的值作為value去構(gòu)造一個(gè)mapMap<Integer, String> map = list.stream().collect(Collectors.toMap(str -> str.length(), str -> str));System.out.println(map);}
}