一 Stream的flatMap
操作符定义
函数签名:Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
R 是新流中元素的类型
T 是旧流中的元素的类型
Function的意义是:接收一个参数,返回一个结果。
连接起来就是:flatMap将旧流中类型为T的每个元素,转为一个新的子流,子流中元素的
类型是R,并将子流汇总为总流
旧流中有几个元素,就会有几个子流
实例:将数组交叉输出
public class StreamTest {
public static void main(String[] args) {
//将每个stringList元素+integerList元素前缀输出
List<Integer> integerList = Arrays.asList(1, 2, 3, 4);
List<String> stringList = Arrays.asList("一", "二", "三", "四");
integerList.stream()
.flatMap(it->stringList.stream().map(item->it+" "+item))
.forEach(System.out::println);
//相当于子流是stringList元素加前缀输出
}
}
二 Stream的并行流
Stream支持并行和串行的操作,串行是单线程的比较耗时,并行时多线程运行,运行效率高。Stream并行的操作比较简单,就是在流中添加parallel()操作。
以排序为例
public class StreamTest {
public static void main(String[] args) {
List<UUID> list = new ArrayList<>(5000000);
for (int i = 0; i < 5000000; i++) {
list.add(i, UUID.randomUUID());
}
long startTime= System.currentTimeMillis();
list.stream()
.sorted()
.count();
long endTime=System.currentTimeMillis();
System.out.println((endTime-startTime));
startTime= System.currentTimeMillis();
list.stream()
.parallel()//添加该操作符即可
.sorted()
.count();
endTime=System.currentTimeMillis();
System.out.println((endTime-startTime));
//运行结果
3698
1401 //并行更加有效率
}
}
三 Stream的分组和分区
Stream的分组和分区,需要的操作符是collect
操作符的签名:R collect(Collector<? super T, A, R> collector)
R 是返回结果的类型
T 流中元素的类型
A 累加器的类型
该操作的含义:使用collector对流中的元素进行聚合的操作,collector封装了
collect(Supplier, BiConsumer, BiConsumer)中的参数,用于重用收集策略,比如toList,和收集操作,比如分组和分区。
Collector:聚合操作,将流中元素收集至一个可变的容器中(List,Map等)。常见的聚合操作有:将元素添加至集合,拼接字符串,常见的数字计算(求和、最值、均值)等,Collectors中有类似的工具类方法。
Collector功能的实现主要是通过四个抽象方法:
supplier():创建容器结果
accumulator():将元素添加至容器中
combiner():将两个容器合二为一(并行时)
supplier():可选的转换操作
分组实现 Collectors的groupingBy方法
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)
参数介绍
M 是返回结果的类型,是Map的子类。分组的结果是Map
T 是流中元素的类型
K 是结果Map的key的类型
A 是结果value的类型
D 是结果Map的value的容器结果类型
classifier是将流中元素转为结果Map的key
mapFactory是结果的map
downstream是整理map的value,因为有可能是多级分组,所以也是Collector
分组案例 将List<String> 按其长度分组
public class StreamTest {
public static void main(String[] args) {
List<String> stringList = Arrays.asList("Hello", "World", "Java", "I");
TreeMap<Integer, List<String>> collect = stringList.stream()
.collect(Collectors.groupingBy(
String::length,//key是字符串的长度
TreeMap::new,//结果是TreeMap
Collectors.toList()));//value是list
System.out.println(collect);
}
}
分区实现 Collectors的partitioningBy方法
分区是分组的特殊化,就是按照predicate分成两组而已
//任然上例为例,将长度改为长短。凡是长度小4的在一组,长度大于5的在另外一组
public class StreamTest {
public static void main(String[] args) {
List<String> stringList = Arrays.asList("Hello", "World", "Java", "I");
Map<Boolean, List<String>> map = stringList.stream()
.collect(Collectors.partitioningBy(
it -> it.length() > 4,//predicate的条件
Collectors.toList()
));
System.out.println(map);
}
}
网友评论