Java - 不同的对象列表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1019854/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 22:20:20  来源:igfitidea点击:

Java - Distinct List of Objects

javalistcollections

提问by javacavaj

I have a list/collection of objects that may or may not have the same property values. What's the easiest way to get a distinct list of the objects with equal properties? Is one collection type best suited for this purpose? For example, in C# I could do something like the following with LINQ.

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

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

My initial thought was to use lambdaj (link text), but it doesn't appear to support this.

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

采纳答案by glmxndr

Use an implementation of the interface Set<T>(class T may need a custom .equals()method, and you may have to implement that .equals()yourself). Typically a HashSetdoes it out of the box : it uses Object.hashCode()and Object.equals()method to compare objects. That should be unique enough for simple objects. If not, you'll have to implement T.equals()and T.hashCode()accordingly.

使用接口的实现Set<T>(类 T 可能需要自定义.equals()方法,您可能必须.equals()自己实现)。通常 aHashSet是开箱即用的:它使用Object.hashCode()Object.equals()方法来比较对象。对于简单的对象,这应该足够独特。如果没有,你就必须执行T.equals()T.hashCode()相应。

See Gaurav Saini's comment below for libraries helping to implement equals and hashcode.

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

回答by Robert Munteanu

Place them in a TreeSet which holds a custom Comparator, which checks the properties you need:

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

SortedSet<MyObject> set = new TreeSet<MyObject>(new Comparator<MyObject>(){

    public int compare(MyObject o1, MyObject o2) {
         // return 0 if objects are equal in terms of your properties
    }
});

set.addAll(myList); // eliminate duplicates

回答by Steve Kuo

You can use a Set. There's couple of implementations:

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

  • HashSetuses an object's hashCodeand equals.
  • TreeSetuses compareTo(defined by Comparable) or compare(defined by Comparator). Keep in mind that the comparison must be consistent with equals. See TreeSetJavaDocs for more info.
  • HashSet使用对象的hashCodeand equals
  • TreeSet使用compareTo(由 定义Comparable)或compare(由 定义Comparator)。请记住,比较必须与 一致equals。有关TreeSet更多信息,请参阅JavaDocs。

Also keep in mind that if you override equalsyou must override hashCodesuch that two equals objects has the same hash code.

还请记住,如果您覆盖,则equals必须覆盖以hashCode使两个 equals 对象具有相同的哈希码。

回答by Apocalisp

The ordinary way of doing this would be to convert to a Set, then back to a List. But you can get fancy with Functional Java. If you liked Lamdaj, you'll love FJ.

执行此操作的普通方法是转换为 Set,然后再转换为 List。但是你可以喜欢Functional Java。如果你喜欢 Lamdaj,你就会喜欢 FJ。

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

You'll need to have defined an ordering for recipients, recipientOrd. Something like:

您需要为收件人定义排序,recipientOrd. 就像是:

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

Works even if you don't have control of equals()and hashCode()on the Recipient class.

即使您无法控制equals()和控制hashCode()Recipient 类,也能正常工作。

回答by Chase Seibert

return new ArrayList(new HashSet(recipients));

回答by Mario Fusco

回答by rudnev

order preserving version of the above response

上述响应的顺序保留版本

return new ArrayList(new LinkedHashSet(recipients));

回答by Craig P. Motlin

If you're using Eclipse Collections, you can use the method distinct().

如果您使用的是Eclipse Collections,则可以使用 方法distinct()

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

The advantage of using distinct()instead of converting to a Set and then back to a List is that distinct()preserves the order of the original List, retaining the first occurrence of each element. It's implemented by using both a Set and a List.

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

MutableSet<T> 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;

If you cannot convert your original List into an Eclipse Collections type, you can use ListAdapterto get the same API.

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

MutableList<Integer> distinct = ListAdapter.adapt(integers).distinct();

Note: I am a committer for Eclipse Collections.

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

回答by Dexter Legaspi

Java 8:

爪哇 8:

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

See java.util.stream.Stream#distinct.

java.util.stream.Stream#distinct