1,Optional
Java 8 中的 Optional
1.1,获取 Optional 的三个方法
1. of(value)
返回一个 Optional, value 不可以为 null
2. empty()
返回一个空的 Optional
3. ofNullable(value)
返回一个 Optional, 如果 value为 null,就是 empty(),否则是 of
1.2,实例方法
1. ifPresent(Consumer<? super T> consumer)
optional 实例非 null 执行 consumer
2. isPresent()
判断 optional 是否有值
3. get()
获取 optional 值
4. orElse(value)
optional 值为 null 时,返回 value
5. orElseGet(Supplier<? extends T> other)
optional 值为 null 时,返回 Supplier 的返回值
6. orElseThrow(Supplier<? extends X> exceptionSupplier)
optional 值为 null 时,抛出指定异常
7. map(Function<? super T, ? extends U> mapper)
使用 Function 函数式接口返回一个值
8. filter(Predicate<? super T> predicate)
断言返回 false 时 optional 为 null
2,Stream
- 中间操作:返回一个新的 stream,可以有 0 个或多个。
- 终端操作:Stream流执行完终端操作之后,无法再执行其他动作,否则会报状态异常,提示该流已经被执行操作或者被关闭,想要再次执行操作必须重新创建Stream流
2.1, 创建 Stream 的几种情景
1,Stream.of()/Stream.iterator()/Stream.generate()
Stream<Integer> streamSelf = Stream.of(1, 2, 3, 4);
Stream<Integer> streamIterate = Stream.iterate(0, integer -> {
System.out.println(integer);
return integer + 2;
}).limit(5);
Stream<Object> streamGenerate = Stream.generate((Supplier<Object>) () -> Math.random()).limit(5);
2,array.stream()
Stream<Integer> streamArray = Arrays.stream(new Integer[]{1, 2, 3, 4, 5});
3,collection.stream()
Stream<Integer> streamCollection = Arrays.asList(1, 2, 3, 4).stream();
4,Files.lines/files.list()
Stream<String> streamFile = Files.lines(new File("C:\\Users\\admin\\Desktop\\test1.html").toPath());
Stream<Path> streamList = Files.list(new File("C:\\Users\\admin\\Desktop").toPath());
2.2,Stream Api
1. 判断匹配元素 *Match()
根据提供的断言判断元素匹配情况,返回 boolean 值。
//所有元素都匹配
boolean allMatch(Predicate<? super T> predicate);
//任意一个匹配
boolean anyMatch(Predicate<? super T> predicate);
//都不匹配
boolean noneMatch(Predicate<? super T> predicate);
example:
@Test
public void test13(){
System.out.println( list.stream().allMatch(new Predicate<Dog>() {
@Override
public boolean test(Dog dog) {
return dog.getSteps() > 5;
}
}));
System.out.println(list.stream().anyMatch(new Predicate<Dog>() {
@Override
public boolean test(Dog dog) {
return dog.getSteps() > 10;
}
}));
System.out.println(list.stream().noneMatch(new Predicate<Dog>() {
@Override
public boolean test(Dog dog) {
return dog.getSteps() > 10;
}
}));
}
2. 统计 count()
统计元素数目
long count();
3. 去重 distinct()
Stream<T> distinct();
4. 过滤 filter()
Stream<T> filter(Predicate<? super T> predicate);
example:
System.out.println( list.stream().filter(new Predicate<Dog>() {
@Override
public boolean test(Dog dog) {
return dog.getSteps() > 20;
}
}).collect(Collectors.toList()) );
5. 获取一个元素 findAny()/findFirst()
findAny() 和 findFirst() 都是从流中获取一个元素,返回 Optional。与 findFirst 不同的是,findAny() 然会任意一个,如果是并行流则可能是随机一个。
//获取随机一个
Optional<T> findAny();
//获取第一个
Optional<T> findFirst();
6. 扁平流处理 flatMap()
与 map() 类似,但是一般适用于双重列表,处理成一层列表,故称扁平流
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
example:
@Test
public void test15(){
List<List<Integer>> lists = Arrays.asList(
Arrays.asList(1, 2, 3, 4),
Arrays.asList(5, 6, 7, 8),
Arrays.asList(9, 11, 13)
);
System.out.println( lists.stream().flatMap(new Function<List<Integer>, Stream<?>>() {
@Override
public Stream<?> apply(List<Integer> list) {
return list.stream();
}
}).collect(Collectors.toList()) );
}
与之类似的还有 flatMapToInt,flatMapToLong, flatMapToDouble,以 flatMapToInt 为例:
//比 flatMap() 麻烦亿点
System.out.println( lists.stream().flatMapToInt(new Function<List<Integer>, IntStream>() {
@Override
public IntStream apply(List<Integer> innerList) {
return innerList.stream().mapToInt(new ToIntFunction<Integer>() {
@Override
public int applyAsInt(Integer value) {
return value;
}
});
}
}).collect(new Supplier<List<Integer>>() {
@Override
public List<Integer> get() {
return new ArrayList<>();
}
}, new ObjIntConsumer<List<Integer>>() {
@Override
public void accept(List<Integer> integers, int value) {
integers.add(value);
}
}, new BiConsumer<List<Integer>, List<Integer>>() {
@Override
public void accept(List<Integer> integers, List<Integer> integers2) {
integers.addAll(integers2);
}
}));
7. 遍历元素 foreach()
对流中每个元素进行处理
void forEach(Consumer<? super T> action);
example:
@Test
public void test16(){
list.stream().forEach(new Consumer<Dog>() {
@Override
public void accept(Dog dog) {
dog.setSteps(10000);
}
});
System.out.println(list);
}
有一个 forEachOrdered() 方法,可以保证在并行流中也是按照顺序处理每个元素。
8. 长度限制 limit()
截取流中部分元素
Stream<T> limit(long maxSize);
example:
System.out.println( list.stream().limit(3).collect(Collectors.toList()) );
9. 元素转换 map()
将流中元素进行映射处理
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
example:
@Test
public void test19(){
System.out.println( list.stream().map(new Function<Dog, Cat>() {
@Override
public Cat apply(Dog dog) {
return new Cat(dog.getSteps(), dog.getName());
}
}).collect(Collectors.toList()) );
}
mapToDouble(),mapToLong(),mapToInt() 差不多,不再赘述。
10,最大最小 max()/min()
获取元素中最大最小,返回的是一个 Optional 对象
Optional<T> max(Comparator<? super T> comparator);
Optional<T> min(Comparator<? super T> comparator);
example:
@Test
public void max(){
System.out.println( list.stream().max(new Comparator<Dog>() {
@Override
public int compare(Dog o1, Dog o2) {
return o1.getSteps() - o2.getSteps();
}
}).get() );
}
11,观察元素 peek()
用于在流的处理过程中提供一种观察元素的机制,而不会改变流中的元素。类似与 foreach(),但是不会改变元素数据。
Stream<T> peek(Consumer<? super T> action);
12,归并 reduce()
三个参数,接收一个初始值,一个映射函数(用来修改元素),和一个二元运算符,参考 Collectors.reducing()
<U> U reduce(U identity,
BiFunction<U, ? super T, U> accumulator,
BinaryOperator<U> combiner);
example:
@Test
public void reduce(){
System.out.println( list.stream().reduce(new BinaryOperator<Dog>() {
@Override
public Dog apply(Dog dog, Dog dog2) {
return dog.getSteps()>dog2.getSteps()?dog:dog2;
}
}).get() );
}
13. 跳过元素 skip
Stream<T> skip(long n);
14. 排序 sort()
Stream<T> sorted();
Stream<T> sorted(Comparator<? super T> comparator);
14. 转换数组 toArray()
两个方法重载
//转换成 Object 数组
Object[] toArray();
//转换成固定泛型数组
<A> A[] toArray(IntFunction<A[]> generator);
example:
@Test
public void toArray(){
Object[] objects = list.stream().toArray();
Dog[] dogs = list.stream().toArray(new IntFunction<Dog[]>() {
@Override
public Dog[] apply(int value) {
return new Dog[value];
}
});
for(Dog dog: dogs){
System.out.println(dog);
}
}
2.3, Stream 类 collect()
收集器,将流转换为其他形式。有两个重载方法
/**
* 接收三个参数
* 第一个参数提供一个 目标类型的示例,如 ArrayList,HashSet 等。
* 第二个参数提供一个消费者(累加器),第一个方法参数就是上面参数提供的实例,第二个参数表示一个元素,就是 stream 流中的每个元素,重复调用直到流中元素全部添加到目标实例重。
* 第三个参数也是一个消费者(整合),好像并发时候才用得到。
*/
<R> R collect(Supplier<R> supplier,
BiConsumer<R, ? super T> accumulator,
BiConsumer<R, R> combiner);
/**
* 参数是一个 Collectors 类型实例
*/
<R, A> R collect(Collector<? super T, A, R> collector);
第一个举个例子了解一下就好:
@Test
public void testCollector(){
System.out.println( list.stream().collect(
new Supplier<List<Dog>>() {
@Override
public List<Dog> get() {
List<Dog> list = new ArrayList<>();
System.out.println( list );
return list;
}
},
new BiConsumer<List<Dog>, Dog>() {
@Override
public void accept(List<Dog> dogs, Dog dog) {
System.out.println("accumulator");
dogs.add(dog);
}
},
new BiConsumer<List<Dog>, List<Dog>>() {
@Override
public void accept(List<Dog> dogs, List<Dog> dogs2) {
System.out.println("combiner");
dogs.addAll(dogs2);
}
}
));
}
我们一般使用的是第二个,通过 Collectors 提供一个 Collector 实例,下面列出常用的几种。
1. 转换为 Collection
//转换为 List
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);
}
//转换为 Set
public static <T>
Collector<T, ?, Set<T>> toSet() {
return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, Set::add,
(left, right) -> { left.addAll(right); return left; },
CH_UNORDERED_ID);
}
//转换为 collection
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);
}
example:
list.stream().collect(Collectors.toList());
list.stream().collect(Collectors.toSet());
list.stream().collect(Collectors.toCollection(new Supplier<Collection<Dog>>() {
@Override
public Collection<Dog> get() {
return new ArrayList<Dog>();
}
}));
2. 转换为对应 Map
转换为 map,一共三个重载方法,同时有三个 toConcurrentMap(),转换为 ConcurrentMap,参数与 toMap 对应。
/**
* 三个重载 构造方法
* Function<? super T, ? extends K> keyMapper, key 的映射函数
* Function<? super T, ? extends U> valueMapper, value 的映射函数
* BinaryOperator<U> mergeFunction, 当key 冲突时,调用的合并方法
* Supplier<M> mapSupplier, Map 构造器,需要返回特定的 map 时使用
*/
public static <T, K, U>
Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper) {
return toMap(keyMapper, valueMapper, throwingMerger(), HashMap::new);
}
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>>
Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper,
BinaryOperator<U> mergeFunction,
Supplier<M> mapSupplier) {
BiConsumer<M, T> accumulator
= (map, element) -> map.merge(keyMapper.apply(element),
valueMapper.apply(element), mergeFunction);
return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID);
}
example:
list.stream().collect(Collectors.toMap(
new Function<Dog, String>() {
@Override
public String apply(Dog dog) {
return dog.getName();
}
}, new Function<Dog, Dog>() {
@Override
public Dog apply(Dog dog) {
return dog;
}
}, new BinaryOperator<Dog>() {
@Override
public Dog apply(Dog o1, Dog o2) {
return o2;
}
}, new Supplier<Map<String, Dog>>() {
@Override
public Map<String, Dog> get() {
return new TreeMap<String, Dog>();
}
}
));
3,字符串拼接 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);
}
example:
//123
System.out.println( Arrays.asList("1", "2", "3").stream().collect(Collectors.joining()) );
//1,2,3
System.out.println( Arrays.asList("1", "2", "3").stream().collect(Collectors.joining(",")) );
//#{1,2,3}
System.out.println( Arrays.asList("1", "2", "3").stream().collect(Collectors.joining(",", "#{", "}")) );
4. 映射 mapping()
mapping() 方法,将流中元素映射为指定对象,与 stream().map() 有点类似。Collectors.mapping的作用是将流中的元素经过mapper函数映射后,再使用downstream收集器来收集这些映射结果。最终返回的结果是downstream收集器生成的结果。
/**
* 两个参数:
* 第一个参数:提供一个映射 mapper,将流中元素映射成指定对象
* 第二个参数:提供一个收集器,将映射后的元素返回一个指定收集器
*/
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());
}
exapmle:
@Test
public void test4(){
List<Cat> catList = list.stream().collect(
Collectors.mapping(
new Function<Dog, Cat>() {
@Override
public Cat apply(Dog dog) {
return new Cat(dog.getSteps(), dog.getName());
}
},
Collectors.toList()
)
);
System.out.println(catList);
}
5. 求平均数 averaging*
这样方法有三个, averagingDouble,averagingInt,averagingLong,以 averagingDouble 为例
public static <T> Collector<T, ?, Double>
averagingDouble(ToDoubleFunction<? super T> mapper) {
/*
* In the arrays allocated for the collect operation, index 0
* holds the high-order bits of the running sum, index 1 holds
* the low-order bits of the sum computed via compensated
* summation, and index 2 holds the number of values seen.
*/
return new CollectorImpl<>(
() -> new double[4],
(a, t) -> { sumWithCompensation(a, mapper.applyAsDouble(t)); a[2]++; a[3]+= mapper.applyAsDouble(t);},
(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);
}
example:
System.out.println(
list.stream().collect(
Collectors.averagingDouble(new ToDoubleFunction<Dog>() {
@Override
public double applyAsDouble(Dog value) {
return value.getSteps();
}
})
)
);
6. 最大最小( maxBy/minBy )
获取最大最小值,根据提供的比较器返回最大/最小元素
//最大值
public static <T> Collector<T, ?, Optional<T>>
maxBy(Comparator<? super T> comparator) {
return reducing(BinaryOperator.maxBy(comparator));
}
//最小值
public static <T> Collector<T, ?, Optional<T>>
minBy(Comparator<? super T> comparator) {
return reducing(BinaryOperator.minBy(comparator));
}
example:
@Test
public void test5(){
System.out.println( list.stream().collect(Collectors.maxBy(new Comparator<Dog>() {
@Override
public int compare(Dog o1, Dog o2) {
return o1.getId() - o2.getId();
}
})));
}
7. 求和 summing*
用于元素间求和,也是有 int, double, long 三种变形,以 int 为例:
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);
}
example:
@Test
public void test7(){
Integer collect = list.stream().collect(Collectors.summingInt(new ToIntFunction<Dog>() {
@Override
public int applyAsInt(Dog value) {
return value.getSteps();
}
}));
System.out.println(collect);
}
8. 统计信息,summarizing*
用于计算流中元素的统计信息,例如计数、求和、最大值、最小值和平均值。有 summarizingDouble,summarizingInt,summarizingLong 三种变形
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);
}
example:
@Test
public void test6(){
DoubleSummaryStatistics collect = list.stream().collect(Collectors.summarizingDouble(new ToDoubleFunction<Dog>() {
@Override
public double applyAsDouble(Dog value) {
return value.getSteps();
}
}));
System.out.println( collect.getAverage() );
System.out.println( collect.getMax() );
System.out.println( collect.getCount() );
System.out.println( collect.getMin() );
System.out.println( collect.getSum() );
}
9. 归约 reducing
用于将流中的元素进行归约操作,也就是将一系列元素逐个处理并最终合并成一个结果。有三个方法重载如下:
//接收一个参数,参数规定了二元运算符,将每两个元素按照此规则进行归约,返回一个 Optional 。
public static <T> Collector<T, ?, Optional<T>> reducing(BinaryOperator<T> op)
//接收一个初始值和一个上述的二元运算符。
public static <T> Collector<T, ?, T> reducing(T identity, BinaryOperator<T> op)
//接收一个初始值,一个映射函数(用来修改元素),和一个二元运算符
public static <T, U> Collector<T, ?, U> reducing(U identity, Function<? super T, ? extends U> mapper, BinaryOperator<U> op)
example:
@Test
public void test8(){
//一个参数
Optional<Dog> col = list.stream().collect(Collectors.reducing(new BinaryOperator<Dog>() {
@Override
public Dog apply(Dog dog, Dog dog2) {
return dog.getSteps()>dog2.getSteps()?dog:dog2;
}
}));
if( col.isPresent() ){
System.out.println( col.get() );
}
//两个参数,带初始值
Dog yq = list.stream().collect(Collectors.reducing(
new Dog(1, 100, "yq"),
new BinaryOperator<Dog>() {
@Override
public Dog apply(Dog dog, Dog dog2) {
return dog.getSteps()>dog2.getSteps()?dog:dog2;
}
}
));
System.out.println( yq );
//三个参数,带初始值,元素映射规则
Dog yq1 = list.stream().collect(Collectors.reducing(
new Dog(1, 100, "yq"),
new Function<Dog, Dog>() {
@Override
public Dog apply(Dog s) {
s.setSteps(s.getSteps() * 1000);
return s;
}
},
new BinaryOperator<Dog>() {
@Override
public Dog apply(Dog dog, Dog dog2) {
return dog.getSteps()>dog2.getSteps()?dog:dog2;
}
}
));
System.out.println(yq1);
}
10. 求总数 counting
public static <T> Collector<T, ?, Long>
counting() {
return reducing(0L, e -> 1L, Long::sum);
}
example:
@Test
public void test9(){
System.out.println( list.stream().collect(Collectors.counting()) );
}
11. 分组 groupingBy
将流中的元素按照某个属性分组,有三个方法重载
//一个参数,根据某个属性分组
public static <T, K> Collector<T, ?, Map<K, List<T>>>
groupingBy(Function<? super T, ? extends K> classifier) {
return groupingBy(classifier, toList());
}
//两个参数,downstream 表示对分组后,每个组的操作
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);
}
//三个参数,mapFactory 表示分组运算结构的结果类型
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) {
example:
@Test
public void test11(){
//根据名字分组
System.out.println( list.stream().collect(
Collectors.groupingBy(
new Function<Dog, String>() {
@Override
public String apply(Dog dog) {
return dog.getName();
}
}
)
));
//根据名字分组,并且每组再取 step 的最小值
System.out.println( list.stream().collect(
Collectors.groupingBy(
new Function<Dog, String>() {
@Override
public String apply(Dog dog) {
return dog.getName();
}
},
Collectors.reducing(new BinaryOperator<Dog>() {
@Override
public Dog apply(Dog dog, Dog dog2) {
return dog.getSteps()>dog2.getSteps()?dog:dog2;
}
})
)
));
//根据名字分组,并且每组再取 step 的最小值,返回的是一个 HashMap 类型(获取每个分组最小的一个)
System.out.println( list.stream().collect(
Collectors.groupingBy(
new Function<Dog, String>() {
@Override
public String apply(Dog dog) {
return dog.getName();
}
},
new Supplier<Map<String, Optional<Dog>>>() {
@Override
public Map<String, Optional<Dog>> get() {
return new HashMap<>();
}
},
Collectors.reducing(new BinaryOperator<Dog>() {
@Override
public Dog apply(Dog dog, Dog dog2) {
return dog.getSteps()>dog2.getSteps()?dog:dog2;
}
})
)
));
}
12. 特殊分组 partitioningBy
用于根据指定的条件对流中的元素进行分区操作。分区操作将流中的元素分为满足条件和不满足条件两个部分,并分别收集到一个Map中。
有两个方法重载
//按照参数断言分成满足条件和不满足条件两个部分
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) {
}
example:
@Test
public void test10(){
//根据断言分组
Map<Boolean, List<Dog>> collect = list.stream().collect(Collectors.partitioningBy(new Predicate<Dog>() {
@Override
public boolean test(Dog dog) {
return dog.getSteps() % 2 == 0;
}
}));
System.out.println(collect);
//根据断言分组,再分别求和
System.out.println( list.stream().collect(Collectors.partitioningBy(
new Predicate<Dog>() {
@Override
public boolean test(Dog dog) {
return dog.getSteps() % 2 == 0;
}
},
Collectors.counting()
)));
}
13. 收集完成后应用一个最终转换操作 collectingAndThen
方法签名如下:
public static<T,A,R,RR> Collector<T,A,RR> collectingAndThen(Collector<T,A,R> downstream,
Function<R,RR> finisher) {
}
该方法接受两个参数:downstream 和 finisher。
- downstream是一个内部收集器,用于执行实际的收集操作,它将元素类型T,累加器类型A,以及结果类型R作为泛型参数。
- finisher是一个Function,它将从downstream收集器返回的结果类型R转换为类型RR的结果。
example:
@Test
public void test12(){
System.out.println( list.stream().collect(Collectors.collectingAndThen(
//先将 list 收集成 List<String>
Collectors.mapping(new Function<Dog, String>() {
@Override
public String apply(Dog t) {
return t.getName();
}
}, Collectors.toList()),
//再将转换后的 List<String> 转换成 Set<String>,最终返回的结果就是转换后的 set
new Function<List<String>, Set<String>>() {
@Override
public Set<String> apply(List<String> r) {
HashSet<String> set = new HashSet<>();
set.addAll(r);
return set;
}
}
)) );
}
2.4,并行流
Stream<Object> parallelStream = new ArrayList<>().parallelStream();
Stream<Object> parallel = new ArrayList<>().stream().parallel();
标签:return,stream,dog,基础,Dog,public,new,JAVA,Steam
From: https://www.cnblogs.com/cnff/p/17071346.html