这里不再介绍 stream 和 lamda表达式原理 旨在用最短的时间学会用stream流处理集合。
使用流的流程可以简单为3步.
1.获取流
2.操作流 ( 有些操作不需要使用stream,如forEach sort)
3.聚合 (如果是遍历这种操作就不需要聚合)
1.获取流
如果是 Collection对象,直接 .stream() 方法即可.如:
Stream stream = list.stream();
Stream parallelStream = list.parallelStream(); // 并行流
关于 Stream 和 ParallelStream 的区别可以自行搜索. 一句话概括:
ParallelStream 会为每个cpu单独开一个线程,所以一般来说 ,在多核下速度比stream快,但是不保证元素处理顺序.
如果是 数组,则可以使用
Stream stream = Arrays.stream( T[] );
2.操作流
比较常用的操作 : 排序( sorted )遍历 ( forEach ),过滤( filter ),映射( map )
@Test
public void test2() throws Exception {
List list = new ArrayList<>();
list.add("a");
list.add("ab");
list.add("abc");
list.add("b");
list.add("bc");
list.sort( (a, b) -> a.length() - b.length());
System.out.println(list);
}
sort里要求传入一个 实现了 Comparator 接口实例 我们可以观察一下 Comparator接口
@FunctionalInterface
public interface Comparator {
int compare(T o1, T o2);
}
被@FunctionalInterface标注的接口是函数式接口 ,它有且只有一个抽象方法, 函数式接口都可以使用lambda表达式来简化语法.
这里拿sort方法举例 有2个参数 o1, o2 对应了
list.sort( (a, b) -> { return a.length() - b.length() ; } );
list.sort( (a, b) -> a.length() - b.length());
list.sort( (a, b) -> a.length() - b.length() ); 注意: 这里你也可以写为 ( String a ,String b ) 但是由于lambda自带的类型推倒,IDE或者编译器都能自动识别此处的a和b都是String对象.
[ → ] 是连参数和方法体的符号 如果 → 只有一句话 则可以省略 { } 和return ,如下列代码.
下面看看 stream的filter方法 它要求传入一个 Predicate接口的实例 里面的抽象方法要求返回一个boolean值.
boolean test(T t);
因此我们可以写为
list.stream().filter( every -> every .length() > 2 ); // 这里的every指每一个元素 .
注: filter()的懒加载机制决定了 ,它不会对流做任何处理, 它的实际动作的取决于后续操作.
map是相对来说复杂一些的函数, 它可以把一种stream映射为另外一种
但是根据之前的经验 我们也可以处理它
map方法要求传入一个 Function对象. 里面有一个抽象方法。
R apply(T t);
如:
List list = new ArrayList<>();
Stream integerStream = list.stream().map(every -> every.length() );
我们的list是一个 String类型的list ,然而经过 map以后 变成了了 Integer (实际是String对象的length( ) )
3. 聚合
聚合是相对来说比较难操作的一步, 不太熟悉的人可以通过大量练习来熟练 ,在此只举比较常用的2个例子
List collect = list.stream().map(every -> every.length()).collect(Collectors.toList()); //直接聚合为list (元素已被映射为Integer)
Map map = list.stream().collect(
Collectors.toMap( //toMap()要求传入2个Function实例
Function.identity(), //如果用自身做key 则直接使用Function.identity()
item -> item.length()) // 用长度做value;
);