本文整理下Java8引入的Stream流,能大大简化集合类的操作,同时引入了常用的filter, map, reduce等高阶函数的操作类型。

Stream有点类似C++库boost.Range的概念,是基于容器的迭代范围的一个视图,并能够给予视图做各种算法。

Stream的引入

先看一个例子:

Integer [] ary = {1,2,3,4,5,6,7,8,9};
ArrayList<Integer> al = new ArrayList<Integer>(Arrays.asList(ary));
al.stream()
    .filter( x -> x%2==1 )
    .forEach(x -> System.out.println(x));

long count = al.stream()
    .filter( x -> x%2==0 )
    .count();    
输出:
1
3
5
7
9

惰性求值 和 及早求值

如果返回值是Stream,那么是惰性求值; 如果返回值是另一个值或为空,那么就是及早求值

使用这些操作的理想方式就是形成一个惰性求值的链,最后用一个及早求值的操作返回想要的结果,这正是它的合理之处。

常用操作

collect(toList())

由 Stream 里的值生成一个列表

List<String> collected = 
    Stream.of("a", "b", "c").collect(Collectors.toList());
System.out.println(
  names.stream()
       .filter(name > name.startsWith("J"))
       .filter(name > name.length() > 3)
       .map(name > name.toUpperCase())
       .collect(Collectors.joining(", ")));

map

如果有一个函数可以将一种类型的值转换成另外一种类型,map 操作就可以使用该函数,将一个流中的值转换成一个新的流。

List<Integer> collected = Stream.of("12", "34", "56")
    .map( x -> Integer.parseInt(x) )
    .collect( Collectors.toList() );

filter

遍历数据并检查其中的元素来过滤产生新的Stream

List<String> beginningWithNumbers = Stream.of("a", "1abc", "abc1")
    .filter(value -> Character.isDigit(value.charAt(0)))
    .collect(Collectors.toList());

flatMap

用多个集合生成相应的Stream,最后把Stream的内容平铺成一个大的Stream

List<String> together = Stream.of(Arrays.asList(1, 2), Arrays.asList(3, 4))
    .flatMap(numbers -> numbers.stream().map( x -> ""+x ))
    .collect(Collectors.toList());
// {"1","2","3","4"}

max和min

提取Stream中的最大/最小值,支持传递一个比较函数,返回一个Optional对象

int m = Stream.of(1,5,3)
    .max((x,y) -> {
        if (x>y) {
            return 1;
        } else if ( x<y ) {
            return -1;
        } else {
            return 0;
        }
    })
    .get();
// m: 5    

reduce

reduce 操作可以实现从一组值中针对每个参数迭代的生成一个值

int count = Stream.of(1, 2, 3)
   .reduce(0, (acc, element) -> acc + element);
// count: 6

sorted

我们能够以自然序或着用Comparator 接口定义的排序规则来排序一个流。

Comparator 能用lambada表达式来初始化,我们还能够逆序一个已经排序的流。

  1. sorted() 默认使用自然序排序, 其中的元素必须实现Comparable 接口
  2. sorted(Comparator<? super T> comparator) :我们可以使用lambada 来创建一个Comparator 实例。可以按照升序或着降序来排序元素。
public static List<String> getModelsAfter2000UsingPipeline(
    List<Car> cars) {
    return 
      cars.stream()
          .filter(car > car.getYear() > 2000)
          .sorted(Comparator.comparing(Car::getYear))
          .map(Car::getModel)
          .collect(toList());
}

并行处理

numbers.stream()
      .parallel()
      .map(Sample::simulateTimeConsumingComputation)

高阶函数

高阶函数是指接受另外一个函数作为参数,或返回一个函数的函数。

Stream支持的操作大部分都是高阶函数。

// 对谓词函数取非操作
private static <T> Predicate<T> not(Predicate<? super T> predicate) {
    return x -> !predicate.test(x);
}

boolean r = not( (Integer x) -> {return x>5;} ).test( 10 );
// r: false