当前位置: 首页 > 知识库问答 >
问题:

使用Java 8从两个具有唯一id的列表中合并对象

柳胡媚
2023-03-14
class Human {
    Long humanId;
    String name;
    Long age;
}


class SuperHuman {
    Long superHumanId;
    Long humanId;
    String name;
    Long age;
}

我有两张单子。人类名单和超人名单。我想从这两个列表中创建一个列表,确保如果一个人是超人,那么它只会在使用Java8的列表中出现一次。有什么好办法吗?更新:这些是不同的类,即两者都不扩展另一个。我希望最后的名单是超人。如果一个人已经是超人了,我们就忽略了这个人类对象。如果人不是超人,我们就把人的物体变成超人的物体。理想情况下,我希望在最后按年龄对他们进行排序,这样我就可以得到一个按日期降序排列的超人名单。

共有3个答案

纪实
2023-03-14

试试这个。

List<Object> result = Stream.concat(
    humans.stream()
        .filter(h -> !superHumans.stream()
            .anyMatch(s -> h.humanId == s.humanId)),
    superHumans.stream())
    .collect(Collectors.toList());
夹谷和韵
2023-03-14

对于如何重新分解代码以使其更好,您确实有其他建议,但如果您做不到这一点,有一种方法——通过自定义的收集器,并没有那么复杂。

自定义收集器还可以让您实际决定要保留哪个条目,即已收集的条目、即将收集的条目或最新的条目。这需要对代码进行一些更改,但在您可能需要的情况下,这是可行的。

 private static <T> Collector<Human, ?, List<Human>> noDupCollector(List<SuperHuman> superHumans) {
    class Acc {

        ArrayList<Long> superIds = superHumans.stream()
                .map(SuperHuman::getHumanId)
                .collect(Collectors.toCollection(ArrayList::new));

        ArrayList<Long> seen = new ArrayList<>();

        ArrayList<Human> noDup = new ArrayList<>();

        void add(Human elem) {
            if (superIds.contains(elem.getHumanId())) {

                if (!seen.contains(elem.getHumanId())) {
                    noDup.add(elem);
                    seen.add(elem.getHumanId());
                }

            } else {
                noDup.add(elem);
            }
        }

        Acc merge(Acc right) {
            noDup.addAll(right.noDup);
            return this;
        }

        public List<Human> finisher() {
            return noDup;
        }

    }
    return Collector.of(Acc::new, Acc::add, Acc::merge, Acc::finisher);
}

假设您有以下条目:

List<SuperHuman> superHumans = Arrays.asList(
            new SuperHuman(1L, 1L, "Superman"));
    //
    List<Human> humans = Arrays.asList(
            new Human(1L, "Bob"),
            new Human(1L, "Tylor"),
            new Human(2L, "John"));

这样做:

List<Human> noDup = humans.stream()
            .collect(noDupCollector(superHumans));

System.out.println(noDup); // [Bob, Tylor]

薛博赡
2023-03-14

根据你最新的问题:

List<Human> humans = ... // init 
List<SuperHuman> superHumans = ... // init

Set<Long> superHumanIds = superHumans.stream()
    .map(SuperHuman::getHumanId)
    .collect(toSet());

humans.stream()
    .filter(human -> superHumanIds.contains(human.getHumanId()))
    .map(this::convert)
    .forEach(superHumans::add);

superHumans.sort(Comparator.comparing(SuperHuman::getAge));

假设该类有另一个具有以下签名的方法:

private Superhuman convert(Human human) {
    // mapping logic
}
 类似资料:
  • 我有一个Java类,它有20个属性及其相应的getter和setter。还有两个对象列表:和。 使用Java 8: 但是我必须在哪个地方指定属性呢?是否应该重写和方法?

  • 我有一个用户定义的对象,称为员工,如下所示,并有两个不同的列表,其中包含员工对象。 在这两个不同的列表中,我需要根据对象中的名称字段找到唯一的对象。最终列表应仅包含一个名为c的对象。 请建议我如何使用java 8做到这一点?

  • 首先,我的问题类似于这个已经回答过的问题,在Java中,将两个arrayList合并成一个新的arrayList,没有重复项,并且顺序正确。 然而,这里的不同之处在于,我尝试将两个列表合并在一起,而不仅仅是一个字符串。我的意图是合并以下类型的两个对象(为了简化,我从示例中去掉了不必要的信息): 所以我得到了一个新的项目,它有一个总结计数。这将消除不需要的重复,因为这些对象上的uniqueKey是相

  • 问题内容: 我有一个表格,其中包含所有新信息。该表用作所有新闻源查询的参考,因此从那里选择事件项,并从正确的表中检索与该事件相对应的信息。 现在,这是我的问题。我在事件表中有,它对应于不同表中事件的ID,例如for ,for 等等。这些ID可能相同,所以暂时我只是使用了一个不同的auto_increment值对于每个这样在500 上以0等开始的表。显然,我不想这样做,因为我还不知道哪个表中的数据最

  • 问题内容: 我有两个表(表A和表B)。 它们具有不同的列数-假设表A具有更多列。 如何合并这两个表,并为表B没有的列获取空值? 问题答案: 为具有较少列的表添加额外的列作为null

  • 问题内容: 我有以下Java6和Java8代码: Java8中有什么方法可以使用Lambda以更简洁的方式处理前一个问题? 问题答案: 流绑定到给定的可迭代/集合,因此您不能真正地“并行”迭代两个集合。 一种解决方法是创建索引流,但不一定比for循环有所改进。流版本可能如下所示: