精华内容
下载资源
问答
  • 串行流和并行流

    2021-07-16 00:07:24
    Stream是java支持的一种流水线式处理数据的方式,也是jdk8的一种特性。 Collection体系下有两个方法...使用场景:数据量大,且业务复杂,用并行,数据量少且业务简单,用串行。 public class StreamTest { public s

    Stream流是java支持的一种流水线式处理数据的方式,也是jdk8的一种特性。

    Collection体系下有两个方法可以获取获取Stream(直接通过集合对象调用方法获取即可)

    1. stream() − 为集合创建串行流。【线程是安全的】
    2. parallelStream() − 为集合创建并行流。【底层是多线程处理,线程不安全,可以设置线程。可以解决线程安全】

    使用场景:数据量大,且业务复杂,用并行,数据量少且业务简单,用串行。

    public class StreamTest {
        public static void main(String[] args) {
            List<Integer> list = Arrays.asList(4, 3, 4, 5, 2, 1);
            final Stream<Integer> stream = list.stream();//获取串行流对象
            //将流中元素自然排序
    		//stream.sorted().forEach(System.out::println);
            //去重
            stream
                    .distinct()//将流中元素去重
                    .sorted()//将流中元素排序
                    .forEach(System.out::println);
            //过滤    //过滤掉大于3的所有元素
            //stream.filter(t -> t > 3).forEach(System.out::println);
            //将stream流对象转换为List对象
            //final List<Integer> collect = stream.collect(Collectors.toList());
            //System.out.println(collect);
            //合并,拼接
            final List<String> list1 = Arrays.asList("小易", "boyas", "星河", "angel651");
            //调用parallelStream方法获取并行流
            final Stream<String> parallelStream = list1.parallelStream();
            //将parallelStream中元素进行拼接【元素类型必须是string类型】
            final String collect1 = parallelStream.collect(Collectors.joining("=>"));
            System.out.println(collect1);
        }
    }
    

    在这里插入图片描述

    展开全文
  • 前序 JDK1.8—函数式编程(lambda、方法引用、Stream) Stream 串行流 一、执行机制 基于pipeline(管道) ...并行流 API:parallelStream() 利用多线程去处理一批数据,各个线程处理完的结果最后 ...

    前序

    JDK1.8—函数式编程(lambda、方法引用、Stream)

    Stream流

    串行流

    一、执行机制

    基于pipeline(管道)
    在这里插入图片描述

    二、流的特性

    1. stream不存储数据
    2. stream不改变数据源
    3. stream不可重复使用
    4. stream串行执行
    5. 上个节点会影响下个节点

    三、流的节点

    中间节点(懒加载): filter、distinct
    结束节点:toArray、foreach

    并行流

    API:parallelStream()
    利用多线程去处理一批数据,各个线程处理完的结果最后

    展开全文
  • 自己跑了一下的性能,仅仅测试了串行流stream、并行流parallelStream以及for-loop。 例子虽然用得不好,仅仅是为了计算double的总和,由于有可能需求是金融类精度,所以使用了自己的工具类NumeralOperationKit...
    public void testParallelStream() {
        List<Double> doubleList = Stream.generate(Math::random).limit(1000000).collect(Collectors.toList());
    
        long time1 = System.currentTimeMillis();
        double sum = doubleList.parallelStream().collect(Collectors.summingDouble(d -> d));
        System.out.println(sum);
        long time2 = System.currentTimeMillis();
        System.out.println(time2 - time1);
    		
        time1 = System.currentTimeMillis();
        double sum2 = doubleList.parallelStream().reduce(NumeralOperationKit::add).get();
        System.out.println(sum2);
        time2 = System.currentTimeMillis();
        System.out.println(time2 - time1);
    
        sum2 = 0;
        time1 = System.currentTimeMillis();
        sum2 = doubleList.stream().reduce(NumeralOperationKit::add).get();
        System.out.println(sum2);
        time2 = System.currentTimeMillis();
        System.out.println(time2 - time1);
    		
        time2 = System.currentTimeMillis();
        double sum3 = 0;
        for (double tmp : doubleList) {
    	sum3 = NumeralOperationKit.add(sum3, tmp);
        }
        System.out.println(sum3);
        long time3 = System.currentTimeMillis();
        System.out.println(time3 - time2);
    }

    直接上代码,不信网上的什么妖魔鬼怪。自己跑了一下流的性能,仅仅测试了串行流stream、并行流parallelStream以及for-loop。

    例子虽然用得不好,仅仅是为了计算double的总和,由于有可能需求是金融类精度,所以使用了自己的工具类NumeralOperationKit,其中add是由BigDecimal计算得出的。

    有很多很多的文章在说流的性能比传统的遍历慢,我用的测试工具:i5配置的MacMini。先上结果:

    result: 
    500026.61796251085
    69
    500026.6179625099
    2443
    500026.61796252226
    2221
    500026.61796252226
    1912

    甭管结果,先看性能,可以说并行流是飞起来了。

    从第一个和第二个结果来看,reduce就是个“终结者”,因为stream本身是具有“懒”特性(可以百度一下)

    reduce一点都不懒,直接开始计算,以至于效率有点低下(这里很难说明白为啥会慢这么多,只能再分析一下源码,看一下jvm)。结果是肯定有差异的、不正确的,因为并行流不是线程安全的啊。

    通过第三个结果能看出来,结果是正确的,但由于reduce,性能感觉一般,不过其实这里还有一个Collectors.reducing的方法,效率一样一样的。

    for-loop不想多说,在数据量比较大的时候性能才会和stream差不多。

    但开发效率的话,肯定stream快一丢丢。譬如组装一个比较复杂的三维map啊啥的、二维数组啊啥的、还能扁平。

    最后再来一组数据让你们看看并行流真正的实力。

    10000000 random double
    result: 
    4999455.0039662095
    70
    4999455.003966218
    13694
    4999455.003967396
    19508
    4999455.003967396
    19258

     

    热爱生活,热爱代码。

    展开全文
  • JDK8 | 串行流 Stream 与并行流 parallelStream 一、串行 Stream 1.获取串行流的两种方式: 所有的 Collection 集合都可以通过 stream 默认方法获取:list.stream(); Stream 接口的静态方法 of 可以获取数组...

    JDK8 | 串行流 Stream 与并行流 parallelStream


    一、串行 Stream 流
    1.获取串行流的两种方式:
    • 所有的 Collection 集合都可以通过 stream 默认方法获取流:list.stream();
    • Stream 接口的静态方法 of 可以获取数组对应的流:Stream.of(6,1,5,4,3);
    // 集合获取流
    // Collection接口中的方法: default Stream<E> stream() 获取流
    List<String> list = new ArrayList<>();
    Stream<String> stream1 = list.stream();
    
    Set<String> set = new HashSet<>();
    Stream<String> stream2 = set.stream();
    
    Vector<String> vector = new Vector<>();
    Stream<String> stream3 = vector.stream();
    
    // Map获取流
    Map<String, String> map = new HashMap<>();
    Stream<String> keyStream = map.keySet().stream();
    Stream<String> valueStream = map.values().stream();
    Stream<Map.Entry<String, String>> entryStream = map.entrySet().stream();
    

    2.Stream常用方法,其他方法大家自行查阅官方API文档

    在这里插入图片描述


    3.Stream注意事项(重要)
    1. Stream只能操作一次
    2. Stream方法返回的是新的流
    3. Stream不调用终结方法,中间的操作不会执行

    二、并行 parallelStream 流
    1.获取并行流的两种方式:
    • 直接获取并行的流:
    • 将串行流转成并行流:
    // 直接获取并行的流
    ArrayList<Integer> list = new ArrayList<>();
    Stream<Integer> stream = list.parallelStream();
    // 将串行流转成并行流
    ArrayList<Integer> list2 = new ArrayList<>();
    Stream<Integer> stream = list2.stream().parallel();
    

    2.并行流的效率是要比串行流要高,底层使用Fork/Join框架进行处理,具体自行百度

    测试效率

    public class Demo {
    	private static long times = 50000000000L;
    	private long start;
    	
    	@Before
    	public void init() {
    		start = System.currentTimeMillis();
    	} 
    
    	@After
    	public void destory() {
    		long end = System.currentTimeMillis();
    		System.out.println("消耗时间: " + (end - start));
    	}
    	
    	// 测试效率,parallelStream 122
    	@Test
    	public void parallelStream() {
    		System.out.println("serialStream");
    		LongStream.rangeClosed(0, times).parallel().reduce(0, Long::sum);
    	} 
    	
    	// 测试效率,普通Stream 354
    	@Test
    	public void serialStream() {
    		System.out.println("serialStream");
    		LongStream.rangeClosed(0, times).reduce(0, Long::sum);
    	}
    }
    

    3.解决并行流的线程安全问题:多线程下,使用并行流会有线程安全的问题

    根据需要进行不同的处理:

    • 使用同步代码块 synchronized (比如使用forEach循环处理时)
    • 使用线程安全的集合 Vector、Collections.synchronizedList(list)
    • 调用Stream流的 collect/toArray 方法

    4.注意事项
    1. parallelStream是线程不安全的
    2. parallelStream适用的场景是CPU密集型的,只是做到别浪费CPU,假如本身电脑CPU的负载很大,那还到处用并行流,那并不能起到作用
    3. I/O密集型 磁盘I/O、网络I/O都属于I/O操作,这部分操作是较少消耗CPU资源,一般并行流中不适用于I/O密集型的操作,就比如使用并流行进行大批量的消息推送,涉及到了大量I/O,使用并行流反而慢了很多
    4. 在使用并行流的时候是无法保证元素的顺序的,也就是即使你用了同步集合也只能保证元素都正确但无法保证其中的顺序

    展开全文
  • 而在Java8中,对于并行流和串行流同样做了大量的优化。对于并行流和串行流的知识,也是在面试过程中,经常被问到的知识点。当然,我们不能只是为了应付面试来学习这些知识,更重要的是将这些知识运用到实际的工作中...
  • 文章目录Lambda 表达式Lambda 表达式的基础语法实现类接口类方法引用Lambda 表达式需要“函数式接口”的支持Java8 内置的四大核心函数式接口示例代码Stream APIStream API 的操作步骤筛选与切片Stream 映射Map与...
  • 强大的Stream API以及并行流串行流

    千次阅读 2019-07-23 14:53:46
    文章目录Stream APIStreamStream操作的三个步骤创建Stream中间操作终止操作创建StreamStream的中间操作筛选与切片映射排序Stream的终止操作查找与匹配归约收集并行流串行流了解Fork/Join框架Fork/Join框架与传统...
  • 一、default关键字 1、简述概念 default关键字:默认方法与冲突 在Java中有一条亘久不变的定理:类只能单继承,接口可以多实现。 Java8之前由于接口中的方法全部都是抽象方法,...一个实现类C实现了AB,C的子类是D:

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,587
精华内容 2,634
关键字:

lambda和串行流使用并行流