Java 8 - Stream API

212 阅读3分钟

Stream

StreamJava 8 提供的一组操作集合的 API。 将要处理的元素集合看作一种流,流在管道中传输,并且可以在管道的节点上进行处理,比如筛选、排序、聚合等。元素流在管道中经过中间操作(intermediate operation)的处理,最后由终端操作 (terminal operation) 得到前面处理的结果。

Java 8 中的 Stream 是对集合 对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk data operation)。

Stream 提供串行和并行两种模式进行汇聚操作.

Stream 不是集合元素,它不是数据结构并不保存数据,它是有关算法和计算的。

Stream 更像一个高级版本的 Iterator。用户只要给出需要对其包含的元素执行什么操作,比如 “过滤掉长度大于 10 的字符串”、“获取每个字符串的首字母”等,Stream 会隐式地在内部进行遍历,做出相应的数据转换。

Stream 是单向的,数据只能遍历一次。

创建流

流的创建有以下几种方式,其中集合Collection接口中为我们提供了default Stream<E> stream() 方法,会被经常使用。

  • Stream.of() Stream 中的静态 of 方法创建流。
  • Collection.stream() 调用集合中default 方法创建流。
  • Collection.parallelStream()
创建 stream 流
List<String> list = new ArrayList<>();
Stream<String> stringStream = list.stream();

流的分类

  • 串行流 Collection.stream()
  • 并行流 Collection.parallelStream()

流的操作

Stream中流的操作分为两类,中间操作终端操作。其中终端操作按照是否短路又分为终结操作短路操作

中间操作会产生另一个流。 终端操作会消费Stream流,并且会产生一个结果。

  • 中间操作 map (mapToInt, flatMap 等)filterdistinctsortedpeeklimitskipparallelsequentialunordered

  • 终结操作 forEachforEachOrderedtoArrayreducecollectminmaxcountanyMatchallMatchnoneMatchfindFirstfindAnyiterator

  • 短路操作 anyMatchallMatchnoneMatchfindFirstfindAnylimit

常用操作

map

<R> Stream<R> map(Function<? super T, ? extends R> mapper);

产生一个新的流,对调用流的元素应用mapper,返回处理过后的Stream

List<User> userList = new ArrayList<>();
List<String> stringList = userList.stream()
        .map(User::getName)
        .collect(Collectors.toList());

flatMap

 <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);

flatMap() 操作能把原始流中的元素进行一对多的转换,并且将新生成的元素全都合并到它返回的流里面。

class Depart {
        private String departName;
        private List<User> userList;
}

List<Depart> departList = new ArrayList<>();
List<User> userList = departList.stream()
        .flatMap(depart -> depart.getUsers().stream())
        .collect(Collectors.toList());

filter

Stream<T> filter(Predicate<? super T> predicate);

产生一个新的流,对调用流的元素应用Predicate谓词操作,返回处理过后的Stream

List<User> userList = new ArrayList<>();
        userList.stream().filter(item -> item.getName().equals("A001")).collect(Collectors.toList());

distinct

List<User> userList = new ArrayList<>();
userList.stream().distinct().collect(Collectors.toList());

forEach

List<User> userList = new ArrayList<>();
userList.stream().forEach(user -> {
        
});

reduce

T reduce(T identity, BinaryOperator<T> accumulator);
List<User> userList = new ArrayList<>();
userList.stream().map(it -> it.getAmount()).reduce(BigDecimal.ZERO, new BinaryOperator<BigDecimal>() {
    @Override
    public BigDecimal apply(BigDecimal bigDecimal, BigDecimal bigDecimal2) {
        return bigDecimal.add(bigDecimal2);
    }
});
userList.stream().map(it -> it.getAmount()).reduce(BigDecimal.ZERO, (bigDecimal, bigDecimal2) -> bigDecimal.add(bigDecimal2));

userList.stream().map(it -> it.getAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);

findFirst

Collectors收集器

toList

所有元素放进 List 并返回

toSet

所有元素放进 Set 并返回

toMap

根据元素生成 Map<K, V>,key 相同时会报错

List<User> userList = new ArrayList<>();
Map<String, Integer> map = userList.stream().collect(Collectors.toMap(User::getName, User::getAge));

groupingBy

Map<Integer, List<User>> set = userList.stream().collect(Collectors.groupingBy(User::getAge));