Stream 流式计算

Stream 简介

  

一、Stream 概述

简介:

Stream用于进行计算,是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。

Stream并不会存储数据。

Stream并不会改变数据源,它会返回一个含有结果集的Stream。

Stream是延迟加载的,在需要结果时才执行。

  
步骤:

  1. 创建一个流。
  2. 将初始流转换为其他流的中间操作,可能包含多个步骤。
  3. 终止操作,执行终止操作后才执行中间操作链,此后这个流就不能再使用了。

  

二、Stream的创建

通过java.util.Collection.stream() 方法用集合创建流

public void method(){
    ArrayList<User> users = getUsers();
    Stream<User> stream = users.stream();//顺序流
    Stream<User> userStream = users.parallelStream();//并行流
}

  
使用java.util.Arrays.stream(T[] array)方法用数组创建流

public void method(){
    Integer[] arr = new Integer[]{1,2,3,4};
    Stream<Integer> stream = Arrays.stream(arr);
}

  
使用Stream的静态方法:of()、iterate()、generate()

public static<T> Stream<T> of(T... values)
//无限流
public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
public static<T> Stream<T> generate(Supplier<? extends T> s)
/**无限流
 * iterate:迭代
 * generate:生成
 */
public void method(){
    Stream.iterate(1, x -> x+2).limit(10).forEach(System.out::println);

    Stream.generate(Math::random).limit(10).forEach(System.out::println);
}

  

三、Stream与parallerStream

streamparallelStream的简单区分: stream是顺序流,由主线程按顺序对流执行操作,而parallelStream是并行流,内部以多线程并行执行的方式对流进行操作,但前提是流中的数据处理没有顺序要求。例如筛选集合中的奇数,两者的处理不同之处:
在这里插入图片描述

  
  

Stream中间操作

多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理。

而在终止操作时一次性全 部处理,称为“惰性求值”。

操作类:

public class User{
    private Stirng name;
    private Integer age;
    
    .....
}

  

一、筛选与切片

方法:

filter(Predicate p) :过滤,接收 Lambda 从流中排除某些元素 。

distinct(): 去重,通过流所生成元素的 hashCode() 和 equals() 去除重复元素 。

limit(long maxSize): 截断,使其元素不超过给定数量 。

skip(long n):跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一 个空流。与 limit(n) 互补 。

  

示例:

//filter(Predicate p) 接收 Lambda , 从流中排除某些元素
public void test5(){
    ArrayList<User> users = getUsers();
    users.stream().filter(e -> e.getAge() >20).forEach(System.out::println);
}

//distinct() 筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
public void test6(){
    ArrayList<User> users = getUsers();
    users.add(new User("周聪",70));
    users.add(new User("周聪",70));
    users.add(new User("周聪",70));
    users.add(new User("周聪",70));
    
    users.stream().distinct().forEach(System.out::println);
}

//limit(long maxSize) 截断流,使其元素不超过给定数量
public void test7(){
    ArrayList<User> users = getUsers();
    users.stream().limit(3).forEach(System.out::println);
}

//skip(long n) 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一 个空流。与 limit(n) 互补
public void test8(){
    ArrayList<User> users = getUsers();
    users.stream().skip(2).forEach(System.out::println);
}

  

二、映射

方法:

map(Function f):

​ 接收一个函数作为参数,该函数会被应用到每个元 素上,并将其映射成一个新的元素。

mapToDouble(ToDoubleFunction f):

​ 接收一个函数作为参数,该函数会被应用到每个元 素上,产生一个新的 DoubleStream。

。。。。

flatMap(Function f):

​ 接收一个函数作为参数,将流中的每个值都换成另 一个流,然后把所有流连接成一个流。

flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper):

​ 接收一个函数作为参数,将流中的每个值都换成DoubleStream流,然后把所有流连接成一个流。

。。。。

  
示例:

public void method(){
    ArrayList<User> users = getUsers();
    users.stream()
        .filter(e -> e.getAge() < 21)
        .map(e -> e.getUsername()).forEach(System.out::println);
}



//flatMap,将{{a,b,c},{1,2,3}} -> a,b,c,1,2,3。
//在这种格式下由于是List包含List,此时就可以使用flatMap,将内部元素List作为多个流,来进行元素之间的分隔,当然你也可以看情况使用。  
public void test2(){
    ArrayList<List<String>> arrayList = new ArrayList<>();
    arrayList.add(new ArrayList<String>(){{add("a");add("b");add("c");}});
    arrayList.add(new ArrayList<String>(){{add("1");add("2");add("3");}});


    String collect = arrayList.stream().flatMap(e -> {
            return e.stream();
        }).collect(Collectors.joining(","));
        
    System.out.println(collect); //a,b,c,1,2,3
}

  

三、排序

方法:

sorted(): 产生一个新流,其中按自然顺序排序 。

sorted(Comparator com): 产生一个新流,其中按比较器顺序排序 。

  
示例:

public void test2(){
	list.stream().sorted();
    list.stream().sorted((e1,e2) ->{return e2.compareTo(e1);});
}

  
  

Stream终止操作

终端操作会从流的流水线生成结果。其结果可以是任何不是流的值,例 如:List、Integer,甚至是 void 。

流进行了终止操作后,不能再次使用。

操作类:

public class User{
    private Stirng name;
    private Integer age;
    
    .....
}

  

一、匹配与查找

方法:

allMatch(Predicate p): 检查是否匹配所有元素 。

anyMatch(Predicate p): 检查是否至少匹配一个元素 。

noneMatch(Predicate p): 检查是否没有匹配所有元素 。

findFirst(): 返回第一个元素 。

findAny(): 返回当前流中的任意元素 。

count() :返回流中元素总数 。

max(Comparator c): 返回流中最大值 。

min(Comparator c) :返回流中最小值 。

forEach(Consumer c):内部迭代(使用 Collection 接口需要用户去做迭代, 称为外部迭代。相反,Stream API 使用内部迭 代——它帮你把迭代做了) 。

  
示例:

/**
 *allMatch(Predicate p) 检查是否匹配所有元素
 *anyMatch(Predicate p) 检查是否至少匹配一个元素
 *noneMatch(Predicate p) 检查是否没有匹配所有元素
 */
public void test12(){
ArrayList<User> users = getUsers();
    boolean b = users.stream().allMatch(e -> e.getAge() == 21);
    System.out.println(b);

    boolean b1 = users.stream().anyMatch(e -> e.getAge() == 21);
    System.out.println(b1);

    boolean b2 = users.stream().noneMatch(e -> e.getAge() == 70);
    System.out.println(b2);
}
			
			
/**
 *findFirst() 返回第一个元素
 *findAny() 返回当前流中的任意元素
 */
public void test13(){

    ArrayList<User> users = getUsers();
    Optional<User> first = users.stream().findFirst();
    System.out.println(first.get());

    Optional<User> any = users.stream().findAny();
    System.out.println(any.get());
}

/**
  *count() 返回流中元素总数
  *max(Comparator c) 返回流中最大值
  *min(Comparator c) 返回流中最小值
  *forEach(Consumer c)内部迭代(使用 Collection 接口需要用户去做迭代, 称为外部迭代。相反,Stream     *API 使用内部迭 代——它帮你把迭代做了)
  */	
public void test14(){
    ArrayList<User> users = getUsers();
    
    long count = users.stream().count();
    System.out.println(count);

    Optional<Integer> max = users.stream().map(e -> e.getAge()).max(Integer::compareTo);

    Optional<String> min = users.stream()
        .map(e -> e.getUsername())
        .min(String::compareTo);
    System.out.println(max);
    System.out.println(min);
}

  

二、规约

map 和 reduce 的连接通常称为 map-reduce 模式,因 Google 用它来进行网络搜索而出名。

  
方法:

T reduce(T identity, BinaryOperator<T> accumulator):

​ 可以将流中元素反复结合起来,得到一 个值。返回 T。

reduce(BinaryOperator accumulator):

​ 可以将流中元素反复结合起来,得到一 个值。返回 Optional。

U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner)

​非并行流情况下,与双参数的没啥区别。但在并行流情况下,通过ForkJoin,整个元素集合分为多个部分进行accumulator,再将多个部分的计算结果combiner汇总。


  
示例:

/**
  *reduce(T iden, BinaryOperator b):可以将流中元素反复结合起来,得到一 个值。返回 T
  *reduce(BinaryOperator b):可以将流中元素反复结合起来,得到一 个值。返回 Optional<T>
  */
public void test15(){
    ArrayList<User> users = getUsers();
    
    //获取User总的年龄
    Integer ageSum = users.stream()
        .map(e -> e.getAge())
        .reduce(0, Integer::sum);
    System.out.println(ageSum);
    
    //User名字的拼接
    Optional<String> nameStr = users.stream()
        .map(e -> e.getUsername())
        .reduce(String::concat);
    
    System.out.println(nameStr.get());

}

/**
 * 三参数情况
 * sum1: 为非并行流情况下的结果。
 * sum2: 为并行流情况下的结果。
 */
@Test
public void test3(){
    Integer sum1 = Stream.of(1, 2, 3).reduce(1, (e1, e2) -> {
        return e1 + e2;
    }, (e1, e2) -> {
        return e1 + e2;
    });

    System.out.println(sum1); //1 + 2 + 3 + 4 = 7


Integer sum2 = Stream.of(1,2,3,4,5,6,7).parallel().reduce(1, (e1, e2) -> {
            System.out.println("线程:" + Thread.currentThread().getName() + "相加" + e1 + " + " + e2 + " = " + (e1+e2));
            return e1 + e2;
        }, (e1, e2) -> {
            System.out.println("线程:" + Thread.currentThread().getName()+"合并, e1 = " +e1 + " e2 = " + e2);
            return e1 + e2;
        });
        System.out.println(sum2);//(1 + 1) + (1 + 2) + (1 + 3) = 9
}



结果:
7
线程:main相加1 + 5 = 6
线程:main相加1 + 4 = 5
线程:main合并, e1 = 5 e2 = 6
线程:ForkJoinPool.commonPool-worker-3相加1 + 1 = 2
线程:main相加1 + 6 = 7
线程:ForkJoinPool.commonPool-worker-3相加1 + 3 = 4
线程:ForkJoinPool.commonPool-worker-2相加1 + 7 = 8
线程:ForkJoinPool.commonPool-worker-2合并, e1 = 7 e2 = 8
线程:ForkJoinPool.commonPool-worker-2合并, e1 = 11 e2 = 15
线程:ForkJoinPool.commonPool-worker-1相加1 + 2 = 3
线程:ForkJoinPool.commonPool-worker-1合并, e1 = 3 e2 = 4
线程:ForkJoinPool.commonPool-worker-1合并, e1 = 2 e2 = 7
线程:ForkJoinPool.commonPool-worker-1合并, e1 = 9 e2 = 26
35
    
扩展结果:将其改为非并行流
7
线程:main相加1 + 1 = 2
线程:main相加2 + 2 = 4
线程:main相加4 + 3 = 7
线程:main相加7 + 4 = 11
线程:main相加11 + 5 = 16
线程:main相加16 + 6 = 22
线程:main相加22 + 7 = 29
29   

  

三、收集

方法:

collect(Collector c):

将流转换为其他形式。接收一个 Collector 接口的实现,用于给Stream中元素做汇总 的方法。

Collector 接口中方法的实现决定了如何对流执行收集的操作(如收集到 List、Set、 Map)。

  
R collect(Supplier<R> supplier,

​     BiConsumer<R, ? super T> accumulator,

​      BiConsumer<R, R> combiner):

和上面的reduce三个参数的有点类似,并行流情况下也使用了ForkJoin,总 - 分 - 总。

​ supplier ---- 一个创建新结果容器的函数。对于并行执行,此函数可能会被多次调用,并且每次都必须返回一 个新值。

​ accumulator ---- 用于将附加元素合并到结果中的函数。

​ combiner ---- 组合两个值的函数,必须与accumulator 函数兼容。

  
示例:

//并行流情况下的计算,每个分支创建一个ArrayList
@Test
public void test4(){
    ArrayList<Integer> list = Stream.of(1, 2, 3)
        .parallel()
        .collect(ArrayList<Integer>::new, 
                 (e1, e2) -> {
        						System.out.println("线程:" + 
                                	Thread.currentThread().getName() + e2 + " 												元素添加 "+e2 + " to " + e1);
        						e1.add(e2);
    								}, 
                 (e1, e2) -> {
        						System.out.println("线程:" + 																Thread.currentThread().getName() + "元素合并" + 
                                    e2 + "to" + e1);     
        						e1.addAll(e2);
    								}
                );

    System.out.println(list);
}


结果:
线程:main2 元素添加 2 to []
线程:ForkJoinPool.commonPool-worker-11 元素添加 1 to []
线程:ForkJoinPool.commonPool-worker-23 元素添加 3 to []
线程:ForkJoinPool.commonPool-worker-2元素合并[3]to[2]
线程:ForkJoinPool.commonPool-worker-2元素合并[2, 3]to[1]
[1, 2, 3]
    
    
扩展结果:非并行流
线程:main1 元素添加 1 to []
线程:main2 元素添加 2 to [1]
线程:main3 元素添加 3 to [1, 2]
[1, 2, 3]    

  
  

Collectors类

此类用在collect(Collector c)中,为产生Collector 的工具类,类似于Collections,Arrays工具类,内部包含许多的静态方法,用于产生一个Collector 对象。

  
简单示例:

Set<String> collect2 = list.stream().collect(Collectors.toSet());

  
Collector<T, A, R>接口:

T:表示原始元素类型

A:表示中间累加类型

R:表示最终结果类型

  

一、toxxx()

用于将流转换为List、Set。。。

方法:

Collector<T, ?, C> toCollection(Supplier<C> collectionFactory):

用于将结果存放到Collection中,collectionFactory — 为一个适当的,空的Collection容器,比如ArrayList 等 。
  
Collector<T, ?, List<T>> toList():

用于将结果存放到List中,ArrayList为其容器。
  
Collector<T, ?, Set<T>> toSet():

用于将结果存放到Set中, HashSet为其容器。

  
Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,

Function<? super T, ? extends U> valueMapper):

keyMapper为key的转换器,valueMapper为value的转换器。

  
Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,

Function<? super T, ? extends U> valueMapper,

BinaryOperator<U> mergeFunction)
​keyMapper为key的转换器,valueMapper为value的转换器。mergeFunction为当key冲突时,选择那个 value。


  
Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,

Function<? super T, ? extends U> valueMapper,

BinaryOperator<U> mergeFunction,

Supplier<M> mapSupplier)

keyMapper为key的转换器,valueMapper为value的转换器。mergeFunction为当key冲突时,选择那个 value。

mapSupplier为使存储元素的map容器(比如HashMap、TreeMap)。

  
Collector<T, ?, ConcurrentMap<K,U>> toConcurrentMap(

Function<? super T, ? extends K> keyMapper,

Function<? super T, ? extends U> valueMapper,

BinaryOperator<U> mergeFunction)
​keyMapper为key的转换器,valueMapper为value的转换器。mergeFunction为当key冲突时,选择那个 value。

map为ConcurrentHashMap。


  
Collector<T, ?,。。> toConcurrentMap(Function<? super T, ? extends K> keyMapper,

Function<? super T, ? extends U> valueMapper,

BinaryOperator<U> mergeFunction,

Supplier<M> mapSupplier)

keyMapper为key的转换器,valueMapper为value的转换器。mergeFunction为当key冲突时,选择那个 value。

mapSupplier为存储元素的容器如何创建,需要是ConcurrentMap的子类


  
示例:

ArrayList<Integer> collection = Stream
    .of(1, 2, 3, 4)
    .collect(Collectors.toCollection(ArrayList::new));

List<Integer> list = Stream
    .of(1, 2, 3, 4)
    .collect(Collectors.toList());

Set<Integer> set = Stream
    .of(1, 2, 3, 4)
    .collect(Collectors.toSet());


list.stream().collect(Collectors.toMap(e -> {return e + "id";}, e ->{return e + "value";}));

list.stream().collect(Collectors.toMap(e -> {return e + "id";}, e ->{return e + "value";}, (e1,e2) -> {return e1;}));

list.stream().collect(Collectors.toMap(e -> {return e + "id";}, e ->{return e + "value";}, (e1,e2) -> {return e1;},TreeMap::new));

  

二、joining

对流中的元素按照某个字符进行拼接,并且可以1指定前缀与后缀。

方法:

Collector<CharSequence, ?, String> joining():

内部使用StringBuilder进行拼接,无分隔符,或者分隔符为”“。
  
Collector<CharSequence, ?, String> joining(CharSequence delimiter):

内部使用StringJoiner进行拼接,delimiter表示分隔符
  
Collector<CharSequence, ?, String> joining(CharSequence delimiter,

CharSequence prefix,

CharSequence suffix):

内部使用StringJoiner进行拼接,delimiter表示分隔符,prefix为前缀,suffix为后缀。

  
示例:

String s = Stream.of("1","2","3").collect(Collectors.joining()); //123

String s1 = Stream.of("1","2","3")
    .collect(Collectors.joining(",")); //1,2,3

String s2 = Stream.of("1","2","3")
    .collect(Collectors.joining(",", "prefix", "suffix")); //prefix1,2,3suffix

  

三、mapping

对流中的元素进行映射,并将其传递给downstream 下游收集器。通常配合groupingBy等分组方法使用。如果仅仅是对整个元素集合进行reduce-mapping,请使用中间操作toMap()。

方法:

Collector<T, ?, R> mapping(Function<? super T, ? extends U> mapper,

Collector<? super U, A, R> downstream):

通过在collector之前对每个输入元素应用映射函数, 将Collector 接受类型为 T 的元素调整为U类型。

mapper ---- 为映射器,downstream – 为下游收集器。

  
示例:

//简单示例
Stream.of("1","2")
    .collect(Collectors.mapping(e ->{return e + "ha";}, Collectors.toList()));



//获取每个城市的姓氏
Map<City, Set<String>> lastNamesByCity = people.stream()
    .collect(groupingBy(Person::getCity,
                        Collectors.mapping(Person::getLastName,Collectors.toSet())
                       )
            );

  

四、collectioningAndThen

先通过downstream下游收集器收集元素,再通过finisher转换,完成一下额外的步骤。

方法:

Collector<T,A,RR> collectingAndThen(Collector<T,A,R> downstream,

Function<R,RR> finisher):

downstream - 为下游收集器, finisher - 应用于下游收集器的函数,用于元素的转换R -》RR

  
示例:

//调整收集器,最终生成一个不可变的列表
List<String> people = people.stream()
    .collect(collectingAndThen(Collecors.toList(), 
                               Collections::unmodifiableList
                              )
            );

  

五、计算

包括像一些求和、最大值、最小、平均值的一些收集器 。

方法:

Collector<T, ?, Long> counting():元素数量

Collector<T, ?, Optional<T>> minBy(Comparator<? super T> comparator):通过传入的比较器求min值

Collector<T, ?, Optional<T>> maxBy(Comparator<? super T> comparator):通过传入的比较器求max值

Collector<T, ?, Integer> summingInt(ToIntFunction<? super T> mapper):转换为Integer,再求和sum

Collector<T, ?, Long> summingLong(ToLongFunction<? super T> mapper):转换为Long,再求和sum

Collector<T, ?, Double> summingDouble(ToDoubleFunction<? super T> mapper):转换为Double,再求和sum 。

Collector<T, ?, Double> averagingInt(ToIntFunction<? super T> mapper):转换为Integer,再求平均值average 。

Collector<T, ?, Double> averagingLong(ToLongFunction<? super T> mapper):转换为Long,再平均值average 。

Collector<T, ?, Double> averagingDouble(ToDoubleFunction<? super T> mapper):转换为Double,再平均值average 。

Collector<T, ?, IntSummaryStatistics> summarizingInt(ToIntFunction<? super T> mapper):转换为Integer,获取IntSummaryStatistics对象,该对象包含sum、max、min、average 。

Collector<T, ?, LongSummaryStatistics> summarizingLong(ToLongFunction<? super T> mapper)

Collector<T, ?, DoubleSummaryStatistics> summarizingDouble(ToDoubleFunction<? super T> mapper)

  
示例:

ArrayList<String> list = new ArrayList<>();
....

Optional<String> min = list.stream().collect(Collectors.minBy((e1, e2) -> {
    return e1.compareTo(e2);
}));

Optional<String> max = list.stream().collect(Collectors.maxBy((e1, e2) -> {
    return e1.compareTo(e2);
}));


Integer sum1 = list.stream().collect(Collectors.summingInt(e -> {
    return Integer.parseInt(e);
}));


Long sum2 = list.stream().collect(Collectors.summingLong(e -> {
    return Long.parseLong(e);
}));


Double sum3 = list.stream().collect(Collectors.summingDouble(e -> {
    return Double.valueOf(e);
}));

Double average = list.stream().collect(Collectors.averagingInt(e -> {
    return Integer.valueOf(e);
}));

  

六、reducing 规约

对元素进行规约得到一个值,通常配置groupingBy()、partitioningBy()使用,要对流执行简单的 map-reduce,请改用 Streammap(Function) 和 Streamreduce(Object, BinaryOperator) 。

方法:

Collector<T, ?, T> reducing(T identity, BinaryOperator<T> op):

Collector<T, ?, Optional<T>> reducing(BinaryOperator<T> op):

Collector<T, ?, U> reducing(U identity,

Function<? super T, ? extends U> mapper,

BinaryOperator<U> op):

​ identity —为规约的标识符,也是当没有元素时的返回值。

​ mapper --为映射器,应用于每个输入值的映射函数。

​ op — 为具体操作,比如两数相加。

  
示例:

//求每个城市最高的人
Comparator<Person> byHeight = Comparator.comparing(Person::getHeight);

Map<City, Person> tallestByCity = people.stream().collect(
    Collectors.groupingBy(
        Person::getCity, Collectors.reducing(BinaryOperator.maxBy(byHeight))
    )
);

//counting()就是使用reducing实现的
public static <T> Collector<T, ?, Long>
    counting() {
        return reducing(0L, e -> 1L, Long::sum);
}

  

七、分组

当需要根据某些情况进行分组时,可以使用groupingBy()、partitioningBy()。

partitioningBy()为断言型分组、groupingBy()为函数型分组 。

方法:

Collector<T, ?, Map<K, List<T>> groupingBy(Function<? super T, ? extends K> classifier):

classifier — 将输入元素映射到键的分类器函数

  
Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier,

Collector<? super T, A, D> downstream):

classifier — 将输入元素映射到键的分类器函数。

downstream — 下游收集器,可再次分组。

  
Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier,

Supplier<M> mapFactory,

Collector<? super T, A, D> downstream):

classifier — 将输入元素映射到键的分类器函数。

mapFactory ---- 产生Map的工厂。

downstream — 下游收集器,可再次分组等操作。

  
Collector<T, ?, ConcurrentMap<K, List<T>>> groupingByConcurrent(

Function<? super T, ? extends K> classifier):

  
Collector<T, ?, ConcurrentMap<K, D>> groupingByConcurrent(

Function<? super T, ? extends K> classifier,

Collector<? super T, A, D> downstream)

  
<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)


  
Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate):

predicate ---- 分组判断

  
Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate,

Collector<? super T, A, D> downstream)

predicate ---- 分组判断

downstream ----- 下游收集器,可再次分组。

  
示例:

list.stream().collect(Collectors.groupingBy(e ->{
    if (e.equals("1")){
        return "group1";
    } else if(e.equals("2")){
        return "group2";
    }
    return "group3";
}));


list.stream().collect(Collectors.groupingBy(e ->{
    if (e.equals("1")){
        return "group1";
    } else if(e.equals("2")){
        return "group2";
    } else {
        return "group3";
    }
},Collectors.toList()));


list.stream().collect(Collectors.groupingBy(e ->{
    if (e.equals("1")){
        return "group1";
    } else if(e.equals("2")){
        return "group2";
    } else {
        return "group3";
    }
},TreeMap::new,Collectors.toList()));


list.stream().collect(Collectors.groupingByConcurrent(e ->{
    if (e.equals("1")){
        return "group1";
    } else if(e.equals("2")){
        return "group2";
    }
    return "group3";
}));

list.stream().collect(Collectors.groupingBy(e ->{
    if (e.equals("1")){
        return "group1";
    } else if(e.equals("2")){
        return "group2";
    } else {
        return "group3";
    }
},Collectors.toList()));


list.stream().collect(Collectors.groupingByConcurrent(e ->{
    if (e.equals("1")){
        return "group1";
    } else if(e.equals("2")){
        return "group2";
    } else {
        return "group3";
    }
}, ConcurrentHashMap::new,Collectors.toList()));

---------------------------------------------------------------
    
list.stream().collect(Collectors.partitioningBy(e -> {return e.equals("hello");}));

Map<Boolean, Map<String, List<String>>> collect3 = 
    list.stream().collect(Collectors.partitioningBy(e -> {
    							return e.equals("hello");
                          },
                           Collectors.groupingBy(e -> {
                                if (e.equals("group1")) {
                                    return "group1";
                                }
                                return "group2";
                          }
                                               )
                                             )
                         );
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值