Stream 流 根据对象属性去重

目录

前言

一、实现原理

二、实现过程

三、filter过滤器的原理

总结


前言

这篇文章介绍一种通过stream流对集合中的对象根据key值去重的简便方法。


一、实现原理

        通过Stream流中的filter方法实现对数据的去重,具体操作是构造一个Predict对象,在Predict中通过检查数据是否存在返回断言中的布尔值。

二、实现过程

代码如下:

public static  <K> Predicate<K> distinctPredicate(Function<K,Object> function){
        ConcurrentHashMap<Object, Boolean> map = new ConcurrentHashMap<>();
        return (t)-> null == map.putIfAbsent(function.apply(t),true);

  }



// 测试代码
public static void main(String[] args) {

        HashMap<String, Object> map1 = new HashMap<>();
        map1.put("key1","value1");
        HashMap<String, Object> map2 = new HashMap<>();
        map2.put("key1","value1");
        ArrayList<Map> maps = new ArrayList<>();
        maps.add(map1);
        maps.add(map2);

        List<Map> distinctMap= maps.stream().filter(distinctPredicate(m -> m.get("key1"))).collect(Collectors.toList());



    }
对于上面代码distinctPredicate方法,我是有一点疑惑的,因为在我看来filter方法每次调用distinctPredicate方法,都会重新初始化ConcurrentHashMap<Object, Boolean> map = new ConcurrentHashMap<>()这行代码,这就意味着,这个方法的map对象里永远只会有一个值,那么也就不会出现存在key就put的情况。如果你也有这样的疑问,下面有这个问题的答案。

三、filter过滤器的原理

        下面是filter中的源码部分,通过接口中的注释可以看到filter对每一个输入的元素都执行一次predicate的test方法,从而决定集合中是否需要包含这个元素。

        需要注意的是filter方法的入参是一个Predict对象,也就意味着filter每次调用的是precdict对象中的方法,并不是我们前面使用的distinctPredicate方法。distinctPredicate方法的唯一作用就是构造一个precdict对象,所以也不会重复的初始化ConcurrentHashMap<Object, Boolean> map = new ConcurrentHashMap<>()这行代码,因此前一个放入map的数据会一致保存到stream的结束。

 /**
     * Returns a stream consisting of the elements of this stream that match
     * the given predicate.
     *
     * <p>This is an <a href="package-summary.html#StreamOps">intermediate
     * operation</a>.
     *
     * @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>,
     *                  <a href="package-summary.html#Statelessness">stateless</a>
     *                  predicate to apply to each element to determine if it
     *                  should be included

                       // 对每一个元素执行断言,从而判断集合中是否包含这个元素

     * @return the new stream
     */

public final Stream<P_OUT> filter(Predicate<? super P_OUT> predicate) {
        Objects.requireNonNull(predicate);
        return new StatelessOp<P_OUT, P_OUT>(this, StreamShape.REFERENCE,
                                     StreamOpFlag.NOT_SIZED) {
            @Override
            Sink<P_OUT> opWrapSink(int flags, Sink<P_OUT> sink) {
                return new Sink.ChainedReference<P_OUT, P_OUT>(sink) {
                    @Override
                    public void begin(long size) {
                        downstream.begin(-1);
                    }

                    @Override
                    public void accept(P_OUT u) {
                        if (predicate.test(u))
                            downstream.accept(u);
                    }
                };
            }
        };
    }


总结

以上就是通过stream流对集合对象中的根据key去重的方法。如有疑问欢迎指出。。。

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值