合并Java 8中的两个对象列表

Manu Joy:

我有一个Parent带有20个属性的Java类(attrib1, attrib2 .. attrib20)及其相应的getter和setters。我也有两个Parent对象列表list1list2

现在,我想合并两个列表,并避免基于attrib1和的重复对象attrib2

使用Java 8:

List<Parent> result = Stream.concat(list1.stream(), list2.stream())
                .distinct()
                .collect(Collectors.toList());   

但是我必须在哪里指定属性?我应该重写hashCodeequals方法吗?

霍尔格:

如果要实现equalsand hashCode,则内部进行操作Parent在该类中添加类似的方法

    @Override
    public int hashCode() {
        return Objects.hash(getAttrib1(), getAttrib2(), getAttrib3(),
            // …
                            getAttrib19(), getAttrib20());
    }

    @Override
    public boolean equals(Object obj) {
        if(this==obj) return true;
        if(!(obj instanceof Parent)) return false;
        Parent p=(Parent) obj;
        return Objects.equals(getAttrib1(), p.getAttrib1())
            && Objects.equals(getAttrib2(), p.getAttrib2())
            && Objects.equals(getAttrib3(), p.getAttrib3())
            // …
            && Objects.equals(getAttrib19(), p.getAttrib19())
            && Objects.equals(getAttrib20(), p.getAttrib20());
    }

如果您这样做了,distinct()在上调用Stream<Parent>将自动执行正确的操作。


如果您不想(或不能)更改类Parent,则没有平等的委托机制,但是您可以求助于排序,因为它具有委托机制:

Comparator<Parent> c=Comparator.comparing(Parent::getAttrib1)
        .thenComparing(Parent::getAttrib2)
        .thenComparing(Parent::getAttrib3)
        // …
        .thenComparing(Parent::getAttrib19)
        .thenComparing(Parent::getAttrib20);

这将基于属性定义顺序。它要求属性本身的类型是可比较的。如果你有这样的定义,你可以用它来实现的等效distinct(),基于这样Comparator

List<Parent> result = Stream.concat(list1.stream(), list2.stream())
        .filter(new TreeSet<>(c)::add)
        .collect(Collectors.toList());

如果您想将其与并行流一起使用,则还有一个线程安全的变体:

List<Parent> result = Stream.concat(list1.stream(), list2.stream())
        .filter(new ConcurrentSkipListSet<>(c)::add)
        .collect(Collectors.toList());

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章