+--------------------+ +------+ +------+ +---+ +-------+| stream of elements +-----> |filter+-> |sorted+-> |map+-> |collect|+--------------------+ +------+ +------+ +---+ +-------+
List<Integer> transactionsIds = widgets.stream().filter(b -> b.getColor == RED).sorted((x, y) -> x.getWeight() - y.getWeight()).mapToInt(Widget :: getWeight).sum();
生成流 集合接口有两种方法来生成流: stream(): 为集合创建串行流 parallelStream(): 为集合创建并行流 并行流可以充分发挥多核处理器的优势 使用fork和join并行方式来拆分任务和加速处理过程 List<String> strings = Arrays.asList("I", "want", "to", "be", "", "great");List<String> filter = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
Stream的创建方式 数组 通过数组来生成Stream流 String[] arrayStr = {"a", "b", "c"};// 使用Stream中的静态方法Stream<String> stream = Stream.of(arrayStr);
集合 通过集合来生成Stream流 List<String> list = Arrays.asList("a", "b", "c");Stream<String> strem = list.stream();
Stream.generate() 通过Stream.generate()方法来生成Stream流 Stream<Integer> generate = Stream.generate(() -> 1);
Stream.iterate() 通过Stream.iterate()方法来生成Stream流 Stream<Integer> iterate = Stream.iterate(1, x -> x + 1);
API 通过其余相关的API进行创建 String str = "api";IntStream stream = str.chars();
Stream常用方法 中间操作 中间操作: 如果调用方法之后返回的结果是Stream对象的操作是一个中间操作 filter filter方法用于通过设置的条件过滤出元素 List<String> strings = Arrays.asList("I", "want", "to", "be", "", "great");long count = Strings.stream().filter(string -> string.isEmpty()).count(); Arrays.asList(1, 2, 3, 4, 5).stream() .filter(x -> x % 2 == 0) // 2, 4 .forEach(System.out :: println) int count = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9).stream() .filter(x -> x % 2 == 0) .mapToInt(x -> x) .sum(); System.out.println(count);
distinct distinct方法通过元素的hashcode()和equals()去除重复元素 Arrays.asList(1, 2, 3, 3, 3, 4, 5).stream().distinct()// 1, 2, 3, 4, 5.forEach(System.out :: println);
sorted sorted方法根据自然排序返回Stream流 sorted(Comparator comparator)方法根据提供的Comparator进行排序集合Set去重:
Arrays.asList(1, 2, 3, 4, 5).stream() .collect(Collectors.toSet()) // 1, 2, 3, 4, 5 .forEach(System.out :: println); 复制代码
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5); // 数字的自然排序就是从小到大 Optional<Integer> min = list.stream().sorted().findFirst(); System.out.println(min :: get()); Optional<Integer> max = list.stream.sorted((a, b) -> b - a).findFirst(); System.out.println(max :: get()); Arrays.asList("java", "python", "c").stream().sorted().forEach(System.out :: println); Arrays.asList("java", "python", "c").stream().sorted((a, b) -> a.length() - b.length()).forEach(System.out :: println);
limit limit方法用来截取指定长度的Stream流 skip方法用来丢弃指定长度的流数据,可以与limit配合实现分页 Stream.iterate(x -> x + 1).limit(50) // 跳过前20个 .skip(20) // 输出20 - 30 .forEach(System.out :: println);
map map用来将Stream流中的元素按照指定的函数映射成一个新的元素的Stream流 flatMap用来将Stream流中的每个元素转换成另一个流,然后将所有流连接成一个新的流 List<String> list = Arrays.asList("a, b, c", "1, 2, 3"); Stream<String> mapList = list.stream().map(s -> s.replace(",", "")); // abc 123 mapList.forEach(System.out :: println); Stream<String> flatMapList = list.stream().flatMap(s -> { // 将每一个元素转换为流数据 String[] arrayStr = s.split(","); Stream<String> stream = Arrays.stream(arrayStr); return stream; }); // a b c 1 2 3 flatMapList.forEach(System.out :: println);
peek peek方法用来获取Stream流中的每一个元素 类似于map, 但是map中接收的是一个Function表达式,有返回值 peek中接收的是一个Consumer表达式,没有返回值 String str = "11, 22, 33, 44, 55";// 11 22 33 44 55 165System.out.println(Stream.of(str.split(",")).peek(System.out :: println).mapToInt(Integer :: valueOf).sum());
终止操作 循环-forEach forEach用来循环遍历每一个元素 // 创建一个实体类,包含有一个属性为num属性.并且有一个build()方法用于为num赋值String str = "1, 2, 3"Stream.of(str.split(",")).map(x -> new User(x)).forEach(System.out :: println);Stream.of(str.split(",")).map(User :: new).forEach(System.out :: println);Stream.of(str.split(",")).map(x -> User.build(x)).forEach(System.out :: println);Stream.of(str.split(",")).map(User :: build).forEach(System.out :: println);
计算-min,max,count,sum min: 返回Stream流元素中的最小值 max: 返回Stream流元素中的最大值 count: 返回Stream流元素中的总个数 sum: 对Stream流元素进行求和 List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);// 求集合的最大值 - 6System.out.println(list.stream().max((a, b) -> a - b).get());// 求集合的最小值 - 1System.out.println(list.stream().min((a, b) -> a - b).get());// 统计元素的个数 - 6System.out.println(list.stream().count());// 元素求和String str = "11, 22, 33, 44, 55";System.out.println(Stream.of(str.split(",")).mapToInt(x -> Integer.valueOf(x)).sum());System.out.println(Stream.of(str.split(",")).mapToInt(Integer :: valueOf).sum());System.out.println(Stream.of(str.split(",")).map(x -> Integer.valueOf(x)).mapToInt(x -> x).sum());System.out.println(Stream.of(str.split(",")).map(Integer :: valueOf).mapToInt(x -> x).sum());
匹配-anyMatch,allMatch,noneMatch,findFirst,findAny anyMatch: 接收一个Predicate函数,只要Stream流中有一个元素满足该断言则返回true, 否则返回false allMatch: 接收一个Predicate函数,当Stream流中每一个元素都满足该断言则返回true, 否则返回false noneMatch: 接收一个Predicate函数,当Stream流中每一个元素都不符合该断言则返回true, 否则返回false findFirst: 返回Stream流中的第一个元素 findAny: 返回Stream流中的任意一个元素 List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);// 如果集合的元素都大于等于0则返回trueSystem.out.println(list.stream().allMatch(x -> x >= 0));// 如果集合中有大于5的元素,返回falseSystemm.out.println(list.stream().noneMatch(x -> x > 5));// 如果集合中有大于3的元素则返回trueSystem.out.println(list.stream().anyMatch(x -> x > 3));// 取第一个偶数System.out.println(list.stream().filter(x -> x % 2 == 0).findFirst().get());// 取任意一个偶数System.out.println(list.stream().filter(x -> x % 2 == 0).findAny().get());
收集器-toArray,collect collect: 接收一个Collector实例,将流中元素转变为另外一种数据结构 Collector<T, A, R> 是一个接口,包含5个抽象方法: Supplier< A > supplier(): 创建一个结果容器 BiConsumer<A, T> accumulator(): 消费型接口. 第一个参数为容器A, 第二个参数为流中元素T BinaryOperator< A > combiner(): 函数接口. 该函数的作用是将各个子流程的运行结果,即accumulator函数操作后的容器A进行合并 Function<A, R> finisher(): 函数式接口. 参数为容器A, 返回类型为collect方法需要的结果类型R Set< Chracteristics > characteristics(): 返回一个不可变的Set集合,用来表明该Collector的特性 // 将对象值转化为ListList<Integer> ageList = userList.stream().map(User :: getAge).collect(Collectors.toList());// 将对象值转化为SetSet<Integer> ageSet = userList.stream().map(User :: getAge).collect(Collectors.toMap());// 将对象值转换为Map. 要求key的取值不能相同Map<String, Integer> userMap = userList.stream().collect(Colletors.toMap(User :: getName, User :: getAge));// 字符串分隔符连接String joinName = userList.stream().map(User :: getName).collect(Collectors.join(",", "(", ")"))// 聚合操作 - 计算对象总数Long count = userList.stream().collect(Collectors.counting());// 聚合操作 - 计算最大值Integer maxAge = userList.stream().map(User :: getAge).collect(Collectors.maxBy(Integer :: compare)).get(); // 聚合操作 - 计算对象值总数Integer sumAge = userList.stream().collect(Collectors.summingInt(User :: getAge));// 聚合操作 - 计算对象值的平均数Double averageAge = userList.stream().collet(Collectors.averagingDouble(User :: getAge));// 根据Age分组Map<Integer, List<User>> ageMap = userList.stream().collect(Collectors.groupingBy(User :: getAge));// 根据条件分区: 一部分大于10, 一部分小于10Map<Boolean, List<User>> partMap = userList.stream().collect(Collectors.partitionBy(x -> x.getAge() > 10));// 规约Integer value = userList.stream().map(User :: getAge).collect(Collectors.reducing(Integer :: sum)).get();
parallelStream parallelStream是流并行处理程序的代替方法 List<String> strings = Arrays.asList("I", "want", "to", "be", "", "great");long count = strings.parallelStream().filter(string -> string.isEmpty()).count();
可以很容易的在顺序运行和并行之间进行直接切换 Collectors Collectors类实现很多归约操作,比如将流转换成集合和聚合元素 Collectors可用于返回列表和字符串 List<String> strings = Arrays.asList("I", "want", "to", "be", "", "great");// 过滤掉空字符串List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());// 合并字符串String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(","));
averagingDouble public static <T> Collector<T, ?, Double> averagingDouble(ToDoubleFunction<? super T> mapper) { return new CollectorImpl<>( () -> new double[4], (a, t) -> { double val = mapper.applyAsDouble(t); sumWithCompensation(a, val); a[2]++; a[3]+= val;}, (a, b) -> { sumWithCompensation(a, b[0]); sumWithCompensation(a, b[1]); a[2] += b[2]; a[3] += b[3]; return a; }, a -> (a[2] == 0) ? 0.0d : (computeFinalSum(a) / a[2]), CH_NOID);}
averagingInt public static <T> Collector<T, ?, Double> averagingInt(ToIntFunction<? super T> mapper) { return new CollectorImpl<>( () -> new long[2], (a, t) -> { a[0] += mapper.applyAsInt(t); a[1]++; }, (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; }, a -> (a[1] == 0) ? 0.0d : (double) a[0] / a[1], CH_NOID);}
averagingLong public static <T> Collector<T, ?, Double> averagingLong(ToLongFunction<? super T> mapper) { return new CollectorImpl<>( () -> new long[2], (a, t) -> { a[0] += mapper.applyAsLong(t); a[1]++; }, (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; }, a -> (a[1] == 0) ? 0.0d : (double) a[0] / a[1], CH_NOID);}
collectingAndThen public static<T,A,R,RR> Collector<T,A,RR> collectingAndThen(Collector<T,A,R> downstream, Function<R,RR> finisher) { Set<Collector.Characteristics> characteristics = downstream.characteristics(); if (characteristics.contains(Collector.Characteristics.IDENTITY_FINISH)) { if (characteristics.size() == 1) characteristics = Collectors.CH_NOID; else { characteristics = EnumSet.copyOf(characteristics); characteristics.remove(Collector.Characteristics.IDENTITY_FINISH); characteristics = Collections.unmodifiableSet(characteristics); } } return new CollectorImpl<>(downstream.supplier(), downstream.accumulator(), downstream.combiner(), downstream.finisher().andThen(finisher), characteristics);}
counting public static <T> Collector<T, ?, Long> counting() { return summingLong(e -> 1L);}
groupingBy public static <T, K> Collector<T, ?, Map<K, List<T>>> groupingBy(Function<? super T, ? extends K> classifier) { return groupingBy(classifier, toList());}public static <T, K, A, D> Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier, Collector<? super T, A, D> downstream) { return groupingBy(classifier, HashMap::new, downstream);}public static <T, K, D, A, M extends Map<K, D>> Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier, Supplier<M> mapFactory, Collector<? super T, A, D> downstream) { Supplier<A> downstreamSupplier = downstream.supplier(); BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator(); BiConsumer<Map<K, A>, T> accumulator = (m, t) -> { K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key"); A container = m.computeIfAbsent(key, k -> downstreamSupplier.get()); downstreamAccumulator.accept(container, t); }; BinaryOperator<Map<K, A>> merger = Collectors.<K, A, Map<K, A>>mapMerger(downstream.combiner()); @SuppressWarnings("unchecked") Supplier<Map<K, A>> mangledFactory = (Supplier<Map<K, A>>) mapFactory; if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) { return new CollectorImpl<>(mangledFactory, accumulator, merger, CH_ID); } else { @SuppressWarnings("unchecked") Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher(); Function<Map<K, A>, M> finisher = intermediate -> { intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v)); @SuppressWarnings("unchecked") M castResult = (M) intermediate; return castResult; }; return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_NOID); }}
groupingByConcurrent public static <T, K> Collector<T, ?, ConcurrentMap<K, List<T>>> groupingByConcurrent(Function<? super T, ? extends K> classifier) { return groupingByConcurrent(classifier, ConcurrentHashMap::new, toList());}public static <T, K, A, D> Collector<T, ?, ConcurrentMap<K, D>> groupingByConcurrent(Function<? super T, ? extends K> classifier, Collector<? super T, A, D> downstream) { return groupingByConcurrent(classifier, ConcurrentHashMap::new, downstream);}public static <T, K, A, D, M extends ConcurrentMap<K, D>> Collector<T, ?, M> groupingByConcurrent(Function<? super T, ? extends K> classifier, Supplier<M> mapFactory, Collector<? super T, A, D> downstream) { Supplier<A> downstreamSupplier = downstream.supplier(); BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator(); BinaryOperator<ConcurrentMap<K, A>> merger = Collectors.<K, A, ConcurrentMap<K, A>>mapMerger(downstream.combiner()); @SuppressWarnings("unchecked") Supplier<ConcurrentMap<K, A>> mangledFactory = (Supplier<ConcurrentMap<K, A>>) mapFactory; BiConsumer<ConcurrentMap<K, A>, T> accumulator; if (downstream.characteristics().contains(Collector.Characteristics.CONCURRENT)) { accumulator = (m, t) -> { K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key"); A resultContainer = m.computeIfAbsent(key, k -> downstreamSupplier.get()); downstreamAccumulator.accept(resultContainer, t); }; } else { accumulator = (m, t) -> { K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key"); A resultContainer = m.computeIfAbsent(key, k -> downstreamSupplier.get()); synchronized (resultContainer) { downstreamAccumulator.accept(resultContainer, t); } }; } if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) { return new CollectorImpl<>(mangledFactory, accumulator, merger, CH_CONCURRENT_ID); } else { @SuppressWarnings("unchecked") Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher(); Function<ConcurrentMap<K, A>, M> finisher = intermediate -> { intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v)); @SuppressWarnings("unchecked") M castResult = (M) intermediate; return castResult; }; return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_CONCURRENT_NOID); }}
joining public static Collector<CharSequence, ?, String> joining() { return new CollectorImpl<CharSequence, StringBuilder, String>( StringBuilder::new, StringBuilder::append, (r1, r2) -> { r1.append(r2); return r1; }, StringBuilder::toString, CH_NOID);}public static Collector<CharSequence, ?, String> joining(CharSequence delimiter) { return joining(delimiter, "", "");}public static Collector<CharSequence, ?, String> joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix) { return new CollectorImpl<>( () -> new StringJoiner(delimiter, prefix, suffix), StringJoiner::add, StringJoiner::merge, StringJoiner::toString, CH_NOID);}
mapping public static <T, U, A, R> Collector<T, ?, R> mapping(Function<? super T, ? extends U> mapper, Collector<? super U, A, R> downstream) { BiConsumer<A, ? super U> downstreamAccumulator = downstream.accumulator(); return new CollectorImpl<>(downstream.supplier(), (r, t) -> downstreamAccumulator.accept(r, mapper.apply(t)), downstream.combiner(), downstream.finisher(), downstream.characteristics());}
maxBy public static <T> Collector<T, ?, Optional<T>> maxBy(Comparator<? super T> comparator) { return reducing(BinaryOperator.maxBy(comparator));}
minBy public static <T> Collector<T, ?, Optional<T>> (Comparator<? super T> comparator) { return reducing(BinaryOperator.minBy(comparator));}
partitioningBy public static <T> Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate) { return partitioningBy(predicate, toList());}public static <T, D, A> Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate, Collector<? super T, A, D> downstream) { BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator(); BiConsumer<Partition<A>, T> accumulator = (result, t) -> downstreamAccumulator.accept(predicate.test(t) ? result.forTrue : result.forFalse, t); BinaryOperator<A> op = downstream.combiner(); BinaryOperator<Partition<A>> merger = (left, right) -> new Partition<>(op.apply(left.forTrue, right.forTrue), op.apply(left.forFalse, right.forFalse)); Supplier<Partition<A>> supplier = () -> new Partition<>(downstream.supplier().get(), downstream.supplier().get()); if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) { return new CollectorImpl<>(supplier, accumulator, merger, CH_ID); } else { Function<Partition<A>, Map<Boolean, D>> finisher = par -> new Partition<>(downstream.finisher().apply(par.forTrue), downstream.finisher().apply(par.forFalse)); return new CollectorImpl<>(supplier, accumulator, merger, finisher, CH_NOID); }}
reducing public static <T> Collector<T, ?, Optional<T>> reducing(BinaryOperator<T> op) { class OptionalBox implements Consumer<T> { T value = null; boolean present = false; @Override public void accept(T t) { if (present) { value = op.apply(value, t); } else { value = t; present = true; } } } return new CollectorImpl<T, OptionalBox, Optional<T>>( OptionalBox::new, OptionalBox::accept, (a, b) -> { if (b.present) a.accept(b.value); return a; }, a -> Optional.ofNullable(a.value), CH_NOID);}public static <T> Collector<T, ?, T> reducing(T identity, BinaryOperator<T> op) { return new CollectorImpl<>( boxSupplier(identity), (a, t) -> { a[0] = op.apply(a[0], t); }, (a, b) -> { a[0] = op.apply(a[0], b[0]); return a; }, a -> a[0], CH_NOID);}public static <T, U> Collector<T, ?, U> reducing(U identity, Function<? super T, ? extends U> mapper, BinaryOperator<U> op) { return new CollectorImpl<>( boxSupplier(identity), (a, t) -> { a[0] = op.apply(a[0], mapper.apply(t)); }, (a, b) -> { a[0] = op.apply(a[0], b[0]); return a; }, a -> a[0], CH_NOID);}
summarizingDouble public static <T> Collector<T, ?, DoubleSummaryStatistics> summarizingDouble(ToDoubleFunction<? super T> mapper) { return new CollectorImpl<T, DoubleSummaryStatistics, DoubleSummaryStatistics>( DoubleSummaryStatistics::new, (r, t) -> r.accept(mapper.applyAsDouble(t)), (l, r) -> { l.combine(r); return l; }, CH_ID);}
summarizingInt public static <T> Collector<T, ?, IntSummaryStatistics> summarizingInt(ToIntFunction<? super T> mapper) { return new CollectorImpl<T, IntSummaryStatistics, IntSummaryStatistics>( IntSummaryStatistics::new, (r, t) -> r.accept(mapper.applyAsInt(t)), (l, r) -> { l.combine(r); return l; }, CH_ID);}
summarizingLong public static <T> Collector<T, ?, LongSummaryStatistics> summarizingLong(ToLongFunction<? super T> mapper) { return new CollectorImpl<T, LongSummaryStatistics, LongSummaryStatistics>( LongSummaryStatistics::new, (r, t) -> r.accept(mapper.applyAsLong(t)), (l, r) -> { l.combine(r); return l; }, CH_ID);}
summingDouble public static <T> Collector<T, ?, Double> summingDouble(ToDoubleFunction<? super T> mapper) { return new CollectorImpl<>( () -> new double[3], (a, t) -> { double val = mapper.applyAsDouble(t); sumWithCompensation(a, val); a[2] += val;}, (a, b) -> { sumWithCompensation(a, b[0]); a[2] += b[2]; return sumWithCompensation(a, b[1]); }, a -> computeFinalSum(a), CH_NOID);}
summingInt public static <T> Collector<T, ?, Integer> summingInt(ToIntFunction<? super T> mapper) { return new CollectorImpl<>( () -> new int[1], (a, t) -> { a[0] += mapper.applyAsInt(t); }, (a, b) -> { a[0] += b[0]; return a; }, a -> a[0], CH_NOID);}
summingLong public static <T> Collector<T, ?, Long> summingLong(ToLongFunction<? super T> mapper) { return new CollectorImpl<>( () -> new long[1], (a, t) -> { a[0] += mapper.applyAsLong(t); }, (a, b) -> { a[0] += b[0]; return a; }, a -> a[0], CH_NOID);}
toCollection public static <T, C extends Collection<T>> Collector<T, ?, C> toCollection(Supplier<C> collectionFactory) { return new CollectorImpl<>(collectionFactory, Collection<T>::add, (r1, r2) -> { r1.addAll(r2); return r1; }, CH_ID);}
toConcurrentMap public static <T, K, U> Collector<T, ?, ConcurrentMap<K,U>> toConcurrentMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper) { return new CollectorImpl<>(ConcurrentHashMap::new, uniqKeysMapAccumulator(keyMapper, valueMapper), uniqKeysMapMerger(), CH_CONCURRENT_ID);}public static <T, K, U> Collector<T, ?, ConcurrentMap<K,U>> toConcurrentMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper, BinaryOperator<U> mergeFunction) { return toConcurrentMap(keyMapper, valueMapper, mergeFunction, ConcurrentHashMap::new);}public static <T, K, U, M extends ConcurrentMap<K, U>> Collector<T, ?, M> toConcurrentMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper,BinaryOperator<U> mergeFunction,Supplier<M> mapFactory) { BiConsumer<M, T> accumulator = (map, element) -> map.merge(keyMapper.apply(element), valueMapper.apply(element), mergeFunction); return new CollectorImpl<>(mapFactory, accumulator, mapMerger(mergeFunction), CH_CONCURRENT_ID);}
toList public static <T> Collector<T, ?, List<T>> toList() { return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add, (left, right) -> { left.addAll(right); return left; }, CH_ID);}
toMap public static <T, K, U> Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper) { return new CollectorImpl<>(HashMap::new, uniqKeysMapAccumulator(keyMapper, valueMapper), uniqKeysMapMerger(), CH_ID);}public static <T, K, U> Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper, BinaryOperator<U> mergeFunction) { return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);}public static <T, K, U, M extends Map<K, U>> <T, ?, M> toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper, BinaryOperator<U> mergeFunction, <M> mapFactory) { BiConsumer<M, T> accumulator = (map, element) -> map.merge(keyMapper.apply(element), valueMapper.apply(element), mergeFunction); return new CollectorImpl<>(mapFactory, accumulator, mapMerger(mergeFunction), CH_ID);}
toSet public static <T> Collector<T, ?, Set<T>> toSet() { return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, Set::add, (left, right) -> { if (left.size() < right.size()) { right.addAll(left); return right; } else { left.addAll(right); return left; } }, CH_UNORDERED_ID);}
统计 产生统计结果的收集器,主要用于int,double,long等类型 List<Integer> numbers = Arrays.asList(3, 2, 3, 7, 3, 5);IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();System.out.println("列表中最大的数:" + stats.getMax());System.out.println("列表中最小的数:" + stats.getMin());System.out.println("所有数之和:" + stats.getSum());System.out.println("平均数:" + stats.getAverage());