在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
Merging two List of objects in java 8
提问by Manu Joy
I have a Java class Parent
with 20 attributes (attrib1, attrib2 .. attrib20)
and its corresponding getters and setters. Also I have two lists of Parent
objects: list1
and list2
.
我有一个Parent
带有 20 个属性的 Java 类(attrib1, attrib2 .. attrib20)
及其相应的 getter 和 setter。我还有两个Parent
对象列表:list1
和list2
.
Now I want to merge both lists and avoid duplicate objects based on attrib1
and 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 hashCode
and equals
method?
但是我必须在哪个地方指定属性?我应该覆盖hashCode
和equals
方法吗?
采纳答案by Holger
If you want to implement equals
and hashCode
, the place to do it is insidethe class Parent
. Within that class add the methods like
如果你想实现equals
and 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 equals
and hashCode
methods in Parent
class to avoid duplicates from the lists. This will give you the exact result what you want.
覆盖类中的equals
和hashCode
方法Parent
以避免列表中的重复项。这将为您提供您想要的确切结果。
回答by llogiq
If you want to override .equals(…)
and .hashCode()
, you need to do so on the Parent
class. Note that this may cause other uses of Parent
to 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);
}
}