天天看点

java8新特性——Stream流一、Stream简介二、Stream API

文章目录

  • 一、Stream简介
  • 二、Stream API
    • 2.1 筛选和切片
      • 2.1.1 filter
      • 2.1.2 distinct
      • 2.1.3 limit(n)
      • 2.1.4 skip(n)
    • 2.2 映射
      • 2.2.1 map
      • 2.2.2 flatMap
    • 2.3 查找和匹配
      • 2.3.1 anyMatch
      • 2.3.2 allMatch
      • 2.3.3 noneMatch
      • 2.3.4 findAny
      • 2.3.5 findFirst
    • 2.4 归约
      • 2.4.1 reduce
    • 2.5 其他
      • 2.5.1 of
      • 2.5.2 empty
      • 2.5.2 concat
      • 2.5.3 peek

祸兮,福所依;福兮,祸所伏。

一、Stream简介

什么是流?

简单说,流是从集合中计算得来的一组元素序列。

集合与流之间的差异就在于什么时候进行计算:

集合是一个内存中的数据结构,它包含数据结构中目前所有的值——集合中的每个元素都得先算出来才能添加到集合中。

相比之下,流则是在概念上固定的数据结构(你不能添加或删除元素),其元素是按需计算的。

二、Stream API

2.1 筛选和切片

2.1.1 filter

筛选元素,例:筛选字符长度>3的元素
// 返回"three","four"
Stream.of("one", "two", "three", "four")
      .filter((e) -> e.length() > 3);
           

2.1.2 distinct

元素去重
// 返回元素"one","three","four"
Stream.of("one", "one", "three", "four")
      .distinct();
           

2.1.3 limit(n)

返回前n条数据
// 返回元素"one","two"
Stream.of("one", "two", "three", "four")
      .limit(2);
           

2.1.4 skip(n)

跳过前 n 条数据
// 返回元素"three","four"
Stream.of("one", "two", "three", "four")
      .skip(2);
           

2.2 映射

2.2.1 map

通常用于将一个类型转换成另外一个类型,也可以是同类型
// 将每个元素映射成大写
Stream.of("one", "two", "three", "four")
      .map(String::toUpperCase);
           
// User  ->  UserDTO
User user = new User();
Stream<UserDTO> userDTOStream = Stream.of(user)
                .map((u) -> {
                    UserDTO dto = new UserDTO();
                    BeanUtils.copyProperties(u, dto);
                    return dto;
                });
           

补充:

mapToInt,将元素转换成int类型, 返回IntStream

mapToLong,将元素转换成long类型,返回LongStream

mapToDouble,将元素转换成double类型,返回DoubleStream

在操作原始数值类型时,最好使用原始类型特化流,因为这些流将元素特化为int、long、double等基本类型,从而避免了进行数值计算时,暗含的装箱、拆箱成本。

2.2.2 flatMap

流的扁平化。flatmap方法让你把一个流中的每个值都换成另一个流,然后把所有的流连接起来成为一个流。

它比较适用于Stream中元素是一个集合或数组的情况,比如:

Stream<String[]>

举个例子:words 数组元素为 {“one”,“two”,“three”},目标时将words以字符格式输出,即:‘o’ ‘n’ ‘e’ …

String[] words = {"one","two","three"};
Stream<String> stream = Stream.of(words);
// 分割字符串
Stream<String[]> stream1 = stream.map(e -> e.split(""));
// 将Stream<String[]> 转换成 Stream<String>
Stream<String> stringStream = stream1.flatMap(e -> Arrays.stream(e));

stringStream.collect(Collectors.toList())
            .forEach(s -> System.out.print(s + " "));
           

说起来,flatMap有点像双层for循环,它可以对stream流中单个元素再进行拆分。

补充:

flatMapToInt,将元素扁平成int类型

flatMapToLong,将元素扁平成long类型

flatMapToDouble,将元素扁平成double类型

2.3 查找和匹配

2.3.1 anyMatch

流中是否有一个元素能匹配

2.3.2 allMatch

是否匹配所有元素

2.3.3 noneMatch

流中没有任何元素匹配

2.3.4 findAny

查找元素,返回当前流中的任意元素

2.3.5 findFirst

查找第一个元素

2.4 归约

2.4.1 reduce

reduce方法可以用在数字求和、乘积等场景。

它的作用是每次计算的时候都用到上一次的计算结果,比如求和操作:前两个数的和加上第三个数的和,一直加到最后一个数位置,最后返回结果。

int sum = IntStream.of(3, 4, 8)
               		 .reduce(0, (a, b) -> a + b);
           

当然,这里用IntStream的sum方法更好

int sum = IntStream.of(3, 4, 8)
                	.sum();
           

2.5 其他

2.5.1 of

可接受一个泛型对象或可变泛型对象集合,返回一个Stream对象
Stream<String> stream = Stream.of("a", "b", "c");
           

2.5.2 empty

创建一个空的Stream对象
Stream<Object> empty = Stream.empty();
           

2.5.2 concat

连接两个Stream,返回一个新的Stream
Stream<String> a = Stream.of("a","b","c");
 Stream<String> b = Stream.of("d","e");
 Stream<String> c = Stream.concat(a,b);
 // 输出:abcde
 c.collect(Collectors.toList()).forEach(System.out::print);
           

2.5.3 peek

peek:窥视,窥探;

java源码中对这个方法进行了详细描述

简单说:这个方法的存在主要是为了支持调试

java源码提供的案例如下:

Stream.of("one", "two", "three", "four")
      .filter(e -> e.length() > 3)
      .peek(e -> System.out.println("Filtered value: " + e))
      .map(String::toUpperCase)
      .peek(e -> System.out.println("Mapped value: " + e))
      .collect(Collectors.toList());
           

输出结果:

Filtered value: three

Mapped value: THREE

Filtered value: four

Mapped value: FOUR

这个方法的好处在于,我们可以在执行Stream的filter、map或者其他操作之后可以查看到数据执行的结果。