JDK8新特性笔记(六):集合框架 流操作②

JDK8新特性笔记(六):集合框架 流操作②

paralleStream并行流

  • 为什么会有并行流

集合做重复的操作,如果使用串行执行会相当耗时,因此一般会采用多线程来加快,java8的paralleStream用fork/join框架提供并发执行能力

原理:线程池维护一个线程队列;可以分割任务,将父任务拆分成子任务,完全贴合分治思想。

stream串行流和parallelStream并行流的区别

public static void main(String[] args) {
    // stream串行流
    List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    numbers.stream().forEach(System.out::println);
    System.out.println("-------------------分割线----------------------");
    // parallelStream并行流
    numbers.parallelStream().forEach(System.out::println);
}

运行结果:
1
2
3
4
5
6
7
8
9
10
-------------------分割线----------------------
7
6
8
3
5
4
1
10
9
2

从结果可以看出并行流的输出是乱序的和多线程打印是一样的效果,并行流本身就是使用线程池多线程处理。

问题:

  • parallelStream并行流是不是一定比Stream流快?

    不一定,数据量少的情况下可能串行更快,ForkJoin会消耗性能

  • 多数情况下并行比串行快,是不是可以都用并行?

    不行,部分情况会有线程安全问题,parallelStream里面使用的外部变量或者集合一定要用线程安全的,不然会引发多线程安全问题。

引发越界异常的例子:

for (int i=0;i<10;i++){
    ArrayList arrayList = new ArrayList()
    IntStream.range(0,100).parallel().forEach(arrayList::add);
    System.out.println(arrayList.size());
}

需要将ArrayList换成线程安全的copyOnWriteArrayList,下面是两集合源码中add方法的对比

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k2QzUlo8-1603072109024)(C:\Users\user\Desktop\JDK8新特性笔记\ArrayList和CopyOnWriteArrayList源码add方法对比.png)]

可以看到CopyOnWriteArrayList加了可重入锁ReentrantLock,所以改成一下代码

for (int i=0;i<10;i++){
    CopyOnWriteArrayList copyOnWriteArrayList = new CopyOnWriteArrayList();
    IntStream.range(0,100).parallel().forEach(copyOnWriteArrayList::add);
    System.out.println(copyOnWriteArrayList.size());
}

1.reduce操作

根据一定的规则将Stream中的元素进行计算后返回一个唯一的值

常用方法一:Optional reduce(BinaryOperator accumulator); 计算累加器

例子:第一个元素和第二个元素相加,结果再和第三个元素相加,直到全部相加完成

Integer integer = Stream.of(1, 2, 3, 4, 5).reduce((num1, num2) -> num1 + num2).get();
System.out.println(integer);

运行结果:
    15

常用方法二:T reduce (T identity,BinaryOperator accumulator); 设置初始值的累加

例子:100作为初始值,然后和第一个元素相加,结果在合第二个元素相加,直到全部相加完成(相当于多了一个基础元素加了进去)

Integer sum2 = Stream.of(1, 2, 3, 4, 5).reduce(100, (num1, num2) -> num1 + num2);
System.out.println(sum2);

运行结果:
	115

练习例子:流中传入一些数,取最大值

Integer max1 = Stream.of(1, 21, 424, 233, 124, 3525, 21412).reduce((num1, num2) -> num1 > num2 ? num1 : num2)
System.out.println(max1);

运行结果:
    21412

2.List的foreach遍历操作

以前的方式:for或者迭代器Iterator

用foreach遍历

List<String> stringList = Arrays.asList("kobe", "wade", "o'neal", "tracy", "gogogo", "believe");
stringList.forEach(obj->{
    System.out.println(obj);
});

运行结果:
    kobe
	wade
	o'neal
	tracy
	gogogo
	believe

注意事项:

  • 不能修改包含外部的变量的值 (比如foreach之前有个int gender = 0 ,在foreach中不能讲gender值置为1或改变)
  • 不能用break或者return或者continue等关键词结束或者跳过循环
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值