java8新特性

Stream流

 Stream流的介绍

  1. stream不存储数据,而是按照特定的规则对数据进行计算,一般会输出结果;
  2. stream不会改变数据源,通常情况下会产生一个新的集合;
  3. stream具有延迟执行特性,只有调用终端操作时,中间操作才会执行。
  4. stream操作分为终端操作和中间操作,那么这两者分别代表什么呢?
    终端操作:会消费流,这种操作会产生一个结果的,如果一个流被消费过了,那它就不能被重用的。
    中间操作:中间操作会产生另一个流。因此中间操作可以用来创建执行一系列动作的管道。一个特别需要注意的点是:中间操作不是立即发生的。相反,当在中间操作创建的新流上执行完终端操作后,中间操作指定的操作才会发生。所以中间操作是延迟发生的,中间操作的延迟行为主要是让流API能够更加高效地执行。
  5. stream不可复用,对一个已经进行过终端操作的流再次调用,会抛出异常。

串行 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常用方法

@Test
public void test() {
  List<String> strings = Arrays.asList("abc", "def", "gkh", "abc");
    //返回符合条件的stream
    Stream<String> stringStream = strings.stream().filter(s -> "abc".equals(s));
    //计算流符合条件的流的数量
    long count = stringStream.count();

    //forEach遍历->打印元素
    strings.stream().forEach(System.out::println);

    //limit 获取到1个元素的stream
    Stream<String> limit = strings.stream().limit(1);
    //toArray 比如我们想看这个limitStream里面是什么,比如转换成String[],比如循环
    String[] array = limit.toArray(String[]::new);

    //map 对每个元素进行操作返回新流
    Stream<String> map = strings.stream().map(s -> s + "22");

    //sorted 排序并打印
    strings.stream().sorted().forEach(System.out::println);

    //Collectors collect 把abc放入容器中
    List<String> collect = strings.stream().filter(string -> "abc".equals(string)).collect(Collectors.toList());
    //把list转为string,各元素用,号隔开
    String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(","));

    //对数组的统计,比如用
    List<Integer> number = Arrays.asList(1, 2, 5, 4);

    IntSummaryStatistics statistics = number.stream().mapToInt((x) -> x).summaryStatistics();
    System.out.println("列表中最大的数 : "+statistics.getMax());
    System.out.println("列表中最小的数 : "+statistics.getMin());
    System.out.println("平均数 : "+statistics.getAverage());
    System.out.println("所有数之和 : "+statistics.getSum());

    //concat 合并流
    List<String> strings2 = Arrays.asList("xyz", "jqx");
    Stream.concat(strings2.stream(),strings.stream()).count();

    //注意 一个Stream只能操作一次,不能断开,否则会报错。
    Stream stream = strings.stream();
    //第一次使用
    stream.limit(2);
    //第二次使用
    stream.forEach(System.out::println);
    //报错 java.lang.IllegalStateException: stream has already been operated upon or closed

    //但是可以这样, 连续使用
    stream.limit(2).forEach(System.out::println);
}

3.Stream注意事项(重要)

Stream不存储数据,而是按照特定的规则对数据进行计算,一般会输出结果

Stream只能操作一次
Stream方法返回的是新的流
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.并行流的与串行流的区别

顾名思义,当使用顺序方式去遍历时,每个item读完后再读下一个item。而使用并行去遍历时,数组会被分成多个段,其中每一个都在不同的线程中处理,然后将结果一起输出。

  • 串行有序
  • 并行无序
  • 并行流的效率是要比串行流要高,底层使用Fork/Join框架进行处理

  • parallelStream是线程不安全的。

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资源,通常不是CPU密集型操作,一般并行流中不适用于I/O密集型的操作,相反,它们是对系统资源(如磁盘、网络、内存等)的频繁访问和等待的操作。就比如使用并行流进行大批量的消息推送,涉及到了大量I/O,使用并行流反而慢了很多
4、在使用并行流的时候是无法保证元素的顺序的,也就是即使你用了同步集合也只能保
证元素都正确但无法保证其中的顺序

并行流使用场景:在数据量比较大的情况下,CPU负载本身不是很高,CPU密集型的操作不要求顺序执行的时候,可以使用并行流。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值