美文网首页
Java(1.8)高级特性-流

Java(1.8)高级特性-流

作者: czn5991 | 来源:发表于2019-03-31 14:47 被阅读0次

什么是流

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

如何操作流

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

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

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

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

创建流

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

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

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

转换流

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

Stream<T> filter(Predicate<? super T> predicate);
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);

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

  • filter
    filter的引元是Predicate<T>,即从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<T>>平摊为Stream<T>的流。比如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<T> limit(long maxSize);
//跳过前n个元素的流
Stream<T> skip(long n);
//将两个流合并成一个流
public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) ;
//对流进行排序
Stream<T> sorted();
Stream<T> sorted(Comparator<? super T> comparator);
//移除流中重复的元素
Stream<T> distinct();
//每个元素被使用时都会先传递给action方法,这个方法主要被用来debug
//例子:Stream.of(1,2,3,4).peek(x->System.out.print(x)).map(x->x=x+1)
Stream<T> peek(Consumer<? super T> action);

终结操作

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

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

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

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

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

public static <T> Collector<T, ?, List<T>> toList();
public static <T> Collector<T, ?, Set<T>> toSet();
//通过keyMapper生成key,通过valueMapper生成value,通过mergeFunction合并key相同的对象
//例子:Map<integer,String> idName=people.collect(Collectors.toMap(Person::getId,Person::getName,
//        (existValue,newValue)->existValue))
public static <T, K, U> Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper
    ,Function<? super T, ? extends U> valueMapper);
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)
//将元素收集到指定的集合中
//例子:person.collect(Collectors.toCollection(TreeSet::new))
public static <T, C extends Collection<T>> 
    Collector<T, ?, C> toCollection(Supplier<C> collectionFactory);
//合并字符串,可以自定义分隔符、第一个元素的前缀和最后一个元素的后缀
public static Collector<CharSequence, ?, String> joining();
public static Collector<CharSequence, ?, String> joining(CharSequence delimiter);
public static Collector<CharSequence, ?, String> 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 <T>
    Collector<T, ?, IntSummaryStatistics> summarizingInt(ToIntFunction<? super T> mapper);
public static <T>
    Collector<T, ?, LongSummaryStatistics> summarizingLong(ToLongFunction<? super T> mapper);
public static <T>
    Collector<T, ?, DoubleSummaryStatistics> summarizingDouble(ToDoubleFunction<? super T> 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 <T, K> Collector<T, ?, Map<K, List<T>>>
    groupingBy(Function<? super T, ? extends K> classifier)
public static <T, K, A, D>
    Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier,
         Collector<? super T, A, D> downstream)
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)

并行流

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

相关文章

  • Java(1.8)高级特性-流

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

  • Java(1.8)高级特性-网络

    网络编程涉及到了最基础的Socket编程,以及基于次的网络服务。下面将介绍在Java中如何实现Socket以及一些...

  • Java(1.8)高级特性-安全

    这里的安全包括了Java虚拟机如何保障自己的安全,不被恶意程序所侵害和Java提供的加密方法。 虚拟机的安全 Ja...

  • 使用Netty,我们到底在开发些什么?

    您可能感兴趣的文章: 大数据成神之路系列:Java高级特性增强-集合Java高级特性增强-多线程Java高级特性增...

  • Java(1.8)高级特性-输入输出

    I/O是一个考试必考,面试必问,又非常繁琐的知识点。各种分不清的类和初始化顺序一直让我觉得很琐碎。当我整体看完I/...

  • Android Studio 3.0 支持直接添加Java1.8

    Android Studio 3.0 以上直接添加Java1.8,就可以使用java1.8特性,比如对lambda...

  • Java 1.8特性

    声明:本栏目所使用的素材都是凯哥学堂VIP学员所写,学员有权匿名,对文章有最终解释权;凯哥学堂旨在促进VIP学员互...

  • java高级特性-----注解(Annotation)

    java高级特性-----注解(Annotation)

  • java-java8新特性

    java8其实就是java1.8,java1.8作为java的一个重大版本,以下是它新增的一些新特性 1、 lam...

  • 字节流与缓冲流

    java零基础入门-高级特性篇(十二) IO 流 2 本章先来看两大“流”派中的字节流。字节流相对字符流总体结构简...

网友评论

      本文标题:Java(1.8)高级特性-流

      本文链接:https://www.haomeiwen.com/subject/wqawvqtx.html