一,Lambda表达式的使用

1.举例:Comparator c= Comparator.comparingInt(o -> o);
2.格式:->:Lambda操作符
左边叫做形参列表,其实就是接口中的抽象方法的形参列表
右边叫做Lambda体(重写的抽象方法的方法体)
3.关于Lambda表达式的使用
总结:
-> 左边:lambda形参列表的参数类型可以省略(类型推断),如果形参列表只有一个参数,()可以省略。
-> 右边:Lambda体应该使用一对{}包裹,如果Lambda体只有一条执行语句(可能是return语句),{}和return也可以省略。
要求接口只有一个抽象方法。
4.Lambda表达式的本质:作为函数式接口的实例。
5.如果一个接口中只声明了一个抽象方法,则此接口称为函数式接口。
可以使用注解@FunctionalInterface检查是否是一个函数式接口。
用匿名实现类表示的现在都可以用Lambda表达式表示。

语法格式

  1. /**
  2. * @author yhd
  3. * @createtime 2020/11/13 22:43
  4. */
  5. public class DemoA {
  6. //语法格式一:无参数,无返回值
  7. @Test
  8. public void test1() {
  9. Runnable run = () -> System.out.println("语法格式一:无参数,无返回值");
  10. run.run();
  11. }
  12. //语法格式二:一个参数,无返回值
  13. @Test
  14. public void test2() {
  15. Consumer<String> consumer = args -> System.out.println(args);
  16. consumer.accept("语法格式二:一个参数,无返回值");
  17. }
  18. //语法格式三:Lambda 需要两个以上参数,多条执行语句,并且有返回值。
  19. @Test
  20. public void test3() {
  21. Comparator<Integer> comparable = (args1, args2) -> {
  22. System.out.println("args1 = " + args1);
  23. System.out.println("args2 = " + args2);
  24. return args1 > args2 ? 1 : (args1 == args2 ? 0 : -1);
  25. };
  26. System.out.println("comparable.compare(1,2) = " + comparable.compare(1, 2));
  27. }
  28. }

二,方法引用

Java内置四大核心函数式接口(要求能看懂)
消费性接口 Consumer void accept(T t)
供给型接口 Supplier T get()
函数型接口 Function R apply(T t)
断定型接口 Predicate boolean test(T t)
使用情景:当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用。
方法引用:本质上就是Lambda表达式,而Lambda表达式作为函数式接口的实例,
所以方法引用,也是函数式接口的实例。
使用格式: 类(对象)::方法名
具体分为如下三种情况:
对象::非静态方法
类::静态方法
类::非静态方法
方法引用的使用要求,要求接口中的抽象方法的形参列表和返回值类型与方法引用
的方法的形参列表和返回值类型相同!

语法格式

  1. /**
  2. * @author yhd
  3. * @createtime 2020/11/13 22:43
  4. */
  5. public class DemoA {
  6. private static void run() {
  7. System.out.println("语法格式一:无参数,无返回值");
  8. }
  9. private static int compare(Integer args1, Integer args2) {
  10. System.out.println("args1 = " + args1);
  11. System.out.println("args2 = " + args2);
  12. return args1 > args2 ? 1 : (args1 == args2 ? 0 : -1);
  13. }
  14. //语法格式一:无参数,无返回值
  15. @Test
  16. public void test1() {
  17. Runnable run = DemoA::run;
  18. run.run();
  19. }
  20. //语法格式二:一个参数,无返回值
  21. @Test
  22. public void test2() {
  23. Consumer<String> consumer = System.out::println;
  24. consumer.accept("语法格式二:一个参数,无返回值");
  25. }
  26. //语法格式三:Lambda 需要两个以上参数,多条执行语句,并且有返回值。
  27. @Test
  28. public void test3() {
  29. Comparator<Integer> comparable = DemoA::compare;
  30. System.out.println("comparable.compare(1,2) = " + comparable.compare(1, 2));
  31. }
  32. //语法格式四:
  33. @Test
  34. public void test4(){
  35. Comparator<Integer>comparator= Integer::compareTo;
  36. System.out.println("comparator.compare(1,2) = " + comparator.compare(1, 2));
  37. }
  38. }

三,构造器引用

和方法引用类似,函数式接口的抽象方法的形参列表和构造器的形参列表一致,抽象方法的返回值类型就是构造器所属的类的类型。
数组引用
大家可以把数组看作一个特殊的类,则写法与构造器引用一致。

语法格式

  1. /**
  2. * @author yhd
  3. * @createtime 2020/11/14 0:18
  4. */
  5. public class DemoB {
  6. @Test
  7. public void test1(){
  8. BiFunction<String,String,Employee> emp = Employee::new;
  9. Employee employee = emp.apply("AA", "20");
  10. System.out.println("employee = " + employee);
  11. }
  12. @Test
  13. public void test2(){
  14. Supplier<Employee> emp = Employee::new;
  15. Employee employee = emp.get();
  16. System.out.println("employee.toString() = " + employee.toString());
  17. }
  18. @Test
  19. public void test3(){
  20. Function<Integer,Integer[]> params = Integer[]::new;
  21. Integer[] arrs = params.apply(5);
  22. System.out.println(Arrays.toString(arrs));
  23. }
  24. }
  25. @Data
  26. @NoArgsConstructor
  27. @AllArgsConstructor
  28. class Employee{
  29. private String name;
  30. private String age;
  31. }

四,Stream

1.Stream关注的是数据的运算,与CPU打交道。
集合关注的是是数据的存储,与内存打交道。
2.
①Stream自己不会存储元素。
②Stream不会改变源对象,相反,他们会返回一个持有结果的新Stream。
③Stream操作是延迟执行的,这意味着它们会等到需要结果的时候才执行。
3.Stream的执行流程
①Stream的实例化
②一系列的中间操作(过滤,映射,。。。)
③终止操作
4.说明:
①一个中间链操作,对数据源的数据进行处理。
②一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被使用。

1.实例化

  1. /**
  2. * @author yhd
  3. * @createtime 2020/11/14 20:18
  4. */
  5. public class DemoC {
  6. /**
  7. * 流的4种实例化方式一:
  8. * 通过集合
  9. * 顺序流和并行流的区别:
  10. * 顺序流按照集合的顺序挨个取出元素
  11. * 并行流开多个线程去取,取出元素的顺序可能会发生变化
  12. */
  13. @Test
  14. public void test1(){
  15. List<Integer> list=new ArrayList<>();
  16. //创建一个顺序流
  17. Stream<Integer> stream = list.stream();
  18. //创建一个并行流
  19. Stream<Integer> parallelStream = list.parallelStream();
  20. }
  21. /**
  22. * 流的4种实例化方式二:
  23. * 通过数组
  24. *
  25. */
  26. @Test
  27. public void test2(){
  28. Integer []a=new Integer[]{1,2,3,4,5,6};
  29. Stream<Integer> stream = Arrays.stream(a);
  30. }
  31. /**
  32. * 流的4种实例化方式三:
  33. * 通过of
  34. */
  35. @Test
  36. public void test3(){
  37. Stream<Integer> stream = Stream.of(1, 2, 3);
  38. }
  39. /**
  40. * 流的4种实例化方式四:
  41. * 无限流
  42. */
  43. @Test
  44. public void test4(){
  45. //迭代
  46. Stream.iterate(0,t->t+2).limit(10).forEach(System.out::print);
  47. //生成
  48. Stream.generate(Math::random).limit(10).forEach(System.out::print);
  49. }
  50. }

2,中间操作

1.过滤

  1. /**
  2. * @author yhd
  3. * @createtime 2020/11/14 21:20
  4. */
  5. public class Demo4 {
  6. private static List<Person> persons = new ArrayList<>();
  7. private static Stream<Person> stream;
  8. static {
  9. persons.add(new Person("1","马云",200.00));
  10. persons.add(new Person("2","马化腾",200.00));
  11. persons.add(new Person("3","李彦宏",200.00));
  12. persons.add(new Person("4","刘强东",200.00));
  13. persons.add(new Person("5","张朝阳",200.00));
  14. persons.add(new Person("5","张朝阳",200.00));
  15. stream = persons.stream();
  16. }
  17. //limit()截断取前面
  18. @Test
  19. public void test1() {
  20. stream.limit(2).forEach(System.out::println);
  21. }
  22. //filter()过滤出需要的元素
  23. @Test
  24. public void test2(){
  25. stream.filter(Demo4::test).forEach(System.out::println);
  26. }
  27. private static boolean test(Person person) {
  28. return person.getSalary() > 7000;
  29. }
  30. //skip()截断取后面
  31. @Test
  32. public void test3(){
  33. stream.skip(2).forEach(System.out::println);
  34. }
  35. //distinct()去除重复元素
  36. @Test
  37. public void test4(){
  38. stream.distinct().forEach(System.out::println);
  39. }
  40. }
  41. @Data
  42. @NoArgsConstructor
  43. @AllArgsConstructor
  44. @EqualsAndHashCode
  45. class Person implements Serializable {
  46. private String id;
  47. private String name;
  48. private Double salary;
  49. }

2.映射

  1. /**
  2. * @author yhd
  3. * @createtime 2020/11/14 22:04
  4. */
  5. public class DemoD {
  6. private static List<Person> persons = new ArrayList<>();
  7. private static Stream<Person> stream;
  8. static {
  9. persons.add(new Person("1", "马云", 200.00));
  10. persons.add(new Person("2", "马化腾", 200.00));
  11. persons.add(new Person("3", "李彦宏", 200.00));
  12. persons.add(new Person("4", "刘强东", 200.00));
  13. persons.add(new Person("5", "张朝阳", 200.00));
  14. stream = persons.stream();
  15. }
  16. /**
  17. * map和flatMap的区别:
  18. * list.add(list);
  19. * list.addAll(list);
  20. */
  21. @Test
  22. public void test1() {
  23. stream.map(Person::getName).filter(e -> e.length() > 2).forEach(System.out::println);
  24. }
  25. @Test
  26. public void test2() {
  27. Arrays.asList("aa", "bb", "cc").stream().map(DemoD::StringToStream).forEach(DemoD::accept);
  28. Arrays.asList("aa", "bb", "cc").stream().flatMap(DemoD::StringToStream).forEach(System.out::println);
  29. }
  30. private static void accept(Stream<Character> e) {
  31. e.forEach(System.out::println);
  32. }
  33. public static Stream<Character> StringToStream(String str) {
  34. List<Character> result = new ArrayList<>();
  35. for (Character s : str.toCharArray())
  36. result.add(s);
  37. return result.stream();
  38. }
  39. }

3.排序

  1. /**
  2. * @author yhd
  3. * @createtime 2020/11/14 22:41
  4. */
  5. public class DemoE {
  6. private static List<Person> persons = new ArrayList<>();
  7. private static Stream<Person> stream;
  8. static {
  9. persons.add(new Person("1", "马云", 200.00));
  10. persons.add(new Person("2", "马化腾", 200.00));
  11. persons.add(new Person("3", "李彦宏", 200.00));
  12. persons.add(new Person("4", "刘强东", 200.00));
  13. persons.add(new Person("5", "张朝阳", 200.00));
  14. persons.add(new Person("5", "张朝阳", 200.00));
  15. stream = persons.stream();
  16. }
  17. @Test
  18. public void test1() {
  19. stream.sorted(DemoE::compare);
  20. }
  21. private static int compare(Person o1, Person o2) {
  22. return o1.getSalary() > o2.getSalary() ? 1 : (o1.getSalary() == o2.getSalary() ? 0 : -1);
  23. }
  24. }

3,终止操作

1.匹配与查找

  1. /**
  2. * @author yhd
  3. * @createtime 2020/11/14 22:48
  4. * 终止操作:匹配与查找
  5. */
  6. public class DemoF {
  7. private static List<Person> persons = new ArrayList<>();
  8. private static Stream<Person> stream;
  9. static {
  10. persons.add(new Person("1", "马云", 200.00));
  11. persons.add(new Person("2", "马化腾", 200.00));
  12. persons.add(new Person("3", "李彦宏", 200.00));
  13. persons.add(new Person("4", "刘强东", 200.00));
  14. persons.add(new Person("5", "张朝阳", 200.00));
  15. persons.add(new Person("5", "张朝阳", 200.00));
  16. stream = persons.stream();
  17. }
  18. //全部匹配返回true
  19. @Test
  20. public void test1() {
  21. System.out.println(stream.allMatch(p -> p.getSalary() > 100));
  22. }
  23. //任意匹配返回true
  24. @Test
  25. public void test2() {
  26. System.out.println(stream.anyMatch(p -> p.getSalary() > 100));
  27. }
  28. //都不匹配返回true
  29. @Test
  30. public void test3() {
  31. System.out.println(stream.noneMatch(p -> p.getSalary() > 300));
  32. }
  33. //获取流里面第一个
  34. @Test
  35. public void test4() {
  36. System.out.println(stream.findFirst().get());
  37. }
  38. //获取流里面随机一个
  39. @Test
  40. public void test5() {
  41. System.out.println(stream.findAny());
  42. }
  43. //获取流里面元素个数
  44. @Test
  45. public void test6() {
  46. System.out.println(stream.count());
  47. }
  48. //获取最大
  49. @Test
  50. public void test7() {
  51. System.out.println(stream.max(Comparator.comparing(Person::getSalary)).get());
  52. }
  53. //获取最小
  54. @Test
  55. public void test8() {
  56. System.out.println(stream.min(Comparator.comparing(Person::getSalary)).get());
  57. }
  58. }

2.归约

  1. public class DemoF {
  2. private static List<Person> persons = new ArrayList<>();
  3. private static Stream<Person> stream;
  4. static {
  5. persons.add(new Person("1", "马云", 200.00));
  6. persons.add(new Person("2", "马化腾", 200.00));
  7. persons.add(new Person("3", "李彦宏", 200.00));
  8. persons.add(new Person("4", "刘强东", 200.00));
  9. persons.add(new Person("5", "张朝阳", 200.00));
  10. persons.add(new Person("5", "张朝阳", 200.00));
  11. stream = persons.stream();
  12. }
  13. @Test
  14. public void test9(){
  15. System.out.println(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9).stream().reduce(10, Integer::sum));
  16. }
  17. @Test
  18. public void test10(){
  19. System.out.println(stream.map(Person::getSalary).reduce(0.0, Double::sum));
  20. }
  21. }

3.收集

collect(Collector())
Collector 接口中方法的实现决定了如何对流执行收集的操作。
Collectors实用类提供了很多静态方法,可以方便的创建常见的收集器实例。

  1. /**
  2. * @author yhd
  3. * @createtime 2020/11/14 22:48
  4. *
  5. */
  6. public class DemoF {
  7. private static List<Person> persons = new ArrayList<>();
  8. private static Stream<Person> stream;
  9. static {
  10. persons.add(new Person("1", "马云", 200.00));
  11. persons.add(new Person("2", "马化腾", 200.00));
  12. persons.add(new Person("3", "李彦宏", 200.00));
  13. persons.add(new Person("4", "刘强东", 200.00));
  14. persons.add(new Person("5", "张朝阳", 200.00));
  15. persons.add(new Person("5", "张朝阳", 200.00));
  16. stream = persons.stream();
  17. }
  18. //列出员工的所有工资
  19. @Test
  20. public void test1(){
  21. stream.map(Person::getSalary).collect(Collectors.toList()).forEach(System.out::println);
  22. }
  23. //列出每个员工的工资
  24. @Test
  25. public void test2(){
  26. //System.out.println(stream.distinct().collect(Collectors.toMap(Person::getName, person -> person)));
  27. System.out.println(stream.distinct().collect(Collectors.toMap(Person::getName, Person::getSalary)));
  28. }
  29. }

五,Optional

Optional提供了很多有用的方法,这样我们就不用显示的进行空值检测。
1.创建Optional类对象的方法:
Optional.of(T t):创建一个Optional实例,t必须非空。
Optional.empty():创建一个空的Optional实例。
Optional.ofNullable(T t):t可以为null。
2.判断Optional容器中是否包含对象:
boolean isPresent() 判断是否包含对象
void ifPresent(Consumer<? super T> consumer):如果有值,就执行Consumer接口的实现代码,并且该值作为参数传给他。
3.获取Optional容器的对象
T get() 如果调用对象包含值,返回该值,否则抛出异常
T orElse(T other) 如果有值则将其返回,否则返回指定的other对象
T orElseGet(Supperlier<? super T> other) 如果有值则将其返回,否则返回由Supplier接口实现提供的对象。
T orElseThrow(Supperlier<? super X> exceptionSupplier) 如果有值则将其返回,否则抛出由Supplier接口实现提供的异常。

  1. /**
  2. * @author yhd
  3. * @createtime 2020/11/15 0:44
  4. */
  5. public class DemoG {
  6. @Test
  7. public void test() {
  8. Girl girl = new Girl();
  9. System.out.println(Optional.ofNullable(Optional.ofNullable(girl).orElseGet(Girl::new).getBoy()).orElseGet(Boy::new).getName());
  10. }
  11. }
  12. @Data
  13. @NoArgsConstructor
  14. @AllArgsConstructor
  15. class Girl {
  16. private Boy boy;
  17. }
  18. @Data
  19. @NoArgsConstructor
  20. @AllArgsConstructor
  21. class Boy {
  22. private String name;
  23. }