JDK1.8 new features (a) ---- the Lambda expressions, Stream API, interface function, method references

jdk1.8 new features knowledge:
  • Lambda expressions
  • Stream API
  • Functional Interface
  • Reference method and constructor calls
  • The default interface methods and static methods
  • The new date and time API
  • default
 
Lambda expressions
    Lambda is our previous code more complex simplified, set of contents is determined such comparison / sorting can be traversed before we removed Analyzing the data we want to write an anonymous inner classes or other methods compareto we want to retrieve data the actual inside them were some judgment is ultimately returned to the comparison of the results we want.
    Example: a scene
        Now we have three users Xiaoming, red, Xiaoqiang their age is 16, 18, 20, and now we want these three users from small to large sorted by age.
        If you press the original wording, our first thought should be to compile anonymous inner class Comparator to compare and sort to get the results we want it, the drawings:
 
    Example: Scene II 
        We are now going to be three user screening, age greater than 16 years old users, our first thought should be judged through the collection filter, and finally put it to a new set of drawings:

 

 Now JDK1.8 provides us with new ways Lambda expressions, code written in more than two examples of upper simpler and more introduction, let's take a look at how much simpler than the code above.

    A scene: figures
    Scene 2: BRIEF

  

 
Below is a summary Lmabda expression syntax:
 
Formulas: In case of a province brackets around the left inferred type Province
 
NOTE: When the presence of a plurality of abstract methods interface, if lambda expressions, and does not match the corresponding intelligent abstract methods, thus introducing the concept of functional interface.
 
First introduce Stream API, top mentions Stream API, write next, next introduce functional interface.
Stream API:
    Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。简单来说,Stream API 提供了一种高效且易于使用的处理数据的方式。
     注意:1.Stream不会自己存储元素
               2.Stream不会改变源对象,相反他们会返回一个持有新结果集的Stream对象。
               3.Stream的操作是延迟执行的,这意味着他们会等到需要结果的时候才执行
               4.  只有当作终止操作时,所有的中间操作会一次性的全部执行,称为“惰性求值”、“延迟加载”  
               5. 每一个Stream流只能操作一次,如果第二次操作会报错stream has already been operated upon or closed
 
    Stream API的执行流程:
直接上代码:
    1.创建流Stream
    2.中间操作
    3.终止操作
 1 //3.终止操作
 2 /**
 3 * 查找和匹配
 4 * allMatch-检查是否匹配所有元素
 5 * anyMatch-检查是否至少匹配一个元素
 6 * noneMatch-检查是否没有匹配所有元素
 7 * findFirst-返回第一个元素
 8 * findAny-返回当前流中的任意元素
 9 * count-返回流中元素的总个数
10 * max-返回流中最大值
11 * min-返回流中最小值
12 */
13 //3.1:allMatch检查是否匹配所有元素是否都成立,都成立返回true 否则返回false
14 Stream<Map<String, Object>> stream2 = maps.stream();
15 boolean a = stream2.allMatch(x -> Integer.valueOf(x.get("age").toString()) > 16);
16 System.err.println("结果:"+a); //false
17 //3.2:anyMatch检查是否至少匹配一个元素,只要有一个成立就返回true
18 Stream<Map<String, Object>> stream3 = maps.stream();
19 boolean b = stream3.anyMatch(x -> Integer.valueOf(x.get("age").toString()) > 16);
20 System.err.println("结果:"+b); //true
21 //3.3:noneMatch检查是否没有匹配所有元素,因为有成立的所以有匹配的元素,估 不成立
22 Stream<Map<String, Object>> stream4 = maps.stream();
23 boolean c = stream4.noneMatch(x -> Integer.valueOf(x.get("age").toString()) > 16);
24 System.err.println("结果:"+c); //false
25 //3.4:findFirst返回第一个元素,按照年龄从小到大排序返回第一个元素
26 Stream<Map<String, Object>> stream5 = maps.stream();
27 Map<String, Object> first = stream5.sorted((x,y) -> Integer.compare(Integer.valueOf(x.get("age")
28 .toString()),Integer.valueOf(y.get("age").toString()))).findFirst().get();
29 System.err.println(first.toString());//{sex=女, name=小红, age=16}
30 //3.5:findAny-返回当前流中的任意元素
31 Stream<Map<String, Object>> stream6 = maps.stream();
32 Map<String, Object> map = stream6.sorted((x,y) -> Integer.compare(Integer.valueOf(y.get("age")
33 .toString()),Integer.valueOf(x.get("age").toString()))).findAny().get();
34 //多次测试返回固定是这个,感觉因该是内部有一个算法排序然后返回其中固定某个 {sex=男, name=小明, age=18}
35 //排序之后返回的永远是第一个
36 System.err.println(map.toString());
37 //3.6:返回流中元素的总个数
38 Stream<Map<String, Object>> stream7 = maps.stream();
39 long count = stream7.count();
40 System.err.println("长度为:"+count); // 长度为:3
41 //TODO 最大最小就不测试了,自己可以试试

还有功能比较强大的两个终止操作 reduce和collect 

reduce操作: reduce:(T identity,BinaryOperator)/reduce(BinaryOperator)-可以将流中元素反复结合起来,得到一个
 1 /**
 2 * reduce :规约操作
 3 * 计算和
 4 * 计算结果作为x,再从数组中取出新值作为y,进行下一步计算
 5 * 结果在加上0 是最后的结果
 6 */
 7 List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
 8 Integer count2 = list.stream().reduce(0, (x, y) -> x + y);
 9 System.out.println(count2);
10  
11 Stream<Map<String, Object>> stream8 = maps.stream();
12 //计算总年龄 也可以是浮点型数据 将Integer 换成Double就ok
13 Optional<Integer> op = stream8.map(m -> Integer.valueOf(String.valueOf(m.get("age"))))
14 .reduce(Integer::sum);
15 System.err.println(op.get()); //54    
collect操作:Collect-将流转换为其他形式,接收一个Collection接口的实现,用于给Stream中元素做汇总的方法,转换为一个新的集合或者对象
 1 /**
 2 * collect操作:Collect-将流转换为其他形式,
 3 * 接收一个Collection接口的实现,用于给Stream中元素做汇总的方法
 4 * Collectors.toList()/toSet()
 5 */
 6 Set<Integer> ageList = list.stream().collect(Collectors.toSet());
 7 ageList.stream().forEach(System.out::println);
 8 //取名字,封装成hashset
 9 HashSet<Integer> hs = list.stream()
10 .collect(Collectors.toCollection(HashSet::new));
11 System.err.println(hs.toString());

函数式接口:

        函数式接口的提出是为了给Lambda表达式的使用提供更好的支持。
什么是函数式接口?
        简单来说就是只定义了一个抽象方法的接口(Object类的public方法除外),就是函数式接口,并且还提供了注解:@FunctionalInterface
函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。
函数式接口可以被隐式转换为 lambda 表达式。
Lambda 表达式和方法引用(实际上也可认为是Lambda表达式)上。
如定义了一个函数式接口如下:
1 @FunctionalInterfaceinterface GreetingService
2 {
3         void sayMessage(String message);
4 }
5  
6 // 那么就可以使用Lambda表达式来表示该接口的一个实现(注:JAVA 8 之前一般是用匿名类实现的):
7 GreetingService greetService1 = message -> System.out.println("Hello " + message);
常见的四大函数式接口有:
        Consumer 《T》:消费型接口,有参无返回值
        Supplier 《T》:供给型接口,无参有返回值
        Function 《T,R》:函数式接口,有参有返回值
        Predicate《T》:断言型接口,有参有返回值,返回值是boolean类型
 1 /**
 2 * @MethodName: functionInterface
 3 * @Description: 四大函数式接口练习
 4 * @param
 5 * @return
 6 * @author rongrong
 7 * @date 2019-12-23
 8 */
 9 public void functionInterface(){
10 /**
11 * 1.Consumer 《T》:消费型接口,有参无返回值
12 * 打印:
13 * 222222
14 * hello
15 */
16 changeStr("hello",(str) -> System.err.println(str));
17  
18 /**
19 * 2.Supplier 《T》:供给型接口,无参有返回值
20 * 打印:
21 * 111111
22 * str
23 */
24 String value = getValue(() -> "str");
25 System.err.println(value);
26  
27 /**
28 * 3. Function 《T,R》::函数式接口,有参有返回值
29 * 打印:
30 * 333333
31 * 20000
32 */
33 Long aLong = changeNum(100L, x -> x * 200);
34 System.err.println(aLong);
35 /**
36 * Predicate《T》: 断言型接口,有参有返回值,返回值是boolean类型
37 * 打印:
38 * true
39 */
40 boolean rongrong = changeBoolean("rongrong", x -> x.equals("rongrong"));
41 System.err.println(rongrong);
42  
43 }
44  
45 /**
46 * Consumer<T> 消费型接口
47 * @param str
48 * @param con
49 */
50 public void changeStr(String str, Consumer<String> con){
51 System.err.println("222222");
52 con.accept(str);
53 }
54  
55 /**
56 * Supplier<T> 供给型接口
57 * @param sup
58 * @return
59 */
60 public String getValue(Supplier<String> sup){
61 System.err.println("111111");
62 return sup.get();
63 }
64  
65 /**
66 * Function<T,R> 函数式接口
67 * @param num
68 * @param fun
69 * @return
70 */
71 public Long changeNum(Long num, Function<Long, Long> fun){
72 System.err.println("333333");
73 return fun.apply(num);
74 }
75  
76 /**
77 * Predicate<T> 断言型接口
78 * @param str
79 * @param pre
80 * @return
81 */
82 public boolean changeBoolean(String str, Predicate<String> pre){
83 return pre.test(str);
84 }

在四大核心函数式接口基础上,还提供了诸如BiFunction、BinaryOperation、toIntFunction等扩展的函数式接口,都是在这四种函数式接口上扩展而来的,不做赘述。

总结:函数式接口的提出是为了让我们更加方便的使用lambda表达式,不需要自己再手动创建一个函数式接口,直接拿来用就好了, 详细接口描述在下边。
 
 
方法引用:
        若lambda体中的内容有方法已经实现了,那么可以使用“方法引用”也可以理解为方法引用是lambda表达式的另外一种表现形式并且其语法比lambda表达式更加简单
(a) 方法引用
    三种表现形式:
        1. 对象:实例方法名
        2. 类::静态方法名
        3. 类::实例方法名 (lambda参数列表中第一个参数是实例方法的调用 者,第二个参数是实例方法的参数时可用)
 1 /**
 2 *注意:
 3 * 1.lambda体中调用方法的参数列表与返回值类型,要与函数式接口中抽象方法的函数列表和返回值类型保持一致!
 4 * 2.若lambda参数列表中的第一个参数是实例方法的调用者,而第二个参数是实例方法的参数时,可以使用ClassName::method
 5 * 下边写的例子 上边是不简化时的写法,下边的是对应的简化写法,就是方法引用
 6 */
 7  
 8 //100
 9 //200
10 Consumer<Integer> con = (x) -> System.out.println(x);
11 con.accept(100);
12 // 方法引用-对象::实例方法
13 Consumer<Integer> con2 = System.out::println;
14 con2.accept(200);
15  
16 // 方法引用-类名::静态方法名
17 BiFunction<Integer, Integer, Integer> biFun = (x, y) -> Integer.compare(x, y);
18 Integer apply = biFun.apply(100, 200);
19 BiFunction<Integer, Integer, Integer> biFun2 = Integer::compare;
20 Integer result = biFun2.apply(100, 200);
21 //-1:-1
22 System.err.println(apply + ":" + result);
23  
24 // 方法引用-类名::实例方法名
25 BiFunction<String, String, Boolean> fun1 = (str1, str2) -> str1.equals(str2);
26 Boolean apply1 = fun1.apply("rong", "rong");
27 BiFunction<String, String, Boolean> fun2 = String::equals;
28 Boolean result2 = fun2.apply("hello", "world");
29 //true:false
30 System.out.println(apply1 + ":" + result2);
(b)构造器引用 
        格式:ClassName::new
 1 // 构造方法引用 类名::new
 2 Supplier<String> sup = () -> new String();
 3 System.out.println(sup.get());
 4 Supplier<String> sup2 = String::new;
 5 System.out.println(sup2.get());
 6  
 7 // 构造方法引用 类名::new (带一个参数)
 8 //x 代表是传进去的参数,也就是泛型中的Integer类型
 9 //new String(...) 代表泛型中的String类型
10 Function<Integer, String> fun = x -> new String(String.valueOf(x));
11 System.err.println(fun.apply(100));
12 Function<String, String> fun3 = String::new;
13 System.out.println(fun3.apply("100"));
(c)数组引用
格式:Type[]::new
1 // 数组引用
2 Function<Integer, String[]> arrayFun = (x) -> new String[x];
3 Function<Integer, String[]> arrayFun2 = String[]::new;
4 //给String数组设置了两个长度。但是值是null
5 String[] strArray = arrayFun2.apply(2);
6 Arrays.stream(strArray).forEach(System.out::println);
 
序号
接口 & 描述
1
BiConsumer<T,U>
代表了一个接受两个输入参数的操作,并且不返回任何结果
2
BiFunction<T,U,R>
代表了一个接受两个输入参数的方法,并且返回一个结果
3
BinaryOperator<T>
代表了一个作用于于两个同类型操作符的操作,并且返回了操作符同类型的结果
4
BiPredicate<T,U>
代表了一个两个参数的boolean值方法
5
BooleanSupplier
代表了boolean值结果的提供方
6
Consumer<T>
代表了接受一个输入参数并且无返回的操作
7
DoubleBinaryOperator
代表了作用于两个double值操作符的操作,并且返回了一个double值的结果。
8
DoubleConsumer
代表一个接受double值参数的操作,并且不返回结果。
9
DoubleFunction<R>
代表接受一个double值参数的方法,并且返回结果
10
DoublePredicate
代表一个拥有double值参数的boolean值方法
11
DoubleSupplier
代表一个double值结构的提供方
12
DoubleToIntFunction
接受一个double类型输入,返回一个int类型结果。
13
DoubleToLongFunction
接受一个double类型输入,返回一个long类型结果
14
DoubleUnaryOperator
接受一个参数同为类型double,返回值类型也为double 。
15
Function<T,R>
接受一个输入参数,返回一个结果。
16
IntBinaryOperator
接受两个参数同为类型int,返回值类型也为int 。
17
IntConsumer
接受一个int类型的输入参数,无返回值 。
18
IntFunction<R>
接受一个int类型输入参数,返回一个结果 。
19
IntPredicate
:接受一个int输入参数,返回一个布尔值的结果。
20
IntSupplier
无参数,返回一个int类型结果。
21
IntToDoubleFunction
接受一个int类型输入,返回一个double类型结果 。
22
IntToLongFunction
接受一个int类型输入,返回一个long类型结果。
23
IntUnaryOperator
接受一个参数同为类型int,返回值类型也为int 。
24
LongBinaryOperator
接受两个参数同为类型long,返回值类型也为long。
25
LongConsumer
接受一个long类型的输入参数,无返回值。
26
LongFunction<R>
接受一个long类型输入参数,返回一个结果。
27
LongPredicate
R接受一个long输入参数,返回一个布尔值类型结果。
28
LongSupplier
无参数,返回一个结果long类型的值。
29
LongToDoubleFunction
接受一个long类型输入,返回一个double类型结果。
30
LongToIntFunction
接受一个long类型输入,返回一个int类型结果。
31
LongUnaryOperator
接受一个参数同为类型long,返回值类型也为long。
32
ObjDoubleConsumer<T>
接受一个object类型和一个double类型的输入参数,无返回值。
33
ObjIntConsumer<T>
接受一个object类型和一个int类型的输入参数,无返回值。
34
ObjLongConsumer<T>
接受一个object类型和一个long类型的输入参数,无返回值。
35
Predicate<T>
接受一个输入参数,返回一个布尔值结果。
36
Supplier<T>
无参数,返回一个结果。
37
ToDoubleBiFunction<T,U>
接受两个输入参数,返回一个double类型结果
38
ToDoubleFunction<T>
接受一个输入参数,返回一个double类型结果
39
ToIntBiFunction<T,U>
接受两个输入参数,返回一个int类型结果。
40
ToIntFunction<T>
接受一个输入参数,返回一个int类型结果。
41
ToLongBiFunction<T,U>
接受两个输入参数,返回一个long类型结果。
42
ToLongFunction<T>
接受一个输入参数,返回一个long类型结果。
43
UnaryOperator<T>
接受一个参数为类型T,返回值类型也为T。
 
 
 
 
 
 
 
 
 
 
 
 

Guess you like

Origin www.cnblogs.com/rrong/p/12088903.html