我有一个Java类Parent
,其中包含20个属性(attrib1, attrib2 .. attrib20)
及其相应的getter和setter。此外,我还有两个Parent
个对象列表:list1
和list2
。
现在我想合并两个列表,避免基于attrib1
和attrib2
的重复对象。
使用Java 8:
List<Parent> result = Stream.concat(list1.stream(), list2.stream())
.distinct()
.collect(Collectors.toList());
但是我必须在哪个地方指定属性?我应该覆盖hashCode
和equals
方法吗?
答案 0 :(得分:22)
如果您要实施equals
和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());
答案 1 :(得分:1)
例如:
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);
}
}
答案 2 :(得分:0)
覆盖equals
类中的hashCode
和Parent
方法,以避免重复列表。这将为您提供您想要的确切结果。
答案 3 :(得分:0)
如果您要覆盖.equals(…)
和.hashCode()
,则需要在Parent
课程上执行此操作。请注意,这可能会导致Parent
的其他用途失败。 Alexis C.的链接解决方案更加保守。