Day1:
1. Lambda表達(dá)式
- Lambda表達(dá)式的基本結(jié)構(gòu):
(param1,param2,param3,paramN) ->{body}
- 關(guān)于函數(shù)式接口:
- 如果一個(gè)接口只有一個(gè)抽象方法淌铐,那么該接口就是一個(gè)函數(shù)式接口。
- 如果我們在某個(gè)接口上聲明了FunctionalInterface注解,那么編譯器就會(huì)按照函數(shù)式接口的定義來要求該接口。
- 如果某個(gè)接口只有一個(gè)抽象方法,但我們沒有給該接口聲明FunctionalInterface注解席吴,那么編譯器依舊會(huì)將該接口看作是函數(shù)式接口溅漾。
ps(為什么函數(shù)式接口中只有一個(gè)抽象方法:因?yàn)樵贚ambad表達(dá)式中并沒有指定方法名字(所以函數(shù)式接口中的方法只能有一個(gè)))
在java中Lambad表示式是對象扩淀,他們必須依附于一類特別的對象函數(shù)——函數(shù)式接口(functional interface)
test2.myTest(()-> {
System.out.println("MyInterface");
});
//method reference(方法引用)
list.forEach(System.out::println);
List<String> list = Arrays.asList("nihao", "xiaoming");
list.forEach(item -> System.out.println(item.toUpperCase()));
List<String> list1 = new ArrayList<>();
list.forEach(item -> list1.add(item.toUpperCase()));
list.stream().map(item ->item.toUpperCase()).forEach(item -> System.out.println(item));
list.stream().map(String::toUpperCase).forEach(item-> System.out.println(item));
運(yùn)行結(jié)果
"C:\Program Files\Java\jdk1.8.0_201\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.1\lib\idea_rt.jar=59655:C:\Program Files\JetBrains\IntelliJ IDEA 2019.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_201\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_201\jre\lib\rt.jar;C:\Users\user\ideaTest\java8\target\classes" com.mobius.vision.jdk8.Test3
NIHAO
XIAOMING
NIHAO
XIAOMING
NIHAO
XIAOMING
Lamdba表達(dá)式的作用:
- 傳遞行為哎甲,而不僅僅是值。
- 提升抽象層次
- API重用性更好
- 更加靈活
Java Lambda結(jié)構(gòu)
- 一個(gè)Lambda表達(dá)式可以有零個(gè)或多個(gè)參數(shù)
- 參數(shù)的類型既可以明確聲明饲嗽,也可以根據(jù)上下文來推斷炭玫。例如:(int a)與(a)效果相同。
- 空圓括號(hào)代表參數(shù)集為空貌虾。例如:()->42
- (args1,args2....)->{body} Lambda表達(dá)式的語法
System.out.println(functionTest.addThe(1,2,(value1,value2)->value1+value2,value3->value3*value3));
//先將1和2作為參數(shù)給biFunction:1+2得3然后將3作為參數(shù)給function3*3得9
}
public Integer addThe(int a,int b,BiFunction<Integer,Integer,Integer> biFunction,
Function<Integer,Integer> function){
return biFunction.andThen(function).apply(a,b);
}
Lambda表達(dá)式的一些操作
package com.mobius.vision.jdk8;
import java.util.Arrays;
import java.util.List;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
/**
* @author NingXioaoming
* @createTime 2019/11/8 11:05
* @description
*/
public class Test4 {
public static void main(String[] args) {
Person person = new Person();
person.setUserName("zhangsan");
person.setAge(18);
Person person1 = new Person();
person1.setUserName("lisi");
person1.setAge(20);
Person person2 = new Person();
person2.setUserName("wangwu");
person2.setAge(22);
List<Person> list = Arrays.asList(person, person1, person2);
Test4 test4 = new Test4();
List<Person> persons = test4.getPersonsByUsername("zhangsan", list);
persons.forEach(pp-> System.out.println(pp.getUserName()));
List<Person> personsByUsername = test4.getPersonsByUsername(20, list);
personsByUsername.forEach(user-> System.out.println(user.getAge()));
List<Person> personsByT = test4.getPersonsByT(19, list, (age, list1) ->
list1.stream().filter(person3 -> person3.getAge() > age).collect(Collectors.toList())
);
personsByT.forEach(person3 -> System.out.println(person3.getAge()));
}
public List<Person> getPersonsByT(Integer age,List<Person> list,BiFunction<Integer,List<Person>,List<Person>> biFunction){
return biFunction.apply(age,list);
}
public List<Person> getPersonsByUsername(String userName, List<Person> list){
list.forEach(person -> System.out.println(person.getUserName()));
return list.stream().filter(person1 -> person1.getUserName().equals(userName)).collect(Collectors.toList());
}
public List<Person> getPersonsByUsername(Integer age,List<Person> list){
BiFunction<Integer,List<Person>,List<Person>> biFunction =(age1,personList)->
personList.stream().filter(person -> person.getAge()>age).collect(Collectors.toList());
return biFunction.apply(age,list);
}
}
Day2:
1. Optional
optional的一些使用方法
Optional<String> heloo = Optional.of("1111");//一定不為空
Optional<String> heloo1 = Optional.empty();//一定為空
Optional<String> heloo2 = Optional.ofNullable("1111");//不確定是否為空
heloo.ifPresent(item -> System.out.println(item));
判斷person是否為空方法
List<String> list = Arrays.asList("nihapo", "wohap");
List<String> list1 = Arrays.asList();
Person person = new Person();
person.setList(list1);
Optional<Person> optional = Optional.ofNullable(person);
//判斷person是否為空方法
System.out.println(optional.map(thePerson->thePerson.getList()).orElse(Collections.emptyList()));
方法引用
- 方法引用:method reference
- 方法引用實(shí)際上是個(gè)Lambda表達(dá)式的一種語法糖
- 我們可以將方法引用看做是一個(gè)【函數(shù)指針】吞加,function pointer,
- 方法引用共分為4類
- 類名::靜態(tài)方法名尽狠。
- 引用名(對象名)::實(shí)類方法名衔憨。
- 類名::示例方法名。
- 構(gòu)造方法引用:類名::new
Student student1 = new Student("zhangsan", 18);
Student student2 = new Student("lisi", 20);
Student student3 = new Student("wangwo", 22);
Student student4 = new Student("xuebing", 16);
List<Student> list = Arrays.asList(student1, student2, student3, student4);
list.sort((studentParam1,studentParam2)->Student.compareStudentByScore(studentParam1,studentParam2));
//上下這兩個(gè)排序等價(jià)袄膏,下面是上面的方法糖
//1. 類名::靜態(tài)方法名
list.sort(Student::compareStudentByScore);
list.forEach(student -> System.out.println(student.getScore()));
//2.引用名(對象名)::實(shí)類方法名践图。
StudentCompare studentCompare = new StudentCompare();
list.sort(studentCompare::compareByScore);
list.forEach(student -> System.out.println(student.getScore()));
//3.類名::示例方法名。
list.sort(Student::compareByScore);
//4.構(gòu)造方法引用:類名::new
Stream(流)
- 流由3部分構(gòu)成:
- 源
- 零個(gè)或多個(gè)中間操作:中間操作都會(huì)返回一個(gè)Stream對象沉馆,例如:Stream<Student>码党,Stream<Integer>德崭。
- 終止操作:終止操作則不會(huì)返回Stream類型,可能不返回值揖盘,也可能返回其他類型的單個(gè)值眉厨。
- 流操作的分類:
- 惰性求值
- 及早求值
List<Integer> list = Arrays.asList(2, 4, 5, 6, 8);
list.stream().map(i->i*2).forEach(integer -> System.out.println(integer));
//給list中的每一個(gè)元素*2然后再相加操作
//這是一個(gè)流:list是源,map是中間操作兽狭,reduce是終止操作
System.out.println(list.stream().map(i -> i*2).reduce(0,Integer::sum));
Stream(流)的一些操作
//一個(gè)流只能被操作一次 多次操作編譯報(bào)錯(cuò):Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
Stream<String> stream = Stream.of("hello","nihap");
// String[] strings = stream.toArray(length -> new String[length]);
//等價(jià)于上面 這里使用方法引用
// String[] strings1 = stream.toArray(String[]::new);
//將stream轉(zhuǎn)化成list集合
List<String> collect = stream.collect(Collectors.toList());
collect.forEach(System.out::println);
Stream<String> stream1 = Stream.of("hello","nihap","word");
// List<String> collect1 = stream1.collect(Collectors.toList());
ArrayList<String> collect1 = stream1.collect(() -> new ArrayList(), (theList, iteam) -> theList.add(iteam), (theList1, theList2) -> theList1.addAll(theList2));
//下面的方法引用等價(jià)于上面的lambda表達(dá)式
stream1.collect(ArrayList::new,ArrayList::add,ArrayList::addAll);
collect1.forEach(item-> System.out.println(item));
//將流轉(zhuǎn)化成LinkedHashSet以及其他....
LinkedHashSet<String> collect2 = stream2.collect(Collectors.toCollection(LinkedHashSet::new));
//將流對象轉(zhuǎn)化成String
String collect3 = stream2.collect(Collectors.joining());
//將集合中的元素轉(zhuǎn)化成大寫并輸出Map給一個(gè)元素對這個(gè)元素操作(加減乘除等...)之后返回一個(gè)新的元素
list.stream().map(String::toUpperCase).collect(Collectors.toList()).forEach(item-> System.out.println(item));
Stream<List<Integer>> listStream = Stream.of(Arrays.asList(1, 2), Arrays.asList(2, 3), Arrays.asList(4, 5));
//flatMap的用法:將多個(gè)集合組成的流壓成一個(gè)流
listStream.flatMap(theList->theList.stream()).map(item->item*item).forEach(integer -> System.out.println(integer));
//通過Stream的generate靜態(tài)方法生成Stream對象憾股,然后輸出Stream流中的第一個(gè)元素
Stream<String> stream1 = Stream.generate(UUID.randomUUID()::toString);
stream1.findFirst().ifPresent(System.out::println);
//構(gòu)造88個(gè)偶數(shù)放到Stream流中然后輸出2,4,8,16 n+1=n*n
Stream.iterate(2,item->item*2).limit(88).forEach(System.out::println);
Stream<Integer> stream3 = Stream.iterate(1, item -> item + 2).limit(6);
//取出stream3中的大于2的元素,每一個(gè)乘以二箕慧,然后再提出前兩個(gè)元素服球,然后再取出前兩元素,然后去掉重復(fù)元素,然后再相加
System.out.println(stream3.filter(itemIn -> itemIn > 2).mapToInt(item -> item * 2).skip(2).limit(2).distinct().sum());
//Stream.summaryStatistics();返回IntSummaryStatistics對象包含了一些數(shù)字的結(jié)果(max销钝,min有咨,count。蒸健。座享。。)
IntSummaryStatistics intSummaryStatistics = stream3.filter(itemIn -> itemIn > 2).mapToInt(item -> item * 2).skip(2).limit(2).distinct().summaryStatistics();
System.out.println(intSummaryStatistics.getMax());
System.out.println(intSummaryStatistics.getMin());
System.out.println(intSummaryStatistics.getSum());
System.out.println(intSummaryStatistics.getCount());
- 內(nèi)部迭代:將n個(gè)條件拼接似忧,然后進(jìn)行循環(huán)查找渣叛。
flatMap的用法
List<String> list1 = Arrays.asList("hello ww", "hello ee", "qq hello");
//flatMap:將多個(gè)stream打平放到一個(gè)stream中 (單詞去重)
list1.stream().map(item->item.split(" ")).flatMap(Arrays::stream).distinct().collect(Collectors.toList()).forEach(System.out::println);
分組和分區(qū)的操作
List<Student> students = Arrays.asList(student, student1, student2, student3);
//根據(jù)Student的name進(jìn)行分組類似sql的group by
Map<String, List<Student>> map = students.stream().collect(Collectors.groupingBy(Student::getName));
Map<Integer, List<Student>> map1 = students.stream().collect(Collectors.groupingBy(Student::getScore));
Map<String, Long> collect = students.stream().collect(Collectors.groupingBy(Student::getName, Collectors.counting()));
Map<String, Double> collect1 = students.stream().collect(Collectors.groupingBy(Student::getName, Collectors.averagingInt(Student::getScore)));
//對數(shù)據(jù)分區(qū)
Map<Boolean, List<Student>> collect2 = students.stream().collect(Collectors.partitioningBy(student7 -> student7.getScore() > 80));
collect方法的詳細(xì)介紹: