[toc]


java8实战学习

1. lambda表达式

1.1 什么是lambda表达式

1.2 什么样的场景能应用lambda表达式

1.3 lambda表达式实现一个接口的四种写法

2. 函数式编程

2.1 什么是函数式编程

2.2 什么是命令式编程

2.3 什么是函数式接口 FunctionalInterface

2.4 什么是 default 办法

2.5 default办法的意义

2.6 java8内置的罕用函数式接口

(1). Predicate<T>

断言 -> 输出T, 输入 boolean

(2). Consumer<T>

生产一个输出 -> 输出T, 不输入(void)

(3). Supplier<T>

生产一个输入 -> 不输出, 输入T

(4). Function<T, R>

输出T, 输入R的函数

(5). UnaryOperator<T>

一元函数: 输出1个输入 1个: 类型都是T

(6). BinaryOperatior<T>

二元函数: 输出2个输入1个: 类型都是T

(7). BiFunction<T, U, R>

输出两个输入一个: 输出 T, U 输入 R, 罕用于 reduce/sort等操作,

2.7 办法援用

(1). 静态方法的办法援用
(2). 实例办法的办法援用
(3). 构造方法的办法援用

2.8. 变量援用和隐式final

为何外部类应用内部变量要是final的

3. stream流式编程

3.1. 内部迭代和外部迭代

(1). 什么是内部迭代
(2). 什么是外部迭代

3.2. 两头操作/终止操作/惰性求值

(1). 什么是两头操作?

返回还是流stream的操作, 就是两头操作, 例如 map操作

map
flatMap
distinct
limit
skip
filter
peek
sorted
(1.1) 有状态操作

有前后程序依赖关系的操作, 比方
distinct(前后不能雷同)
sorted(前后程序要求)
limit/skip(截取后面的/跳过后面的)

(1.2) 无状态操作

无前后依赖关系的操作:
map/mapToInt/flatMap/flatMapToInt
filter
peek

(2). 什么是终止操作?

返回一个后果的(求和/汇总)等, 例如 sum/max/min/avg等

forEach
collect
reduce
toArray
min/max/count
findAny
findFirst
allMatch
anyMatch
noneMatch
(1.1) 短路操作

findFirst
findAny
allMatch
anyMatch
noneMatch

(1.2) 非短路操作

forEach
forEachOrdered 并行流中保障程序的
collect
toArray
reduce 输出: BinaryOperator<T>
min
max
count

(3). 什么是惰性求值?

如果没有终止操作, 两头的操作动作都不会理论执行, 这就是惰性求值;

3.3 stream流的创立

(1) 汇合

collection.stream
collection.parallelStream

(2) 数组

array.stream
Stream.of

(3). 数字
IntStream

IntStream.range
IntStream.rangeClosed

LongStream

LongStream.range
LongStream.rangeClosed

Random

Random.longs
Random.ints
Random.doubles

(4).本人创立

Stream.generate
Stream.iterate

3.4 并行流

(1). parallel()
(2). 并行流默认应用的线程池

ForkJoinPool.commonPool

(3). 自定义线程池

如何自定义线程池, 并应用到流并行时?

3.5 收集器 collect

(1). 收集对象的属性列表为一个新汇合

collect(Collectors.toList())

(2). 统计信息汇总

IntSummaryStatistics ageSumStats = students.stream().collect(Collectors.summarizingInt(Student::getAge))

(3). 分块:应用断言(一分为二)

Map<Boolean, List<Student>> genders = students.stream().collect(Collectors.partitioningBy(s->s.getGender() == Gender.MALE))

(4). 分组:应用属性(一分为N, 相似sql groupby)

Map<Grade, List<Student>> grades = students.stream().collect(Collectors.groupingBy(Student::getGrade))

(5). 分组并汇总计数

Map<Grade, Long> gradeCount = students.stream().collect(Collectors.groupingBy(Student::getGrade, Collectors.counting()));
counting()能够替换为同类的max/min/avg等

(6). 小结
Collectors.toList()
Collectors.toCollection()
Collectors.summarizingInt(x)
Collectors.partitioningBy(x)
Collectors.groupingBy(x)
Collectors.counting()

3.6 stream运行机制

(1). 链式调用

所有操作链式调用, 1个元素只迭代一次;

(2). 属性sourceStage

每一个两头操作返回一个新的stream流, 流内有一个属性: sourceStage; 指向同一个中央: 即 链表的头 Head

(3). Head -> nextStage -> nextStage -> null

stream接口的实现类
java.util.stream.AbstractPipeline
java.util.stream.ReferencePipeline
属性: sourceStage --> ReferencePipeline$Head

(4). 无状态操作运行机制

齐全链式调用: s1.a操作完->s1.b

(5). 有状态操作运行机制
public void testStream() {    Random r = new Random();    Stream.generate(() -> r.nextInt()).limit(500)            .peek(s -> System.out.println("peek: " + s)) // 1            .filter(s -> {  // 2                System.out.println("filter: " + s);                return s > 1000000;            })            .sorted((i1, i2) -> { // 3.                System.out.println("排序:" + i1 + ", " + i2);                return i1.compareTo(i2);            })            .peek(s -> System.out.println("peek2:" + s)) //4.            .count(); }

1,2 都是无状态操作; 3是有状态操作; 4是无状态操作
3的有状态操作会截断 1, 2的无状态操作;
原本是1, 2的链式调用: s1.a->s1.b->s1.c 当初会变成: s1.a() ->s2.a() -> s1.b() ->s2.b()
output: 无sorted: 能够看到纯无状态操作是纯链式: peek->filter->peek2

peek: 2047843427filter: 2047843427peek2:2047843427peek: -1210662664filter: -1210662664peek: 835825054filter: 835825054peek2:835825054peek: 2068471207filter: 2068471207peek2:2068471207peek: -1139851578filter: -1139851578peek: -885776051filter: -885776051peek: 481902862filter: 481902862peek2:481902862peek: 684461691filter: 684461691peek2:684461691peek: 1417449012filter: 1417449012peek2:1417449012peek: -40633821filter: -40633821

output: 有sorted: 能够看到前面的无状态操作peek2被有状态的sorted打断, 变成: peek->filter... peek->filter 排序all, peek2 all

peek: -607778068filter: -607778068peek: 50926402filter: 50926402peek: -774310924filter: -774310924peek: 342023904filter: 342023904peek: 26606322filter: 26606322peek: 693727663filter: 693727663peek: -334751306filter: -334751306peek: -960784614filter: -960784614peek: 522967780filter: 522967780peek: -2144851449filter: -2144851449排序:342023904, 50926402排序:26606322, 342023904排序:26606322, 342023904排序:26606322, 50926402排序:693727663, 50926402排序:693727663, 342023904排序:522967780, 342023904排序:522967780, 693727663peek2:26606322peek2:50926402peek2:342023904peek2:522967780peek2:693727663

1, 2还是链式调用; 两头的3执行完后, 隔断了4, 所以4不会和1,2承续链式调用, 而是独自执行;

(6) 并行操作: parallel()

在4后加5: parallel():
sorted() 有状态操作不会并行; 1,2,4都会应用 ForkJoinPool线程池并行执行:

@Testpublic void testStream() {    Random r = new Random();    long count = Stream.generate(() -> r.nextInt()).limit(10)            .peek(s -> System.out.println(Thread.currentThread().getName() + " peek: " + s)) // 1            .filter(s -> {  // 2                System.out.println(Thread.currentThread().getName() + " filter: " + s);                return s > 1000000;            })            .sorted((i1, i2) -> { // 3.                System.out.println(Thread.currentThread().getName() + " 排序:" + i1 + ", " + i2);                return i1.compareTo(i2);            })            .peek(s -> System.out.println(Thread.currentThread().getName() + " peek2:" + s)) //4.            .parallel()            .count();    System.out.println(count);}
ForkJoinPool.commonPool-worker-1 peek: -1644694686ForkJoinPool.commonPool-worker-1 filter: -1644694686ForkJoinPool.commonPool-worker-1 peek: 1524371421ForkJoinPool.commonPool-worker-1 filter: 1524371421ForkJoinPool.commonPool-worker-1 peek: -1937453784ForkJoinPool.commonPool-worker-1 filter: -1937453784ForkJoinPool.commonPool-worker-1 peek: 991114309ForkJoinPool.commonPool-worker-1 filter: 991114309ForkJoinPool.commonPool-worker-1 peek: -109655961ForkJoinPool.commonPool-worker-1 filter: -109655961ForkJoinPool.commonPool-worker-1 peek: 878490064ForkJoinPool.commonPool-worker-1 filter: 878490064ForkJoinPool.commonPool-worker-1 peek: 2031919515ForkJoinPool.commonPool-worker-1 filter: 2031919515ForkJoinPool.commonPool-worker-1 peek: -1855129379ForkJoinPool.commonPool-worker-1 filter: -1855129379ForkJoinPool.commonPool-worker-1 peek: 1897985020ForkJoinPool.commonPool-worker-1 filter: 1897985020ForkJoinPool.commonPool-worker-1 peek: 352116584ForkJoinPool.commonPool-worker-1 filter: 352116584main 排序:991114309, 1524371421main 排序:878490064, 991114309main 排序:2031919515, 878490064main 排序:2031919515, 991114309main 排序:2031919515, 1524371421main 排序:1897985020, 1524371421main 排序:1897985020, 2031919515main 排序:352116584, 1524371421main 排序:352116584, 991114309main 排序:352116584, 878490064ForkJoinPool.commonPool-worker-6 peek2:991114309main peek2:1524371421ForkJoinPool.commonPool-worker-3 peek2:352116584ForkJoinPool.commonPool-worker-2 peek2:2031919515ForkJoinPool.commonPool-worker-7 peek2:1897985020ForkJoinPool.commonPool-worker-4 peek2:8784900646

论断: 有状态的并行操作"不肯定"并行 为啥是"不肯定"?

因为官网并未明说, 然而察看下来, 是非并行的!

3.7 小结链式调用原理:

  1. stream链式调用原理: ReferencePipeline
  2. 每个两头操作产生一个流(新的流)
  3. 新流和原流的关系: 新流内有个sourceStage->指向原流的Head节点(ReferencePipeline$Head)
  4. 链式调用的保护: ReferencePipeline中的 nextStage -> nextStage -> null来保护链;

3.8 小结2

  1. 有状态操作 毁坏链式调用
  2. 并行操作中有状态操作不肯定并行, 如排序!