Java8新特性(Lambda表达式、Stream流、Optional类)等
1. Lambda表达式由来
1 package java8; 2 3 public class EmployeeTest { 4 public static void main(String[] args) { 5 6 Employee employee1 = new EmployeeImpl(); 7 employee1.getSalary(); 8 System.out.println("****************"); 9 10 11 Employee employee2 = new Employee() { 12 @Override 13 public void getSalary() { 14 System.out.println("Employee匿名内部类"); 15 } 16 }; 17 employee2.getSalary(); 18 System.out.println("****************"); 19 20 /** 21 * lambda表达式可以看作是一个接口的实例,使用lambda是有前提条件的,就是该接口必须是函数式接口。 22 * 那么什么是函数式接口呢?用一句话总结就是有且仅有一个抽象方法的接口(在java提供的类库中,函数式接口上面都有@FunctionalInterface注解) 23 * 24 * lambda表达式可以总结为:一个(), 一个 ->, 一段代码{} 25 * 一个():参数 26 * 一段代码{}:具体业务逻辑 27 */ 28 Employee employee3 = () -> { 29 System.out.println("将上述匿名内部类转为使用lambda表达式"); 30 }; 31 employee3.getSalary(); 32 } 33 34 interface Employee { 35 public void getSalary(); 36 } 37 38 static class EmployeeImpl implements Employee { 39 40 @Override 41 public void getSalary() { 42 System.out.print("Employee的普通实现类"); 43 } 44 } 45 }
2. Stream流
2.1 函数型接口Function
1 package java8; 2 3 import java.util.function.Function; 4 5 /** 6 * 1. 函数型接口Function:有输入,有输出 7 * 核心抽象方法为 抽象方法 R apply(T t); 8 */ 9 public class FunctionInterface1 { 10 11 public static void main(String[] args) { 12 // 通过lambda实例化一个接口,实现抽象方法R apply(T t); 13 Functionfunction = (s) -> { 14 if (s == null) { 15 return 0; 16 } 17 return s.length(); 18 }; 19 Integer result = testFunction("hello", function); 20 System.out.println(result); 21 22 System.out.println("****************"); 23 System.out.println(testFunction("hello", s -> { 24 return "更简化的写法".length(); 25 })); 26 } 27 28 29 // interface Function 抽象方法 R apply(T t); 30 private static Integer testFunction(String str, Functionfunction) { 31 // str作为第13行的参数s进行传递 32 return function.apply(str); 33 } 34 }
结果
5
****************
6
2.1 函数型接口Function
- 函数型接口Function
-
抽象方法 R apply(T t)
-
- 消费型接口Consumer
- 抽象方法:void accept(T t)
- 供给型接口Supplier
- 抽象方法:T get()
- 断言型接口Predicate
- 抽象方法:boolean test(T t)
1 package java8; 2 3 import java.util.function.Function; 4 5 /** 6 * 1. 函数型接口Function:有输入,有输出 7 * 核心抽象方法为 抽象方法 R apply(T t); 8 */ 9 public class FunctionInterface1 { 10 11 public static void main(String[] args) { 12 // 通过lambda实例化一个接口,实现抽象方法R apply(T t); 13 Functionfunction = (s) -> { 14 if (s == null) { 15 return 0; 16 } 17 return s.length(); 18 }; 19 Integer result = testFunction("hello", function); 20 System.out.println(result); 21 22 System.out.println("****************"); 23 System.out.println(testFunction("hello", s -> { 24 return "更简化的写法".length(); 25 })); 26 } 27 28 29 // interface Function 抽象方法 R apply(T t); 30 private static Integer testFunction(String str, Functionfunction) { 31 // str作为第13行的参数s进行传递 32 return function.apply(str); 33 } 34 }
1 package java8; 2 3 import java.util.function.Consumer; 4 5 /** 6 * Consumer消费性接口有输入,但是没有返回值 7 * 抽象方法:void accept(T t); 8 */ 9 public class ConsuerFunctionInterface { 10 11 public static void main(String[] args) { 12 // s是实例化方法accept的参数,{}内部是accept的方法体 13 testConsumer(s -> {System.out.println(s);}, "消费性接口抽象方法accept实现"); 14 } 15 16 private static void testConsumer(Consumerconsumer, String str) { 17 consumer.accept(str); 18 } 19 }
1 package java8; 2 3 4 import java.util.function.Supplier; 5 6 /** 7 * Supplier供给型接口:无输入、有输出 8 * 抽象方法:T get(); 9 */ 10 public class SupplierFunctionInterface { 11 12 public static void main(String[] args) { 13 14 // ()是实例化方法T get()参数:即无参数,{}是get的方法体 15 testSupplier(()-> { 16 String name = "Supplier的抽象方法get实现"; 17 System.out.println(name); 18 return new Person(name); 19 }); 20 } 21 22 private static Person testSupplier(Supplier supplier) { 23 return supplier.get(); 24 } 25 26 } 27 28 class Person { 29 private static String name; 30 31 Person(String name) { 32 this.name = name; 33 } 34 }
1 package java8; 2 3 import java.util.function.Predicate; 4 5 /** 6 * 断言型接口Predicate7 * 抽象方法:boolean test(T t); 8 */ 9 public class PredicateFunctionInterface { 10 11 public static void main(String[] args) { 12 // b是test方法的参数, {}内部是test方法体 13 boolean res = testPredicate((b) -> { 14 System.out.println("断言型接口Predicate抽象方法boolean test(T t)的实例化"); 15 return b > 99; 16 }, 99); 17 18 System.out.println("b>99, res=" + res); 19 } 20 21 22 private static boolean testPredicate(Predicate predicate, int a) { 23 return predicate.test(a); 24 } 25 }
2.2 创建Stream流的方式
2.2.1 ::(双冒号)使用
https://www.jianshu.com/p/96b4815d629e
1 package java8; 2 3 import java.util.Arrays; 4 import java.util.Comparator; 5 import java.util.List; 6 import java.util.Optional; 7 8 public class DoubleMaoHao { 9 10 public static void main(String[] args) { 11 ListlistStr = Arrays.asList("adnm", "p", "admmt", "pot", "xbangd", "weoujgsd"); 12 13 // 最大的串:实例化Comparator的抽象方法int compare(T o1, T o2) 14 // (o1, o2)有两个参数,o1作为当前对象,o2作为参数,都是String;返回值为int —— 其它方法满足这样条件的也可以 15 Optional optionalMax1 = listStr.stream().max(((o1, o2) -> { return o1.compareTo(o2);} )); 16 17 // 简写 18 // 而String::compareTo方法是指int compareTo(String anotherString)--即参数为string,返回值为int的 19 // 其它方法 public int indexOf(String str) --即参数为string,返回值为int的 也可以,但是int length() 无参数的方法就不行 20 Optional optionalMax2 = listStr.stream().max(String::compareTo); // String::length报错 21 22 System.out.println("optionalMax1=" + optionalMax1.get() + ", optionalMax2=" + optionalMax2.get()); // optionalMax3=adnm, optionalMax4=w3 23 24 25 List listStr3 = Arrays.asList("adnm", "dn", "n"); 26 List listStr4 = Arrays.asList("adnm", "w3", "3"); 27 Optional optionalMax3 = listStr3.stream().max(String::indexOf); // adnm.indexOf("dn")>0, "dn".indexOf("n")>0 28 Optional optionalMax4 = listStr4.stream().max(String::indexOf); // adnm.indexOf("w3")<0, "w3".indexOf("3")>0 29 System.out.println("optionalMax3=" + optionalMax3.get() + ", optionalMax4=" + optionalMax4.get()); // optionalMax3=adnm, optionalMax4=w3 30 31 Optional optionalMax5 = listStr.stream().max((o1,o2) -> {return 1;}); // >=0:adnm 即两两比较 前面最大; <0,则最后一个最大 32 System.out.println("optionalMax5=" + optionalMax5.get()); // max=adnm (第0个) 33 34 Optional optionalMax6 = listStr.stream().max((o1,o2) -> {return -1;}); // >=0:adnm 即两两比较 前面最大; <0,则最后一个最大 35 System.out.println("optionalMax6=" + optionalMax6.get()); // max=weoujgsd (最后一个) 36 37 38 /** 39 * max()方法中需要一个函数式接口Comparator 40 * comparing方法中需要一个函数型接口Function ,唯一的抽象方法为R apply(T t); 41 * x作为Function方法的参数,到了Function方法体里 x作为对象来调用 无参数方法(这里x是String类型,则可以调用String的所有无参方法且返回值为int) 42 */ 43 Optionalmax1 = listStr.stream().max(Comparator.comparing((x) -> { 44 return x.length(); 45 })); 46 Optional max2 = listStr.stream().max(Comparator.comparing((x) -> { 47 return 1; 48 })); 49 Optional max3 = listStr.stream().max(Comparator.comparing((x) -> { 50 return -1; 51 })); 52 // 要看comparing内部的实现Function keyExtractor (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2)); 53 System.out.println("max1=" + max1.get() + ", max2=" + max2.get() + ", max3=" + max3.get()); // max1=weoujgsd, max2=adnm, max3=adnm 54 55 // 简写形式——使用了静态方法Comparator.comparing,比较的是length属性, 56 Optional max1_1 = listStr.stream().max(Comparator.comparing(String::length)); // String::compareTo报错 57 System.out.println("简写_最长的字符串 max1_1:" + max1_1.get()); 58 } 59 }
结果:
optionalMax1=xbangd, optionalMax2=xbangd optionalMax3=adnm, optionalMax4=w3 optionalMax5=adnm optionalMax6=weoujgsd max1=weoujgsd, max2=adnm, max3=adnm 简写_最长的字符串 max1_1:weoujgsd
参考文献:
1.https://zhuanlan.zhihu.com/p/340538961
2.https://blog.csdn.net/yczz/article/details/50896975
3.https://blog.csdn.net/love905661433/article/details/86422169