Java – 不同的对象列表

我有一个列表/对象集合,可能有也可能没有相同的属性值。 获得具有相同属性的对象的明确列表的最简单方法是什么? 一种集合类型最适合此目的吗? 例如,在C#中,我可以使用LINQ执行以下操作。

var recipients = (from recipient in recipientList select recipient).Distinct(); 

我最初的想法是使用lambdaj( 链接文本 ),但它似乎不支持这一点。

使用接口Set (类T可能需要自定义.equals()方法,您可能必须自己实现.equals() )。 通常, HashSet开箱即用:它使用Object.hashCode()Object.equals()方法来比较对象。 对于简单的对象来说,这应该是唯一的。 如果没有,你将不得不相应地实现T.equals()T.hashCode()

有关帮助实现equals和hashcode的库,请参阅下面的Gaurav Saini的评论。

 return new ArrayList(new HashSet(recipients)); 

将它们放在一个TreeSet中,该TreeSet包含一个自定义Comparator,它会检查您需要的属性:

 SortedSet set = new TreeSet(new Comparator(){ public int compare(MyObject o1, MyObject o2) { // return 0 if objects are equal in terms of your properties } }); set.addAll(myList); // eliminate duplicates 

Java 8:

 recipients = recipients.stream() .distinct() .collect(Collectors.toList()); 

请参阅java.util.stream.Stream#distinct

如果您正在使用Eclipse Collections ,则可以使用distinct()方法。

 ListIterable integers = Lists.mutable.with(1, 3, 1, 2, 2, 1); Assert.assertEquals( Lists.mutable.with(1, 3, 2), integers.distinct()); 

使用distinct()而不是转换为Set然后返回List的优点是distinct()保留了原始List的顺序,保留了每个元素的第一次出现。 它是通过使用Set和List实现的。

 MutableSet seenSoFar = Sets.mutable.with(); int size = list.size(); for (int i = 0; i < size; i++) { T item = list.get(i); if (seenSoFar.add(item)) { targetCollection.add(item); } } return targetCollection; 

如果无法将原始List转换为Eclipse Collections类型,则可以使用ListAdapter获取相同的API。

 MutableList distinct = ListAdapter.adapt(integers).distinct(); 

注意:我是Eclipse Collections的提交者。

命令保留上述响应的版本

 return new ArrayList(new LinkedHashSet(recipients)); 

您可以使用Set 。 有几个实现:

  • HashSet使用对象的hashCodeequals
  • TreeSet使用compareTo (由Comparable定义)或compare (由Comparator定义)。 请记住,比较必须与equals一致。 有关详细信息,请参阅TreeSet JavaDocs。

还要记住,如果重写equals ,则必须覆盖hashCode ,使得两个equals对象具有相同的哈希码。

这样做的普通方法是转换为Set,然后转换回List。 但是你可以使用Functional Java 。 如果你喜欢Lamdaj,你会爱上FJ。

 recipients = recipients .sort(recipientOrd) .group(recipientOrd.equal()) .map(List.head_()); 

您需要为收件人, recipientOrd定义订单。 就像是:

 Ord recipientOrd = ord(new F2() { public Ordering f(Recipient r1, Recipient r2) { return stringOrd.compare(r1.getEmailAddress(), r2.getEmailAddress()); } }); 

即使您没有在Recipient类上控制equals()hashCode() ,也可以正常工作。