dev

Java Basics - Java 8

/wrote/note-bak/dev/java/java8/

Lambda Experssion

Lambda表达式是一种匿名函数,‌也称为闭包。‌它可以将代码像数据一样进行传递。

使用Lambda表达式可以写出更简洁、更灵活的代码

Arrays.sort(input[], (int x, int y) -> x - y);

Functional Interface

Consumer

消费者接口,直接操作 Object ,没有输出。

Abstract Methods: void accept(T t)

常用于 stream.forEach(s -> System.out.println(s)), forEach 里面的就是一个 Consumer,这里用于打印流里面的值。

Supplier

提供者接口,不接受入参,输出为一个 Object。

Abstract Methods: T get()

常用于 stream.filter(i -> i > 10).findFirst().orElseGet(-1),orElseGet 里面就是一个 Supplier,这里用于返回一个默认值。

Predicate

判断接口,传入一个 Object ,然后做一些判断,输出 true / false 。

Abstract Methods: boolean test(T t)

常用于 stream.filter(i -> i > 10).collect(Collectors.toList());,filter 里面就是一个 Predicate,这里用于找出所有大于10的数。

Function

函数接口,做转换,传入一个类型为 T 的对象,输出一个类型为 R 的对象。

Abstract Methods: R apply(T t)

常用于 stream.map(s -> s.length);,map 里面就是一个 Function,这里是把统计流里面的字符串的长度。

https://www.cnblogs.com/SIHAIloveYAN/p/11288064.html

Method Reference

方法引用:把已经定义好的有名字的方法,当作Lambda Expression来使用。

它的常用语法为:className::methodName

Optional

Optional是一个容器类。将Object放到Optional中,从而可以使用容器的一些特性,比如链式编程(Stream)等。

一个常用的场景是使用 ofNullable 方法,保证不会NPE。

Stream

What is Stream

Stream 是对 Collection 功能的增强,它专注于对集合进行各种便利高效的聚合操作(aggregate operation),或者大批量数据操作(bulk data operation)。

Stream 就像一个高级版本的Iterator,用户指明想要进行的操作,它会在内部隐式地遍历,做出相应的数据转换。

Stream Characteristics

  1. stream不存储数据
  2. stream不改变源数据
  3. stream的延迟执行特性

Stream Features

  • Stream API借助于Lambda Exrepssion,极大的提高编程效率和程序可读性。
  • 它提供串行并行两种模式进行操作,并发模式能够充分利用多核处理器的优势,使用fork/join并行方式来拆分任务和加速处理过程。

Stream Composition

一般使用Stream的时候,有三个步骤:

  • 获取一个数据源(产生)
  • 数据转换(中间操作)
  • 执行操作获取想要的结果(结束操作) 每次转换完成后,返回一个新的Stream对象,可以对其继续进行其他转换。这就允许Stream操作可以像链条一样排列,变成一个管道。

Stream Data Sources

Collections, Arrays, or I/O resources

  • Collection.stream()
  • Collection.parallelStream()
  • Arrays.stream(T array)
  • Stream.of(T… values) 构造流的几种常见方法
// 1. Individual values
Stream stream1 = Stream.of("a", "b", "c");
// 2. Arrays
String [] strArray = new String[] {"a", "b", "c"};
Stream stream2 = Stream.of(strArray);
Stream stream3 = Arrays.stream(strArray);
// 3. Collections
List<String> list = Arrays.asList(strArray);
Stream stream4 = list.stream();

流转换为其它数据结构

// 1. Array
String[] strArray1 = stream.toArray(String[]::new);
// 2. Collection
List<String> list1 = stream.collect(Collectors.toList());
List<String> list2 = stream.collect(Collectors.toCollection(ArrayList::new));
Set set1 = stream.collect(Collectors.toSet());
Stack stack1 = stream.collect(Collectors.toCollection(Stack::new));
// 3. String
String str = stream.collect(Collectors.joining()).toString();

Stream Operations

流的操作类型分为两种:中间操作,结束操作。

  • Intermediate: 一个流可以后面跟随零个或多个 intermediate 操作。其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用。这类操作仅仅调用到这类方法,并没有真正开始流的遍历。

  • map: 转换流,将一种类型的流转换为另外一种流

  • flatMap: 转换合并流,将一个或多个流合并成一个新流

  • filter: 过滤流,过滤流中的元素,返回一个符合条件的Stream

  • distinct: 去重

  • sorted: 排序

  • peek: 查看

  • limit: 取前几个

  • skip: 跳过前几个

  • Terminal:一个流只能有一个terminal操作,当这个操作执行后,流就被使用”光”了,无法再被操作。Terminal操作的执行,才会真正开始流的遍历,并且会生成一个结果,或者一个side effect。

  • forEach: 循环操作Stream中数据

  • toArray: 返回流中元素对应的数组对象

  • reduce: 聚合操作,用来做统计

  • collect: 聚合操作,封装目标数据

  • min, max, count: 聚合操作,最小值,最大值,总数量

  • anyMatch: 短路操作,有一个符合条件返回true

  • allMatch / noneMatch: 全部符合,或者全部不符合时返回 true

  • findFirst / findAny: 短路操作,获取第一个,或者任意一个元素

  • iterator

Common Use Cases

所有的单词转换为大写

List<String> output = wordList.stream()
    .map(String::toUpperCase)
    .collect(Collectors.toList());

过滤数组,只留下偶数

Integer[] sixNums = {1, 2, 3, 4, 5, 6};
Integer[] evens = Stream.of(sixNums)
    .filter(n -> n%2 == 0)
    .toArray(Integer[]::new);

对一个人员集合遍历,找出男性并打印姓名

roster.stream()
 .filter(p -> p.getGender() == Person.Sex.MALE)
 .forEach(p -> System.out.println(p.getName()));

找出最长一行的长度

BufferedReader br = new BufferedReader(new FileReader("c:\\SUService.log"));
int longest = br.lines()
    .mapToInt(String::length)
    .max()
    .getAsInt();
br.close();
System.out.println(longest);

Reference