Java - отдельный список объектов - PullRequest
26 голосов
/ 20 июня 2009

У меня есть список / коллекция объектов, которые могут иметь или не иметь одинаковые значения свойств. Какой самый простой способ получить отдельный список объектов с одинаковыми свойствами? Один тип коллекции лучше всего подходит для этой цели? Например, в C # я мог бы сделать что-то вроде следующего с LINQ.

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

Сначала я думал использовать lambdaj ( текст ссылки ), но, похоже, это не поддерживается.

Ответы [ 9 ]

37 голосов
/ 30 июня 2009
return new ArrayList(new HashSet(recipients));
28 голосов
/ 20 июня 2009

Используйте реализацию интерфейса Set<T> (для класса T может потребоваться пользовательский метод .equals(), и вам, возможно, придется реализовать этот .equals() самостоятельно). Обычно HashSet делает это из коробки: для сравнения объектов он использует Object.hashCode() и Object.equals(). Это должно быть достаточно уникальным для простых объектов. Если нет, вам придется реализовать T.equals() и T.hashCode() соответственно.

См. Комментарий Gaurav Saini ниже о библиотеках, помогающих реализовать equals и hashcode.

20 голосов
/ 20 июня 2009

Поместите их в TreeSet, который содержит собственный компаратор, который проверяет нужные вам свойства:

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
11 голосов
/ 24 апреля 2015

Java 8:

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

См. java.util.stream.Stream#distinct.

7 голосов
/ 20 декабря 2013

Если вы используете 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());

Преимущество использования distinct() вместо преобразования в набор и затем обратно в список состоит в том, что distinct() сохраняет порядок исходного списка, сохраняя первое вхождение каждого элемента. Это реализовано с использованием как 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;

Если вы не можете преобразовать свой исходный Список в тип коллекций Eclipse, вы можете использовать ListAdapter для получения того же API.

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

Примечание: я являюсь коммиттером для Eclipse Collections.

7 голосов
/ 24 марта 2013

сохраняющая порядок версия вышеуказанного ответа

return new ArrayList(new LinkedHashSet(recipients));
4 голосов
/ 20 июня 2009

Вы можете использовать Set. Есть пара реализаций:

  • HashSet использует hashCode и equals.
  • TreeSet использует compareTo (определяется Comparable) или compare (определяется Comparator). Имейте в виду, что сравнение должно соответствовать equals. См. TreeSet JavaDocs для получения дополнительной информации.

Также имейте в виду, что если вы переопределяете equals, вы должны переопределить hashCode так, чтобы два равных объекта имели одинаковый хэш-код.

3 голосов
/ 20 июня 2009

Обычным способом сделать это будет преобразование в набор, а затем обратно в список. Но вы можете получить фантазию с Функциональная Java . Если вам понравился Lamdaj, вы полюбите FJ.

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

Вам необходимо определить порядок для получателей, recipientOrd. Что-то вроде:

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

Работает, даже если у вас нет контроля над equals() и hashCode() в классе получателей.

2 голосов
/ 03 августа 2009

На самом деле lambdaj реализует эту функцию с помощью метода selectDistinctArgument

http://lambdaj.googlecode.com/svn/trunk/html/apidocs/ch/lambdaj/Lambda.html#selectDistinctArgument(java.lang.Object,%20A)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...