如何根据自定义java对象而不是基本类型从列表中删除重复项?

在我发布这个问题之前,我发现在这里发布了类似的问题。 但答案是基于一个字符串。 但是,我在这里有不同的情况。 我不是要删除String而是另一个名为AwardYearSource的对象。 该类有一个名为year的int属性。 所以我想删除基于年份的重复项。 即如果有不止一次提到的2010年,我想删除该AwardYearSource对象。 我怎样才能做到这一点?

基于字段删除元素的最简单方法如下(保留顺序):

Map map = new LinkedHashMap<>(); for (AwardYearSource ays : list) { map.put(ays.getYear(), ays); } list.clear(); list.addAll(map.values()); 

另一种方法是覆盖equals(Object obj) hashCode()equals(Object obj) 。 由于它只需要一个字段来确定相等性,因此非常简单。 就像是:

 public boolean equals(Object obj) { if (obj == null || !(obj instanceof AwardYearSource)) { return false; } return (this.year == ((AwardYearSource)obj).year); } public int hashCode() { return this.year; } 

然后你可以将所有对象都粘贴到一个Set以删除重复项:

 Set set = new Set(); set.add(new AwardYearSource(2011)); set.add(new AwardYearSource(2012)); set.add(new AwardYearSource(2011)); for (AwardYearSource aws : set) { System.out.println(aws.year); } 

相当简单。 虽然有些东西让我对地图版本感到不安(不是我怀疑它们是否有效,但它似乎有点矫枉过正,不知怎的 – 虽然这个版本在这方面不一定更好)。
答案是function性的,线程安全的(假设AwardYearSource是不可变的)。

 public static List removeDuplicateYears( final Collection awards) { final ArrayList input = new ArrayList(awards); // If there's only one element (or none), guaranteed unique. if (input.size() <= 1) { return input; } final HashSet years = new HashSet(input.size(), 1); final Iterator iter = input.iterator(); while(iter.hasNext()) { final AwardYearSource award = iter.next(); final Integer year = award.getYear(); if (years.contains(year)) { iter.remove(); } else { years.add(year); } } return input; } 

您可以使用地图并将年份作为关键字存储在您的对象中:

 Map map = new HashMap(); map.put(someAwardYearSource1.getYear(), someAwardYearSource1); map.put(someAwardYearSource2.getYear(), someAwardYearSource2); etc. 

最后,地图将按年份包含唯一值,您可以使用values方法调用:

 Collection noDups = map.values(); 

创建一个HashMap对象,其中int作为键类型,您的类作为值类型。 然后迭代列表并使用以下方法将每个元素插入到地图中:

 mymap.put(source.year, source); 

然后从origianl列表中删除所有元素并迭代地图并将每个元素插入到列表中。

如果您的AwardYearSource类重写了equals和hashcode方法(Eclipse可以生成两者),那么您可以将它们添加到Set中。 该集不包含任何重复项。

 public class AwardYearSource { private final int year; public AwardYearSource(int year) { this.year = year; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + year; return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; AwardYearSource other = (AwardYearSource) obj; if (year != other.year) return false; return true; } @Override public String toString() { return String.valueOf(year); } public static void main(String[] args) { Set set = new HashSet(); set.add(new AwardYearSource(2000)); set.add(new AwardYearSource(2000)); set.add(new AwardYearSource(2000)); set.add(new AwardYearSource(2000)); System.out.println(set); } } 

输出是[2000]。 集合中只有一个项目。

 Set set = new HashSet<>(); list.removeIf(i -> set.contains(i.getYear()) ? true : !set.add(i.getYear())); 

这应该有助于其中,在这种情况下,基于某些属性(或属性的组合)决定重复。 希望这可以帮助。