> 文档中心 > 分组:Stream不得不知的操作

分组:Stream不得不知的操作

场景

假如现在存在两个列表List 和List

其中A包含 B的集合。

代码如下。

A对象

@Datapublic void A{ private Integer id;    private String name; private List bList;}

B 对象

@Datapublic void B{    private Integer AId;    private String name; private String storeName;    private Long startTime; private BigDecimal amount;...}

现在需要将符合条件的List的内容set到List

用来组合出一个新的VO返回出去。

 

常规解决方案

一般解决方法都是直接使用for循环操作

先讲List循环,然后根据条件,找到对应的List的对象List,

一条条set到A中去。

常规伪代码

List listA;List listB;listA.foreach(a->{    List newListB = new ArrayList();    for(int i=0;i<listB.size();i++){ if(a.id==listB[i].AId){   newListB.add(listB[i]); }    }    a.setBList(newListB);});

我们可以看到,在常规操作里面,可以看到当前会有大量的循环。

循环影响性能,这个事情我们就不作过多讨论了。

而且代码看起来的话,大量的嵌套和判断,导致代码的自读性差。

Stream常规操作

如果熟悉stream的话,

一般都会把里面嵌套的那层for使用stream来操作。

例如

List listA;List listB;listA.foreach(a->{ List newListB = listB.stream.filter(e->e.getAId==a.getId).collect(Collectors.toList());     a.setBList(newListB);    });

上面的stream操作也会产生很多的对象

同时,每次循环都会将listB全部比对一次。

在性能上来讲,还是有待提高。

那么有没有一种比较优雅的方案呢?

在这里,推荐一种新的方案。

新解决方案

Stream的groupingBy方法

使用这个方法的源码在Collectors中。

groupingBy源码

public final class Collectors { ...    /* @param  the type of the input elements     * @param  the type of the keys     * @param classifier the classifier function mapping input elements to keys     * @return a {@code Collector} implementing the group-by operation     *     * @see #groupingBy(Function, Collector)     * @see #groupingBy(Function, Supplier, Collector)     * @see #groupingByConcurrent(Function)     */    public static  Collector<T, ?, Map<K, List>>    groupingBy(Function classifier) { return groupingBy(classifier, toList());    } ...}

通过groupingBy的分类器,可以直接将当前List中的数据,进行分类。

这样得到的数据就可以直接赋值了。

示例

我们还是拿原来的代码来操作

List listA;List listB;//跳过赋值操作Map<Integer,List> bMap = listB.stream.collect(Collectors.groupingBy(B::getAId));listA.foreach(a->{ a.setBList(bMap.get(a.getId()));    });

我们将listB直接进行分组,使用map进行存储。map对应的key就是groupingBy中的分类器B::getAId。value就是对应的分组的数据。

这样一看,我们的代码非常简洁。

总结

groupingBy在分类操作的时候非常有用,我们可以直接将数据分好组。在后续需要调用的时候,直接get就好,就不需要进行二次计算操作了。在执行速度和代码可读性方面都有不错的提升。

顺便再上面的中间,再加点料,如果需要根据AId来对分组的amount属性求和。这样的话,你会怎样做呢?

麦克风网