在java 8中合并两个对象列表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30866753/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 10:17:37  来源:igfitidea点击:

Merging two List of objects in java 8

javajava-8java-stream

提问by Manu Joy

I have a Java class Parentwith 20 attributes (attrib1, attrib2 .. attrib20)and its corresponding getters and setters. Also I have two lists of Parentobjects: list1and list2.

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

Now I want to merge both lists and avoid duplicate objects based on attrib1and attrib2.

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

Using Java 8:

使用 Java 8:

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

But in which place I have to specify the attributes? Should I override hashCodeand equalsmethod?

但是我必须在哪个地方指定属性?我应该覆盖hashCodeequals方法吗?

采纳答案by Holger

If you want to implement equalsand hashCode, the place to do it is insidethe class Parent. Within that class add the methods like

如果你想实现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());
    }

If you did this, distinct()invoked on a Stream<Parent>will automatically do the right thing.

如果你这样做了,distinct()在 a 上调​​用Stream<Parent>将自动做正确的事情。



If you don't want (or can't) change the class Parent, there is no delegation mechanism for equality, but you may resort to orderingas that has a delegation mechanism:

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

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

This defines an order based on the properties. It requires that the types of the attributes itself are comparable. If you have such a definition, you can use it to implement the equivalent of a distinct(), based on that Comparator:

这定义了基于属性的顺序。它要求属性本身的类型具有可比性。如果你有这样的定义,你可以使用它来实现 a 的等价物distinct(),基于它Comparator

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

There is also a thread-safe variant, in case you want to use it with parallel streams:

还有一个线程安全的变体,以防你想将它与并行流一起使用:

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

回答by Dominic D'Souza

Override the equalsand hashCodemethods in Parentclass to avoid duplicates from the lists. This will give you the exact result what you want.

覆盖类中的equalshashCode方法Parent以避免列表中的重复项。这将为您提供您想要的确切结果。

回答by llogiq

If you want to override .equals(…)and .hashCode(), you need to do so on the Parentclass. Note that this may cause other uses of Parentto fail. Alexis C.'s linked solution is more conservative.

如果你想覆盖.equals(…)and .hashCode(),你需要在Parent类上这样做。请注意,这可能会导致 的其他用途Parent失败。Alexis C. 的链接解决方案更为保守。

回答by saka1029

For example:

例如:

public class Parent {

    public int no;
    public String name;

    @Override
    public int hashCode() {
        return (no << 4) ^ name.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Parent))
            return false;
        Parent o = (Parent)obj;
        return this.no == o.no && this.name.equals(o.name);
    }
}