关于java8:java8实战学习

3次阅读

共计 6478 个字符,预计需要花费 17 分钟才能阅读完成。

[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: 2047843427
filter: 2047843427
peek2:2047843427
peek: -1210662664
filter: -1210662664
peek: 835825054
filter: 835825054
peek2:835825054
peek: 2068471207
filter: 2068471207
peek2:2068471207
peek: -1139851578
filter: -1139851578
peek: -885776051
filter: -885776051
peek: 481902862
filter: 481902862
peek2:481902862
peek: 684461691
filter: 684461691
peek2:684461691
peek: 1417449012
filter: 1417449012
peek2:1417449012
peek: -40633821
filter: -40633821

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

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

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

(6) 并行操作: parallel()

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

@Test
public 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: -1644694686
ForkJoinPool.commonPool-worker-1 filter: -1644694686
ForkJoinPool.commonPool-worker-1 peek: 1524371421
ForkJoinPool.commonPool-worker-1 filter: 1524371421
ForkJoinPool.commonPool-worker-1 peek: -1937453784
ForkJoinPool.commonPool-worker-1 filter: -1937453784
ForkJoinPool.commonPool-worker-1 peek: 991114309
ForkJoinPool.commonPool-worker-1 filter: 991114309
ForkJoinPool.commonPool-worker-1 peek: -109655961
ForkJoinPool.commonPool-worker-1 filter: -109655961
ForkJoinPool.commonPool-worker-1 peek: 878490064
ForkJoinPool.commonPool-worker-1 filter: 878490064
ForkJoinPool.commonPool-worker-1 peek: 2031919515
ForkJoinPool.commonPool-worker-1 filter: 2031919515
ForkJoinPool.commonPool-worker-1 peek: -1855129379
ForkJoinPool.commonPool-worker-1 filter: -1855129379
ForkJoinPool.commonPool-worker-1 peek: 1897985020
ForkJoinPool.commonPool-worker-1 filter: 1897985020
ForkJoinPool.commonPool-worker-1 peek: 352116584
ForkJoinPool.commonPool-worker-1 filter: 352116584
main 排序:991114309, 1524371421
main 排序:878490064, 991114309
main 排序:2031919515, 878490064
main 排序:2031919515, 991114309
main 排序:2031919515, 1524371421
main 排序:1897985020, 1524371421
main 排序:1897985020, 2031919515
main 排序:352116584, 1524371421
main 排序:352116584, 991114309
main 排序:352116584, 878490064
ForkJoinPool.commonPool-worker-6 peek2:991114309
main peek2:1524371421
ForkJoinPool.commonPool-worker-3 peek2:352116584
ForkJoinPool.commonPool-worker-2 peek2:2031919515
ForkJoinPool.commonPool-worker-7 peek2:1897985020
ForkJoinPool.commonPool-worker-4 peek2:878490064
6

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

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

3.7 小结链式调用原理:

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

3.8 小结 2

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