2012-04-16 46 views
12

在我发布这个问题之前,我发现有点类似的问题发布here。但答案是基于String。不过,我在这里有不同的情况。我不是想要删除String,而是另一个名为AwardYearSource的对象。这个类有一个int属性叫做year。所以我想根据年份删除重复项目。即如果2010年有不止一次提及,我想删除该AwardYearSource对象。我怎样才能做到这一点?如何从基于自定义Java对象而不是基元类型的列表中删除重复项?

+0

Java的8路也相当不错:http://stackoverflow.com/questions/23699371/java-8-distinct-by-property – JDC 2016-12-09 07:53:32

回答

45

删除基于字段内容如下(维持秩序)的最简单方法:

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

谢谢。它解决了我的问题。不过,我将代码的第一行更改为Map map = new LinkedHashMap (); ....否则它不会编译。 – WowBow 2012-04-16 15:44:58

+5

对不起,'<>'语法只适用于Java 7. – 2012-04-16 15:47:45

+0

好戏。感谢解决我的问题。 – James 2017-03-29 19:03:22

0

你可以使用地图和存储您的对象与去年作为重点:

Map<Integer, AwardYearSource> map = new HashMap<Integer, AwardYearSource>(); 
map.put(someAwardYearSource1.getYear(), someAwardYearSource1); 
map.put(someAwardYearSource2.getYear(), someAwardYearSource2); 

etc. 

在结束时,地图将在今年包含唯一的值,您可以用数值方法调用:

Collection<AwardYearSource> noDups = map.values(); 
0

用int作为键类型,将你的类作为值类型创建一个HashMap对象。然后遍历该列表,并使用每一个元素插入到地图中:

mymap.put(source.year, source); 

然后从原著列表中删除所有的元素和迭代在地图上,并插入每个元素到列表中。

+0

真的吗?你能否提供更多细节?尽管至少有一个迭代器是不必要的 - 请参阅其他一些答案。如果在线程环境中使用,这会产生一些令人讨厌的副作用。 – 2012-04-16 15:59:52

+0

也许您已在满错误的答案上发布此评论?我在我的解决方案中没有看到任何迭代器,并且它非常安全。 – smichak 2012-04-16 16:10:55

+0

您明确提到迭代,并且您将至少使用一个_implicit_(在for-each构造的情况下生成的编译器)迭代器。如果这是打包在自己的方法(它应该是),然后从原始列表中删除项目是绝对不**线程安全。 – 2012-04-16 16:40:51

1

另一种方法是覆盖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<AwardYearSource> set = new Set<AwardYearSource>(); 

set.add(new AwardYearSource(2011)); 
set.add(new AwardYearSource(2012)); 
set.add(new AwardYearSource(2011)); 

for (AwardYearSource aws : set) { 
    System.out.println(aws.year); 
} 
0

如果您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<AwardYearSource> set = new HashSet<AwardYearSource>(); 
     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]。集合中只有一个项目。

1

相当简单。尽管有些东西让我误解了地图版本(不是我怀疑他们会工作,但它似乎有点矫枉过正,尽管这个版本在这方面不一定更好)。
答案是功能性和线程安全的(假设AwardYearSource是不可变的)。

public static List<AwardYearSource> removeDuplicateYears(
              final Collection<AwardYearSource> awards) { 
    final ArrayList<AwardYearSource> input = new ArrayList<AwardYearSource>(awards); 
    // If there's only one element (or none), guaranteed unique. 
    if (input.size() <= 1) { 
     return input; 
    } 
    final HashSet<Integer> years = new HashSet<Integer>(input.size(), 1); 
    final Iterator<AwardYearSource> 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;  

} 
+0

决赛圈太多了 – 2012-04-16 18:21:33

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

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

相关问题