Java(1.8)高级特性-流

什么是流

与文件的输入/输出流无关,流(Stream)是一种类似集合的概念。我们能够通过流来定义对集合“做什么”来实现我们的目标。

如何操作流

使用流来达成目的需要经过三步:

  1. 创建流
  2. 转换流(即将初始流通过我们定义的“做什么”将其转换成其他流)
  3. 终结操作(terminal peration,从最终的流中获得我们需要的数据)

下面是一个例子,该例子创建了一个Integer类型的流,并对流中的所有元素调用x=x+1的方法,最后使用reduce终止操作获得整个流的和。流的操作是尽可能惰性执行的,直到需要结果时才会执行,即应用了终止操作后,之前的惰性操作会强制执行,流就失去了作用。

Stream s=Stream.of(1,2,3,4);
int sum=s.map(x->x+1).reduce(0,(x,y)->{x+y});

创建流

//创建一个元素的流
public static Stream of(T t)
//从多个元素中创建流,参数可以是数组也可以是多个单值 
public static Stream of(T... values) 
//创建一个空流
public static Stream empty() 
//创建一个无限流,元素分别为seed,f(seed),f(f(seed)),....
//例子:Stream s=Stream.iterate(1,x->x+1);
public static Stream iterate(final T seed, final UnaryOperator f)
//通过Supplier创建无限流 
//例子:Stream s=Stream.generate(Math::random)
public static Stream generate(Supplier s)

Stream类中提供了如上方法创建一个流。除此之外,Arrays、集合类、Files也都提供了创建流的方法。

//从一个数组的给定范围创建流
public static  Stream stream(T[] array, int startInclusive, int endExclusive)
//从集合创建流
default Stream stream()
//从文件创建流,元素为文件中的一行
public static Stream lines(Path path, Charset cs) throws IOException 

转换流

Stream提供了多种方法来进行转换流。

Stream filter(Predicate predicate);
 Stream map(Function mapper);
 Stream flatMap(Function> mapper);

这是三种主要的流转换方法。

  • filter
    filter的引元是Predicate,即从T到boolean的函数,可以使用此方法获得满足条件的流,比如通过Stream s=Stream.of(1,2,3,4,5).filter(x->x>3)我们就可以获得大于3的流。
  • map
    mapStream中的每个元素调用mapper方法,比如Stream s=Stream.of(1,2,3,4,5).map(x->x=x+1)可以得到每个元素加一的流。
  • flatmap
    flatmap可以处理后得到的Stream>平摊为Stream的流。比如Stream.of("apple","bit").map(x->letters(x))将得到[["a","p","p","l","e"],["b","i","t"]],而Stream.of("apple","bit").flatmap(x->letters(x))将得到["a","p","p","l","e","b","i","t"]

除了以上3种方法,Stream类还提供了获取子流、排序等方法。

//获取前maxSize个元素的流
Stream limit(long maxSize);
//跳过前n个元素的流
Stream skip(long n);
//将两个流合并成一个流
public static  Stream concat(Stream a, Stream b) ;
//对流进行排序
Stream sorted();
Stream sorted(Comparator comparator);
//移除流中重复的元素
Stream distinct();
//每个元素被使用时都会先传递给action方法,这个方法主要被用来debug
//例子:Stream.of(1,2,3,4).peek(x->System.out.print(x)).map(x->x=x+1)
Stream peek(Consumer action);

终结操作

定义了流并进行转换后,我们终于可以得到我们想要的数据。Stream提供了如下的终结操作。

Optional min(Comparator comparator);
Optional max(Comparator comparator);
long count();
boolean anyMatch(Predicate predicate);
boolean allMatch(Predicate predicate);
boolean noneMatch(Predicate predicate);
void forEach(Consumer action);
void forEachOrdered(Consumer action);
Optional findFirst();
Optional findAny();
//可以通过reduce操作对流中的数据进行处理。如果定义了简约操作(accumulator)op
//那么返回的值为 v1 op v2 op v3 ...
//可以通过定义identity,当流为空时返回该值
Optional reduce(BinaryOperator accumulator);
T reduce(T identity, BinaryOperator accumulator);
 U reduce(U identity,BiFunction accumulator,BinaryOperator combiner);

当然,转换后的流并不一定非要进行上述的终结操作,我们也可以将得到的结果存入集合中来使用。

//获取流的iterator,遍历方法与集合的iterator相同
Iterator iterator();
Object[] toArray();
 A[] toArray(IntFunction generator);
 R collect(Collector collector);
 R collect(Supplier supplier,BiConsumer accumulator,BiConsumer combiner)

对于其中的collect方法,可以通过定义不同收集器来获得不同的集合类型,比如Stream.of(1,2,3,4).collect(Collectors.toSet())来获得Set。收集器Collectors有如下这些方法(部分),方法的说明在注释部分。

public static  Collector> toList();
public static  Collector> toSet();
//通过keyMapper生成key,通过valueMapper生成value,通过mergeFunction合并key相同的对象
//例子:Map idName=people.collect(Collectors.toMap(Person::getId,Person::getName,
//        (existValue,newValue)->existValue))
public static  Collector> toMap(Function keyMapper
    ,Function valueMapper);
public static  Collector> toMap(Function keyMapper
    ,Function valueMapper,BinaryOperator mergeFunction)
//将元素收集到指定的集合中
//例子:person.collect(Collectors.toCollection(TreeSet::new))
public static > 
    Collector toCollection(Supplier collectionFactory);
//合并字符串,可以自定义分隔符、第一个元素的前缀和最后一个元素的后缀
public static Collector joining();
public static Collector joining(CharSequence delimiter);
public static Collector joining(CharSequence delimiter,
                                                             CharSequence prefix,
                                                             CharSequence suffix);

//生成(Int|Long|Double)SummaryStatistics
/* (Int|Long|Double)SummaryStatistics可以通过
 *   getCount()产生元素个数
 *   getSum()求和
 *   getAverage()求平均数
 *   getMax()、getMin() 获得最大/小值,如果没有元素时返回(MAX|MIN)_VALUE
 *   例子:Stream.of(1,2,3,4).collect(Collectors.summaringzingInt(x->x)).getCount();
 */

public static 
    Collector summarizingInt(ToIntFunction mapper);
public static 
    Collector summarizingLong(ToLongFunction mapper);
public static 
    Collector summarizingDouble(ToDoubleFunction mapper)

//对映射表中的元素进行分组   
/*
 * classifier为分类的标准,比如Persion::getName以名字分组
 * mapFactory为映射表的工厂类,比如TreeMap::new
 * downstream为对分类后的数据进行的操作,有counting()、summingInt()、maxBy(Cmparator)、minBy()
 * mapping(mapper,downstream)
 */
//例子:people.collect(
//          Collectors.groupingBy(
//              Person::getName,
//              Collectors.mapping(Person::getId,Collectors.counting())))
public static  Collector>>
    groupingBy(Function classifier)
public static 
    Collector> groupingBy(Function classifier,
         Collector downstream)
public static >
    Collector groupingBy(Function classifier,
         Supplier mapFactory,Collector downstream)

并行流

我们可以创建并行流来加快流的处理速度。获取流的方法有两种,一是使用Strea.parallel(),二是使用Collection.parallelStreamm()从集合中获取并行流。只要终结方法执行时,流处于并行状态,所有的中间操作都将并行执行。

你可能感兴趣的:(Java(1.8)高级特性-流)