当前位置: 首页 > news >正文

青岛主流网站/河南自助建站seo公司

青岛主流网站,河南自助建站seo公司,公司内部网站创建,江阴外贸网站建设公司Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作,或者大批量数据操作。通常我们需要多行代码才能完成的操作,借助于Stream流式处理可以很简单的实现。 Stream 不是集合元素,它不是…

       Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作,或者大批量数据操作。通常我们需要多行代码才能完成的操作,借助于Stream流式处理可以很简单的实现。

       Stream 不是集合元素,它不是数据结构并不保存数据,它是有关算法和计算的,它更像一个高级版本的Iterator。同时Stream提供串行和并行两种模式进行汇聚操作。比如你的Stream里面有很多数据,Stream可以开多个线程每个线程处理一部分。最后把结果汇总起来。

       在开始之前我们先用一个图来整体的概况下Stream。如下所示:

Stream

一 Stream流创建

       想使用Stream流,首先咱得先创建一个Stream流对象。创建Steam需要数据源.这些数据源可以是集合、可以是数组、可以使文件、甚至是你可以去自定义等等。

1.1 集合作为Stream数据源

       集合Collection作为Stream的数据源,应该也是我们用的最多的一种数据源了。Collection里面也提供了一些方法帮助我们把集合Collection转换成Stream。

1.1.1 stream()方法

       调用Collection.stream()函数创建一个Stream对象。相当于把集合Collection里面的数据都导入到了Stream里面去了。

    @Testpublic void collectionStream() {List<Integer> list = Lists.newArrayList(1, 2, 3, 4, 5);// 使用List创建一个流对象Stream<Integer> stream = list.stream();// TODO: 对流对象做处理}

1.1.2 parallelStream()方法

       调用Collection.parallelStream()创建Stream对象。

    @Testpublic void collectionParallelStream() {List<Integer> list = Lists.newArrayList(1, 2, 3, 4, 5);// 使用List创建一个流对象Stream<Integer> stream = list.parallelStream();// TODO: 对流对象做处理}

parallelStream()与stream()区别是parallelStream()使用多线程并发处理最后子啊汇总结果,而stream()是单线程。所以相对来说parallelStream()效率要稍微高点。

1.2 数组作为Stream数据源

       数组也可以作为Stream的数据源。我们可以通过Arrays.stream()方法把一个数组转化成流对象。Arrays.stream()方法很丰富,有很多个。大家可以根据实际情况使用。

    @Testpublic void arrayStream() {int[] intArray = new int[10];for (int index = 0; index < intArray.length; index++) {intArray[index] = index;}// 使用数组创建一个流对象IntStream stream = Arrays.stream(intArray);// TODO: 对流对象做处理}

1.3 BufferedReader作为Stream数据源

       我们也可以把BufferedReader里面lines方法把BufferedReader里面每一行的数据作为数据源生成一个Stream对象。

    @Testpublic void bufferedReaderStream() {File file = new File("/home/tuacy/github/google-guava-study/src/main/resources/application.yml");try {// 把文件里面的内容一行一行的读出来BufferedReader in = new BufferedReader(new FileReader(file));// 生成一个Stream对象Stream<String> stream = in.lines();// TODO: 对流对象做处理} catch (IOException e) {e.printStackTrace();}}

1.4 File作为Stream数据源

       Files里面多个生成Stream对象的方法,都是对Path(文件)的操作。有的是指定Path目录下所有的子文件(所有的子文件相当于是一个列表了)作为Stream数据源,有的把指定Path文件里面的每一行数据作为Stream的数据源。

1.4.1 Files.list()

       列出指定Path下面的所有文件。把这些文件作为Stream数据源。

    @Testpublic void fileListStream() {Path path = Paths.get("D:\\job\\git\\google-guava-study\\src\\main\\resources");try {// 找到指定path下的所有的文件Stream<Path> stream = Files.list(path);// TODO: 对流对象做处理} catch (IOException e) {e.printStackTrace();}}

1.4.2 Files.walk()

       Files.walk()方法用于遍历子文件(包括文件夹)。参数maxDepth用于指定遍历的深度。把子文件(子文件夹)作为Stream数据源。

    @Testpublic void fileWalkStream() {Path path = Paths.get("D:\\job\\git\\google-guava-study\\src\\main\\resources");try {// 第二个参数用于指定遍历几层Stream<Path> stream = Files.walk(path, 2);// TODO: 对流对象做处理} catch (IOException e) {e.printStackTrace();}}

1.4.3 Files.find()

       Files.find方法用于遍历查找(过滤)子文件。参数里面会指定查询(过滤)条件。把过滤出来的子文件作为Stream的数据源。

    @Testpublic void fileFindStream() {Path path = Paths.get("D:\\job\\git\\google-guava-study\\src\\main\\resources");try {// 找到指定path下的所有不是目录的文件Stream<Path> stream = Files.find(path, 2, (path1, basicFileAttributes) -> {// 过滤掉目录文件return !basicFileAttributes.isDirectory();});// TODO: 对流对象做处理} catch (IOException e) {e.printStackTrace();}}

1.4.4 Files.lines()

       Files.lines方法是把指定Path文件里面的每一行内容作为Stream的数据源。

    @Testpublic void fileLineStream() {Path path = Paths.get("D:\\job\\git\\google-guava-study\\src\\main\\resources\\application.yml");try {// 生成一个Stream对象Stream<String> stream = Files.lines(path);// TODO: 对流对象做处理} catch (IOException e) {e.printStackTrace();}}

1.5 自己构建Stream

       我们也可以自己去创建Stream自己提供数据源。Stream类里面提供of()、iterate()、generate()、builder()等一些方法来创建Stream,Stream的数据源我们自己提供。

1.5.1 Stream.of()

       Stream.of()函数参数就是数据源。

       Stream<Integer> ofSteam = Stream.of(1,2,3,4,5,6);

1.5.2 Stream.iterate()

       Stream.iterate()可以用来生成无限流,函数需要两个参数:第一个参数是初始值、第二个参数用于确定怎么根据前一个元素的值生成下一个元素。

        // Stream.iterate() 流式迭代器 Stream.iterate()函数的第二个参数告诉你怎么去生成下一个元素Stream<BigInteger> integers = Stream.iterate(BigInteger.ONE,new UnaryOperator<BigInteger>() {@Overridepublic BigInteger apply(BigInteger bigInteger) {return bigInteger.add(BigInteger.ONE);}});// 简单输出integers.limit(10).forEach(new Consumer<BigInteger>() {@Overridepublic void accept(BigInteger bigInteger) {System.out.println(bigInteger.intValue());}});

1.5.3 Stream.generate()

       Stream.generate()也是用于生成一个无限流。参数用于获取每个元素。

        // Stream.generate() 生成无限流Stream<Double> generateA = Stream.generate(new Supplier<Double>() {@Overridepublic Double get() {return java.lang.Math.random() * 100;}});// 简单输出前10个值generateA.limit(10).forEach(new Consumer<Double>() {@Overridepublic void accept(Double bigInteger) {System.out.println(bigInteger.intValue());}});

1.5.4 Stream.build()

       Stream.build()通过建造者模式生成一个Stream建造器。然后把需要加入Stream里面的数据源一个一个通过建造器添加进去。

        // Stream.builder()构造一个Stream对象Stream.Builder<Integer> build = Stream.<Integer>builder().add(1).add(2).add(3);build.accept(4);build.accept(5);build.build().forEach(new Consumer<Integer>() {@Overridepublic void accept(Integer integer) {System.out.println(integer);}});// TODO: 对流对象做处理

1.6 其他Stream创建方式

       Stream其他创建方式我们就不一一举例了。有如下方式。

  • Random.ints()。
  • BitSet.stream()。
  • Pattern.splitAsStream(java.lang.CharSequence)
  • JarFile.stream()。

二 Stream流操作(操作符)

       Stream流操作就是对Stream流的各种处理。Stream里面已经给提供了很多中间操作(我们一般称之为操作符)。

Stream提供的流操作符。

Stream流操作符解释
filter过滤
map对流里面每个元素做转换
mapToInt把流里面的每个元素转换成int
mapToLong流里面每个元素转换成long
mapToDouble流里面每个元素转换成double
flatMap流里面每个元素转换成Steam对象,最后平铺成一个Stream对象
flatMapToInt流里面每个元素转换成IntStream对象,最后平铺成一个IntStream对象
flatMapToLong流里面每个元素转换成LongStream对象,最后平铺成一个LongStream对象
flatMapToDouble流里面每个元素转换成DoubleStream对象,最后平铺成一个DoubleStream对象
distinct去重
sorted排序
peek查看流里面的每个元素
limit返回前n个数
skip跳过前n个元素

       Stream提供了这么多的操作符,而且这些操作符是可以组合起来使用。关于每个操作符的使用我们用一个简单的实例代码来说明。

2.1 filter

       filter用于对流里面的数据做过滤操作。

    // 过滤@Testpublic void filter() {Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);// 过滤出偶数Stream<Integer> filterStream = stream.filter(new Predicate<Integer>() {@Overridepublic boolean test(Integer integer) {return integer % 2 == 0;}});// 简单输出filterStream.forEach(new Consumer<Integer>() {@Overridepublic void accept(Integer integer) {System.out.println(integer);}});}

2.2 map

       map用于对流里面的元素做转换。

    // 转换@Testpublic void map() {Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);// 整数转换为StringStream<String> mapStream = stream.map(new Function<Integer, String>(){@Overridepublic String apply(Integer integer) {return String.valueOf(integer);}});// 简单输出mapStream.forEach(new Consumer<String>() {@Overridepublic void accept(String integer) {System.out.println(integer);}});}

2.3 mapToInt、mapToLong、mapToDouble

       mapToInt、mapToLong、mapToDouble用于将流里面的元素转换成对应的类型。

    // 转换@Testpublic void mapToInt() {Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);// 整数转换为StringIntStream mapStream = stream.mapToInt(new ToIntFunction<Integer>(){@Overridepublic int applyAsInt(Integer value) {return value == null ? 0 : value;}});// 简单输出总和System.out.println(mapStream.sum());}

2.4 flatMap、flatMapToInt、flatMapToLong、flatMapToDouble

       flatMap、flatMapToInt、flatMapToLong、flatMapToDouble也是对每个元素的转换,不过他们和map的不同点在于,他们是吧每个元素转换成一个Stream流,最终在平铺成一个Stream流。

    // 转换@Testpublic void flatMap() {Stream<String> stream = Stream.of("java:1", "android:2", "ios:3");// 整数转换为StringStream<String> rerStream = stream.flatMap(new Function<String, Stream<String>>() {@Overridepublic Stream<String> apply(String s) {// 分割Iterable<String> iterableList = Splitter.on(':').trimResults() // 移除前面和后面的空白.omitEmptyStrings().split(s);return Lists.newArrayList(iterableList).parallelStream();}});// 简单输出rerStream.forEach(new Consumer<String>() {@Overridepublic void accept(String integer) {System.out.println(integer);}});}
    // 转换@Testpublic void reduce() {Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);// 所有的元素相加,在加上20Integer reduceValue = stream.reduce(20, new BinaryOperator<Integer>() {@Overridepublic Integer apply(Integer integer, Integer integer2) {System.out.println(integer);System.out.println(integer2);return integer + integer2;}});System.out.println(reduceValue);}

2.5 distinct

       distinct操作符用于去重。

    // 去重@Testpublic void distinct() {Stream<Integer> stream = Stream.of(1,2,3,1,2,3,1,2,3);Stream<Integer> rerStream = stream.distinct();// 简单输出rerStream.forEach(new Consumer<Integer>() {@Overridepublic void accept(Integer integer) {System.out.println(integer);}});}

2.6 sorted

       sorted操作符用于对流里面的元素排序。

    // 排序@Testpublic void sorted() {Stream<Integer> stream = Stream.of(1,2,3,2,5,4,8,6);Stream<Integer> rerStream = stream.sorted(new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {if (o1.equals(o2)) {return 0;} else {return o1 > o2 ? 1 : -1;}}});// 简单输出rerStream.forEach(new Consumer<Integer>() {@Overridepublic void accept(Integer integer) {System.out.println(integer);}});}

2.7 peek

       peek操作符用于查看流里面的每个元素。在多个操作符同时使用的时候的中间加入peek操作符可以参考每个操作符之后的结果。

    // 查看@Testpublic void peek() {Stream<Integer> stream = Stream.of(1,2,3,1,2,3,1,2,3);// 查看Stream<Integer> reStream = stream.peek(new Consumer<Integer>() {@Overridepublic void accept(Integer integer) {System.out.println(integer);}});// 简单输出reStream.forEach(new Consumer<Integer>() {@Overridepublic void accept(Integer integer) {System.out.println(integer);}});}

2.8 limit

       limit操作符用于取流前面多少个元素。

    // limit@Testpublic void limit() {Stream<Integer> stream = Stream.of(1,2,3,1,2,3,1,2,3);// limitStream<Integer> reStream = stream.limit(3);// 简单输出reStream.forEach(new Consumer<Integer>() {@Overridepublic void accept(Integer integer) {System.out.println(integer);}});}

2.9 skip

       skip用于跳过里面的多少个元素。

    // skip@Testpublic void skip() {Stream<Integer> stream = Stream.of(1,2,3,1,2,3,1,2,3);// skipStream<Integer> reStream = stream.skip(3);// 简单输出reStream.forEach(new Consumer<Integer>() {@Overridepublic void accept(Integer integer) {System.out.println(integer);}});}

三. Stream流终端操作

       Stream流终端操作是流式处理的最后一步,之前已经对Stream做了一系列的处理之后。该拿出结果了。我们可以在终端操作中实现对流的遍历、查找、归约、收集等等一系列的操作。

Stream流终端操作提供的函数有

终端操作符解释
forEach遍历
forEachOrdered如果流里面的元素是有顺序的则按顺序遍历
toArray转换成数组
reduce归约 - 根据一定的规则将Stream中的元素进行计算后返回一个唯一的值
collect收集 - 对处理结果的封装
min最小值
max最大值
count元素的个数
anyMatch任何一个匹配到了就返回true
allMatch所有都匹配上了就返回true
noneMatch没有一个匹配上就返回true
findFirst返回满足条件的第一个元素
findAny返回某个元素

       关于Stream终端操作部分,我们就着重讲下collect()函数的使用。因为其他的终端操作符都很好理解。collect()稍稍复杂一点。

3.1 collect()

       collect()的使用主要在于对参数的理解,所有我们这里要专门讲下collect()函数的参数Collector这个类,以及怎么去构建Collector对象。只有在了解了这些之后,咱们才可以熟练的把他们用在各种场景中。

3.1.1 Collector

       Collector类目前没别的用处,就是专门用来作为Stream的collect()方法的参数的。把Stream里面的数据转换成我们最终想要的结果上。

Collector各个方法,以及每个泛型的介绍,都在下面详细的解释了。如果有疑问可以留言。

/*** Collector是专门用来作为Stream的collect方法的参数的** 泛型含义* T:是流中要收集的对象的泛型* A:是累加器的类型,累加器是在收集过程中用于累积部分结果的对象。* R:是收集操作得到的对象(通常但不一定是集合)的类型。*/
public interface Collector<T, A, R> {/*** 生成结果容器,容器类型为A* (多线程的情况下可能会调用多次,开多个线程同时去处理一个流,每个线程调用一次)*/Supplier<A> supplier();/*** A对应supplier()函数创建的结果容器* T对应Stream流里面一个一个的元素* 用于消费元素,也就是归纳元素,一般在这个里面把流里面的元素T(也可以转换下)放到supplier()创建的结果T里面去*/BiConsumer<A, T> accumulator();/*** 用于两个两个合并并行执行的线程的执行结果,将其合并为一个最终结果A* 多线程的情况下,多个线程并行执行。每个线程产生一个结果*/BinaryOperator<A> combiner();/*** 用于将之前整合完的结果A转换成为R** combiner()完成之后了A, 这里还可以在转一道。生成你自己想要的结果*/Function<A, R> finisher();/*** characteristics表示当前Collector的特征值,* 这是个不可变Set* 它定义了收集器的行为--尤其是关于流是否可以多线程并行执行,以及可以使用哪些优化的提示*/Set<Characteristics> characteristics();/*** 它定义了收集器的行为--尤其是关于流是否可以并行归约,以及可以使用哪些优化的提示*/enum Characteristics {/*** accumulator函数可以从多个线程同时调用,且该收集器可以并行归约流。如果收集器没有标为UNORDERED,* 那它仅在用于无序数据源时才可以并行归约* 多线程并行*/CONCURRENT,/*** 归约结果不受流中项目的遍历和累积顺序的影响(无序)*/UNORDERED,/*** 无需转换结果*/IDENTITY_FINISH}/*** 四参方法,用于生成一个Collector,T代表流中的一个一个元素,R代表最终的结果*/public static<T, R> Collector<T, R, R> of(Supplier<R> supplier,BiConsumer<R, T> accumulator,BinaryOperator<R> combiner,Characteristics... characteristics);/*** 五参方法,用于生成一个Collector,T代表流中的一个一个元素,A代表中间结果,R代表最终结果,finisher用于将A转换为R*/public static<T, A, R> Collector<T, A, R> of(Supplier<A> supplier,BiConsumer<A, T> accumulator,BinaryOperator<A> combiner,Function<A, R> finisher,Characteristics... characteristics);}

       有了上面的介绍,接下来我们自己来new一个Collector对象,把我们Steam流里面的数据转换成List。(当然了Collectors类里面有提供这个方法,这里我们自己写一个也是为了方便大家的理解)

    // 自己来组装Collector,返回一个List@Testpublic void collectNew() {Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);List<Integer> intList = stream.collect(new Collector<Integer, List<Integer>, List<Integer>>() {// 生成结果容器,容器类型为,我们这里为List<Integer>@Overridepublic Supplier<List<Integer>> supplier() {return new Supplier<List<Integer>>() {@Overridepublic List<Integer> get() {return new ArrayList<>();}};}// 把流里面的结果都放到结果容器里面去@Overridepublic BiConsumer<List<Integer>, Integer> accumulator() {return new BiConsumer<List<Integer>, Integer>() {@Overridepublic void accept(List<Integer> integers, Integer integer) {integers.add(integer);}};}// 两个两个合并并行执行的线程的执行结果,将其合并为一个最终结果A@Overridepublic BinaryOperator<List<Integer>> combiner() {return new BinaryOperator<List<Integer>>() {@Overridepublic List<Integer> apply(List<Integer> left, List<Integer> right) {left.addAll(right);return left;}};}// 可以对最终的结果做一个转换操作@Overridepublic Function<List<Integer>, List<Integer>> finisher() {return new Function<List<Integer>, List<Integer>>() {@Overridepublic List<Integer> apply(List<Integer> integers) {return integers;}};}// 特征值@Overridepublic Set<Characteristics> characteristics() {return EnumSet.of(Collector.Characteristics.UNORDERED, Collector.Characteristics.IDENTITY_FINISH);}});for (Integer item : intList) {System.out.println(item);}}

3.1.2 Collectors

       Collectors是Collector的工具类,用来创建Collector对象。它内部以及给我们提供了各种各样的创建Collector对象的方法,已经能满足我们大部分的需求了,我们可以直接拿来使用,非常方便。

Collectors各个方法介绍

public final class Collectors {/*** 将流中的元素全部放置到一个集合中返回** collectionFactory参数用于创建Collection对象(比如List,LinkeList等等)*/public static <T, C extends Collection<T>>Collector<T, ?, C> toCollection(Supplier<C> collectionFactory);/*** 将流中的元素放置到一个列表集合中去。这个列表默认为ArrayList*/public static <T>Collector<T, ?, List<T>> toList();/*** 将流中的元素放置到一个无序集set中去。默认为HashSet*/public static <T>Collector<T, ?, Set<T>> toSet();/*** joining的目的是将流中的元素全部以字符序列的方式连接到一起,可以指定连接符,甚至是结果的前后缀*/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);/*** 这个映射是首先对流中的每个元素进行映射,即类型转换,然后再将新元素以给定的Collector进行归纳*/public static <T, U, A, R>Collector<T, ?, R> mapping(Function<? super T, ? extends U> mapper,Collector<? super U, A, R> downstream);/*** 该方法是在归纳动作结束之后,对归纳的结果进行再处理*/public static<T,A,R,RR> Collector<T,A,RR> collectingAndThen(Collector<T,A,R> downstream,Function<R,RR> finisher);/*** 该方法用于计数*/public static <T> Collector<T, ?, Long> counting();/*** 生成一个用于获取最小/最大值的Optional结果的Collector*/public static <T> Collector<T, ?, Optional<T>> minBy(Comparator<? super T> comparator);public static <T> Collector<T, ?, Optional<T>> maxBy(Comparator<? super T> comparator);/*** 生成一个用于求元素和的Collector,首先通过给定的mapper将元素转换类型,然后再求和*/public static <T> Collector<T, ?, Integer> summingInt(ToIntFunction<? super T> mapper);public static <T> Collector<T, ?, Long> summingLong(ToLongFunction<? super T> mapper);public static <T> Collector<T, ?, Double> summingDouble(ToDoubleFunction<? super T> mapper);/*** 生成一个用于求元素平均值的Collector,首选通过参数将元素转换为指定的类型*/public static <T> Collector<T, ?, Double> averagingInt(ToIntFunction<? super T> mapper);public static <T> Collector<T, ?, Double> averagingLong(ToLongFunction<? super T> mapper);public static <T> Collector<T, ?, Double> averagingDouble(ToDoubleFunction<? super T> mapper);/*** 规约 对流中的元素做统计归纳作用* 和Stream类里面的reducing操作符一样*/public static <T> Collector<T, ?, T> reducing(T identity, BinaryOperator<T> op);public static <T> Collector<T, ?, Optional<T>> reducing(BinaryOperator<T> op);public static <T, U> Collector<T, ?, U> reducing(U identity,Function<? super T, ? extends U> mapper,BinaryOperator<U> op);/*** 这个方法是用于生成一个拥有分组功能的Collector*/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);/*** 和groupingBy方法一样,只是返回的Collector是并行的*/public static <T, K>Collector<T, ?, ConcurrentMap<K, List<T>>>groupingByConcurrent(Function<? super T, ? extends K> classifier);public static <T, K, A, D>Collector<T, ?, ConcurrentMap<K, D>> groupingByConcurrent(Function<? super T, ? extends K> classifier,Collector<? super T, A, D> downstream);public static <T, K, A, D, M extends ConcurrentMap<K, D>>Collector<T, ?, M> groupingByConcurrent(Function<? super T, ? extends K> classifier,Supplier<M> mapFactory,Collector<? super T, A, D> downstream);/*** 该方法将流中的元素按照给定的校验规则的结果分为两个部分,放到一个map中返回,map的键是Boolean类型,值为元素的列表List。*/public static <T>Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate);public static <T, D, A>Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate,Collector<? super T, A, D> downstream);/*** 根据给定的键生成器和值生成器生成的键和值保存到一个map中返回,键和值的生成都依赖于元素,* 可以指定出现重复键时的处理方案和保存结果的map*/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);public static <T, K, U, M extends Map<K, U>>Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,Function<? super T, ? extends U> valueMapper,BinaryOperator<U> mergeFunction,Supplier<M> mapSupplier);/*** 并发版本的toMap*/public static <T, K, U>Collector<T, ?, ConcurrentMap<K,U>> toConcurrentMap(Function<? super T, ? extends K> keyMapper,Function<? super T, ? extends U> valueMapper);public static <T, K, U>Collector<T, ?, ConcurrentMap<K,U>>toConcurrentMap(Function<? super T, ? extends K> keyMapper,Function<? super T, ? extends U> valueMapper,BinaryOperator<U> mergeFunction);public static <T, K, U, M extends ConcurrentMap<K, U>>Collector<T, ?, M> toConcurrentMap(Function<? super T, ? extends K> keyMapper,Function<? super T, ? extends U> valueMapper,BinaryOperator<U> mergeFunction,Supplier<M> mapSupplier);/*** 这三个方法适用于汇总的,返回值分别是IntSummaryStatistics,LongSummaryStatistics,DoubleSummaryStatistics*/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);
}

       为了加深大家的理解。接下来我们对Collectors里面的每个函数都写一个简单的实例。

3.1.2.1 toCollection

       将流中的元素全部放置到一个集合中返回,这里使用Collection,泛指多种集合。

    @Testpublic void toCollection() {List<String> list = Arrays.asList("java", "ios", "c");LinkedList<String> retList = list.stream().collect(Collectors.toCollection(new Supplier<LinkedList<String>>() {@Overridepublic LinkedList<String> get() {return new LinkedList<>();}}));}

3.1.2.2 toList

       将流中的元素放置到一个列表集合中去。这个列表默认为ArrayList。

    @Testpublic void collectList() {Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);List<Integer> intList = stream.collect(Collectors.toList());}

3.1.2.3 toSet

       将流中的元素放置到一个无序集set中去。默认为HashSet。

    @Testpublic void toSet() {List<String> list = Arrays.asList("java", "ios", "c");Set<String> retList = list.stream().collect(Collectors.toSet());}

3.1.2.4 joining

       joining的目的是将流中的元素全部以字符序列的方式连接到一起,可以指定连接符,甚至是结果的前后缀。

    @Testpublic void joining() {List<String> list = Arrays.asList("java", "ios", "c");String ret = list.stream().collect(Collectors.joining(":", "@@", "@@"));System.out.println(ret);//@@java:ios:c@@}

3.1.2.5 mapping

       这个映射是首先对流中的每个元素进行映射,即类型转换,然后再将新元素以给定的Collector进行归纳。

    @Testpublic void mapping() {List<String> list = Arrays.asList("java", "ios", "c");// 先把流里面的每个元素的前后加上[],之后在用:拼接起来String ret = list.stream().collect(Collectors.mapping(new Function<String, String>() {@Overridepublic String apply(String s) {return "[" + s + "]";}},Collectors.joining(":")));System.out.println(ret);//[java]:[ios]:[c]}

3.1.2.6 collectingAndThen

       该方法是在归纳动作结束之后,对归纳的结果进行再处理。

    @Testpublic void collectingAndThen() {List<String> list = Arrays.asList("java", "ios", "c");// Collectors.toList()之后在把List<String>通过Joiner转换StringString ret = list.stream().collect(Collectors.collectingAndThen(Collectors.toList(),new Function<List<String>, String>() {@Overridepublic String apply(List<String> strings) {return Joiner.on("; ").join(strings);}}));System.out.println(ret);//java; ios; c}

3.1.2.7 counting

       计算流里面的元素个数。

    @Testpublic void counting() {List<String> list = Arrays.asList("java", "ios", "c");// 元素个数Long ret = list.stream().collect(Collectors.counting());System.out.println(ret);//3}

3.1.2.8 minBy/maxBy

       生成一个用于获取最小/最大值的Optional结果的Collector。

    @Testpublic void minBy() {List<String> list = Arrays.asList("java", "ios", "c");// 这里简单的用字符串比较的大小Optional<String> ret = list.stream().collect(Collectors.minBy(new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {return o1.compareTo(o2);}}));}

3.2.2.9 summingInt/summingLong/summingDouble

       生成一个用于求元素和的Collector,首先通过给定的mapper将元素转换类型,然后再求和。

    @Testpublic void summingInt() {List<Integer> list = Arrays.asList(1, 2, 3);// 求和Integer ret = list.stream().collect(Collectors.summingInt(new ToIntFunction<Integer>() {@Overridepublic int applyAsInt(Integer value) {return value;}}));}

3.2.2.10 averagingInt/averagingLong/averagingDouble

       生成一个用于求元素平均值的Collector,首选通过参数将元素转换为指定的类型。

    @Testpublic void averagingInt() {List<Integer> list = Arrays.asList(1, 2, 3);// 求平均值Double ret = list.stream().collect(Collectors.averagingInt(new ToIntFunction<Integer>() {@Overridepublic int applyAsInt(Integer value) {return value;}}));}

3.1.2.11 reducing

       reducing方法有三个重载方法,其实是和Stream里的三个reduce方法对应的,二者是可以替换使用的,作用完全一致,也是对流中的元素做统计归纳作用(规约)。

    @Testpublic void reducing() {List<Integer> list = Arrays.asList(1, 2, 3);// 求平均值Integer ret = list.stream().collect(Collectors.reducing(10,new Function<Integer, Integer>() {@Overridepublic Integer apply(Integer integer) {return integer * integer;}},new BinaryOperator<Integer>() {@Overridepublic Integer apply(Integer integer, Integer integer2) {return integer + integer2;}}));System.out.println(ret); // 10 + 1*1 + 2*2 + 3*3 = 24}

3.1.2.12 groupingBy

       这个方法是用于生成一个拥有分组功能的Collector,它也有三个重载方法。这里要稍微解释下参数最长的函数每个参数的含义。

  • Function<? super T, ? extends K> classifier:确定怎么从流里面每个元素获取key。
  • Supplier mapFactory:用于创建最终要生成的对象一般都是Map。
  • Collector<? super T, A, D> downstream:每一组数据用什么来存放,一般是List,所以这个参数一般是Collectors.toList()。
    @Testpublic void collectGroupingBy() {List<Student> list = Arrays.asList(new Student("吴六", 26), new Student("张三", 26), new Student("李四", 27));Map<Integer, List<Student>> ret = list.stream().collect(Collectors.groupingBy(new Function<Student, Integer>() {@Overridepublic Integer apply(Student student) {return student.getAge();}},new Supplier<Map<Integer, List<Student>>>() {@Overridepublic Map<Integer, List<Student>> get() {return new HashMap<>();}},Collectors.toList()));for (Map.Entry<Integer, List<Student>> entry : ret.entrySet()) {Integer mapKey = entry.getKey();List<Student> mapValue = entry.getValue();System.out.println(mapKey + ":" + mapValue);}}private static class Student {private String name;private int age;public Student(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}}

groupingByConcurrent和groupingBy是一样的,只不过groupingByConcurrent生成的是ConcurrentMap,而groupingBy生成的是Map。

3.1.2.13 partitioningBy

       该方法将流中的元素按照给定的校验规则的结果分为两个部分,放到一个map中返回,map的键是Boolean类型,值为元素的列表List。

    @Testpublic void partitioningBy() {List<Integer> list = Arrays.asList(1, 2, 3);// 求平均值Map<Boolean, List<Integer>> ret = list.stream().collect(Collectors.partitioningBy(new Predicate<Integer>() {@Overridepublic boolean test(Integer integer) {return integer % 2 == 0;}},Collectors.toList()));for (Map.Entry<Boolean, List<Integer>> entry : ret.entrySet()) {Boolean mapKey = entry.getKey();List<Integer> mapValue = entry.getValue();System.out.println(mapKey + ":" + mapValue);}}

3.1.2.14 toMap

       toMap方法是根据给定的键生成器和值生成器生成的键和值保存到一个map中返回,键和值的生成都依赖于元素,可以指定出现重复键时的处理方案和保存结果的map。

    @Testpublic void toMap() {List<Student> list = Arrays.asList(new Student("吴六", 26), new Student("张三", 26), new Student("李四", 27));Map<Integer, List<Student>> ret = list.stream().collect(Collectors.toMap(// keynew Function<Student, Integer>() {@Overridepublic Integer apply(Student student) {return student.getAge();}},// valuenew Function<Student, List<Student>>() {@Overridepublic List<Student> apply(Student student) {return Lists.newArrayList(student);}},// 有系统key的value怎么处理new BinaryOperator<List<Student>>() {@Overridepublic List<Student> apply(List<Student> students, List<Student> students2) {students.addAll(students2);return students;}}));for (Map.Entry<Integer, List<Student>> entry : ret.entrySet()) {Integer mapKey = entry.getKey();List<Student> mapValue = entry.getValue();System.out.println(mapKey + ":" + mapValue);}}private static class Student {private String name;private int age;public Student(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}}

3.1.2.15 summarizingInt/summarizingLong/summarizingDouble

       这三个方法适用于汇总的,返回值分别是IntSummaryStatistics,LongSummaryStatistics,DoubleSummaryStatistics。

    @Testpublic void summarizingInt() {List<Integer> list = Arrays.asList(1, 2, 3);IntSummaryStatistics ret = list.stream().collect(Collectors.summarizingInt(new ToIntFunction<Integer>(){@Overridepublic int applyAsInt(Integer value) {return value;}}));System.out.println(ret.getAverage());}

       关于JDK8里面Stream部分内容我们就讲这么些,真心希望能帮助上大家。大家如果有什么疑问可以留言。最后,上面所有的实例代码在 https://github.com/tuacy/google-guava-study里面都可以找到。

http://www.jmfq.cn/news/4954987.html

相关文章:

  • 做门头上那个网站申报/seo排名赚钱
  • 如皋做网站/自己怎么做网址
  • wordpress图片使用图床/搜狗整站优化
  • 在线捏脸网站需要多少钱/种子资源
  • 赣州市网站建设公司/广州seo网站推广公司
  • 做banner网站/宁波seo优化流程
  • 丰镇网站建设/百度网址大全设为主页
  • 西安做网站/营销软文200字
  • 网站建设和关键词优化技巧/真正的免费建站在这里
  • 0基础学网站建设/网络营销和传统营销的区别和联系
  • 网站支付怎么做虚拟币支付/湛江百度seo公司
  • 黄骅市原来叫什么名字/手机百度seo快速排名
  • 网站建设过程与思路/外链
  • 做电商引流软文网站/网站友情链接有什么用
  • seo网站设计/百度网站快速优化
  • 我的家乡网站建设模板/怎么做公司网站推广
  • java网站开发新技术/免费引流微信推广
  • 铜仁建设局网站首页/免费推广网站入口
  • 什么网站可以做设计/专业网站优化排名
  • 企业邮箱购买价格/seo快速软件
  • 购物网站 设计/他达拉非
  • 连云港网站建设 连云港网站制作/网站推广技巧和方法
  • 网站推广软文范例/互联网广告营销是什么
  • 任县网站建设公司/seo标题优化关键词怎么选
  • 莱芜在线广告信息/郑州seo优化阿亮
  • ps做字幕模板下载网站/网站开发公司哪家好
  • 深圳分销网站制作/快速优化工具
  • 网站如何做权重/芭蕉视频app无限次数
  • 做了微网站/最新的新闻 最新消息
  • 网站建设的作用/it培训班出来现状