首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何根据属性减去两个对象列表?

如何根据属性减去两个对象列表?
EN

Stack Overflow用户
提问于 2022-05-25 07:11:16
回答 2查看 221关注 0票数 1

我有两个Java对象列表

比方说dataToBeAdded,dataToBeSubtracted

这些对象具有相同的数据类型,并具有多个属性。

DummyObject{ attr1,attr2,attr3,attr4 }

我想合并这些列表,但是如果attr1、attr2、attr3在列表中匹配,则以有条件的方式进行合并

减去attr4并使其成为列表的一部分。

如果属性不匹配

  • 元素来自list1(dataToBeadded),将其添加到输出中,因为它是

  • 元素来自list2(dataToBeSubtracted)使attr4负(乘-1)

这就像是一个完全的外连接操作

我用地图和溪流做了一些事情

代码语言:javascript
复制
        Map<String, DummyObj> dataToBeAddedMap = dataToBeAdded.stream()
                .collect(Collectors.toMap(obj -> obj.attr1() + obj.attr2() + obj.attr3(), item -> item));

        Map<String, CumulativeSalesDataByHour> dataToBeSubtractedMap = dataToBeSubtracted.stream()
                .collect(Collectors.toMap( obj -> obj.attr1() + obj.attr2() + obj.attr3(), item ->
                        new DummyObject(item.attr1(), item.attr2(), item.attr3(), -1 * item.attr4())));

        Map<String, DummyObject> resultantData = Stream.of(dataToBeAddedMap, dataToBeSubtractedMap)
                .flatMap(map -> map.entrySet().stream())
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        Map.Entry::getValue,
                        (v1, v2) -> new DummyObject(v1.attr1(),
                                v1.attr2(),
                                v1.attr3(),
                                v1.attr4() + v2.attr4())
                ));

        System.out.println(resultantData.values());

这给了我想要的结果,但是否有更有效的方法来实现这一点呢?

编辑1:

添加输入和预期输出

代码语言:javascript
复制
        DummyObject a1 = new DummyObject("uuid1", "abcd", "mer1", 20D);
        DummyObject a2 = new DummyObject("uuid1", "pqrs", "mer1", 25D);
        DummyObject a3 = new DummyObject("uuid2", "xyz", "mer1", 18D);

        List<DummyObject> dataToBeAdded = ImmutableList.of(a1,a2,a3);

        DummyObject d1 = new DummyObject("uuid1", "abcd", "mer1", 5D);
        DummyObject d2 = new DummyObject("uuid1", "pqrs", "mer1", 2D);
        DummyObject d3 = new DummyObject("uuid3", "xyz", "mer2", 10D);

        List<DummyObject> dataToBeSubtracted = ImmutableList.of(d1,d2,d3);

        Desired Output
        [

            DummyObject("uuid1", "abcd", "mer1", 15D); // 20-5
            DummyObject("uuid1", "pqrs", "mer1", 23D); // 25-2
            DummyObject("uuid2", "xyz", "mer1", 18D); 
            DummyObject("uuid3", "xyz", "mer1", -10D); 

        ]    
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-05-25 07:42:53

与其为要添加的元素和要减去的元素创建两个额外的Map,不如立即使用两个List创建一个链式流,并将减法List的每个元素映射到一个attr4字段已经被否定的元素。

然后,您可以使用Map终端操作在单个collect(Collectors.toMap())中收集所有对象。关键是前3个字段的连接,值将是对象本身,而冲突案例可以通过创建一个新的DummyObj来处理,该字段与您要分组的3个字段相同,第四个字段由第一个和第二个碰撞值的attr4之和(类似于您在上一个流中所做的)。

另一个小的改进可能不是将字符串与+操作符链接起来,后者为每个连接创建一个新的String,而是使用String.format()方法生成单个String来按(减少开销)对元素进行分组。

代码语言:javascript
复制
Map<String, DummyObj> mapRes = Stream.concat(dataToBeAdded.stream(), dataToBeSubtracted.stream().map(obj -> {
            obj.setAttr4(-1 * obj.getAttr4());
            return obj;
        }))
        .collect(Collectors.toMap(obj -> String.format("%s%s%s", obj.getAttr1(), obj.getAttr2(), obj.getAttr3()),
                Function.identity(),
                (obj1, obj2) -> new DummyObj(obj1.getAttr1(), obj1.getAttr2(), obj1.getAttr3(), obj1.getAttr4() + obj2.getAttr4())
        ));

下面是测试上面代码的链接:

https://ideone.com/K5qfsI

票数 2
EN

Stack Overflow用户

发布于 2022-05-25 08:32:54

如果你真的想要性能,你需要重写管道--无论发生什么事情,你都会问这个问题?使用前3个属性作为键(也许可以创建一个新的类来表示这3个属性),这样就有了两个映射。

但是,如果管道不能改变,最快的算法是:

iterator-1.

  • If

  • 编写一个比较器对这些列表进行排序。

  • 生成2个迭代器(每个迭代器一个)。

  • 生成一个输出列表。

  • 循环,为两个迭代器创建一个“当前项”指针。如果当前-1低于当前-2(或完成当前-2),复制电流-1和前进的电流-2低于当前-1(或当前-1完成),则在c-2上翻转符号,添加和iterator-2.

  • If当前-1和当前-2是相同的,适当地更新attr4,然后两者都提前。

  • 如果两者都完成了,则返回输出列表.

它将大大增加代码,但它不会产生任何新的瞬态对象,除了两个迭代器和一个比较器。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72373297

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档