Подтвердить что ты не робот

Как удалить дубликаты из списка?

Я хочу удалить дубликаты из списка, но то, что я делаю, не работает:

List<Customer> listCustomer = new ArrayList<Customer>();    
for (Customer customer: tmpListCustomer)
{
  if (!listCustomer.contains(customer)) 
  {
    listCustomer.add(customer);
  }
 }
4b9b3361

Ответ 1

Если этот код не работает, вероятно, вы не внедрили equals(Object) в класс Customer.

Предположительно есть некоторый ключ (назовем его customerId), который однозначно идентифицирует клиента; например.

class Customer {
    private String customerId;
    ...

Соответствующее определение equals(Object) будет выглядеть так:

    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        }
        if (!(obj instanceof Customer)) {
            return false;
        }
        Customer other = (Customer) obj;
        return this.customerId.equals(other.customerId);
    }

Для полноты вы также должны реализовать hashCode, чтобы два одинаковых объекта Customer вернули одно и то же значение хэш-функции. Соответствующим hashCode для вышеуказанного определения equals будет:

    public int hashCode() {
        return customerId.hashCode();
    }

Также стоит отметить, что это не эффективный способ удаления дубликатов, если список большой. (Для списка с N клиентами вам необходимо выполнить сравнения N*(N-1)/2 в худшем случае, т.е. Когда дубликатов нет.) Для более эффективного решения вы должны использовать что-то вроде HashSet для проверки дубликатов.

Ответ 2

Предполагая, что вы хотите сохранить текущий порядок и не хотите Set, возможно, самый простой способ:

List<Customer> depdupeCustomers =
    new ArrayList<>(new LinkedHashSet<>(customers));

Если вы хотите изменить исходный список:

Set<Customer> depdupeCustomers = new LinkedHashSet<>(customers);
customers.clear();
customers.addAll(dedupeCustomers);

Ответ 3

Выполняет ли клиент контракт equals()?

Если он не реализует equals() и hashCode(), тогда listCustomer.contains(customer) проверяет, существует ли тот же самый экземпляр в списке (к примеру, я имею в виду точный адрес объекта - память и т.д.). Если то, что вы ищете, - это проверить, есть ли в этом списке один и тот же Клиент (возможно, тот же клиент, если у них есть то же имя клиента или номер клиента), тогда вам нужно будет переопределить equals(), чтобы обеспечить что он проверяет, соответствуют ли соответствующие поля (например, имена клиентов).

Примечание. Не забудьте переопределить hashCode(), если вы собираетесь переопределить equals()! В противном случае у вас могут возникнуть проблемы с вашими HashMaps и другими структурами данных. Для хорошего освещения причин этого и того, что можно избежать, подумайте о том, чтобы взглянуть на главы Josh Bloch Эффективные Java на equals() и hashCode() (Ссылка содержит только информацию о том, почему вы должны реализовать hashCode() при реализации equals(), но есть хорошее представление о том, как переопределить equals() тоже).

Кстати, есть ли ограничение на ваш набор? Если этого не происходит, немного проще решить эту проблему, используйте Set<Customer> так:

Set<Customer> noDups = new HashSet<Customer>();
noDups.addAll(tmpListCustomer);
return new ArrayList<Customer>(noDups);

Что будет приятно удалять дубликаты для вас, так как наборы не позволяют дублировать. Однако это потеряет любое упорядочение, которое было применено к tmpListCustomer, так как HashSet не имеет явного упорядочения (вы можете обойти это с помощью TreeSet, но это не совсем связано с вашим вопросом). Это может немного упростить ваш код.

Ответ 4

Обновление java 8
вы можете использовать поток массива, как показано ниже:

Arrays.stream(yourArray).distinct()
                    .collect(Collectors.toList());

Ответ 5

Список → Набор → Список (отдельный)

Просто добавьте все свои элементы в Set: он не позволяет повторять его элементы. Если после этого вам понадобится список, используйте новый конструктор ArrayList(theSet) (где theSet - ваш результирующий набор).

Ответ 6

Я подозреваю, что у вас может не быть Customer.equals() правильно реализован (или вообще).

List.contains() использует equals(), чтобы проверить, идентичен ли какой-либо из его элементов объекту, переданному как параметр. Тем не менее, реализация по умолчанию equals проверяет физическую идентичность, а не идентификатор ценности. Поэтому, если вы не перезаписали его в Customer, он вернет false для двух разных объектов Customer, имеющих одинаковое состояние.

Вот подробные подробности как реализовать equalshashCode, который является его парой - вы должны практически всегда реализовывать оба варианта, если вам нужно реализовать любой из них). Поскольку вы не показали нам класс Customer, трудно дать более конкретные рекомендации.

Как отмечали другие, вам лучше использовать Set вместо выполнения задания вручную, но даже для этого вам все равно нужно реализовать эти методы.

Ответ 7

Метод "содержит" проверяет, содержит ли список запись, возвращающую значение true из Customer.equals(Object o). Если вы не переопределили equals (Object) в Customer или один из его родителей, тогда он будет искать только существующее вхождение одного и того же объекта. Возможно, это было то, что вы хотели, и в этом случае ваш код должен работать. Но если вы искали не имеющие двух объектов, представляющих одного и того же клиента, тогда вам нужно переопределить equals (Object), чтобы вернуть true, когда это так.

Верно также, что использование одной из реализаций Set вместо List дало бы вам повторное удаление автоматически и быстрее (для чего угодно, кроме очень маленьких списков). Вам все равно нужно предоставить код для равных.

Вы также должны переопределить hashCode() при переопределении equals().

Ответ 8

private void removeTheDuplicates(List<Customer>myList) {
    for(ListIterator<Customer>iterator = myList.listIterator(); iterator.hasNext();) {
        Customer customer = iterator.next();
        if(Collections.frequency(myList, customer) > 1) {
            iterator.remove();
        }
    }
    System.out.println(myList.toString());

}

Ответ 9

Два предложения:

  • Используйте HashSet вместо ArrayList. Это значительно ускорит проверку contains(), если у вас длинный список

  • Убедитесь, что Customer.equals() и Customer.hashCode() реализованы правильно, то есть они должны основываться на комбинированных значениях лежащих в основе полей в объекте клиента.

Ответ 10

Почти все приведенные выше ответы верны, но я предлагаю использовать Map или Set при создании соответствующего списка, а не после получения производительности. Поскольку преобразование списка в Set или Map, а затем повторное преобразование его в список снова является тривиальной работой.

Пример кода:

Set<String> stringsSet = new LinkedHashSet<String>();//A Linked hash set 
//prevents the adding order of the elements
for (String string: stringsList) {
    stringsSet.add(string);
}
return new ArrayList<String>(stringsSet);

Ответ 11

Как уже упоминалось, вы, вероятно, не используете equals() правильно.

Однако следует также отметить, что этот код считается весьма неэффективным, поскольку время выполнения может быть числом квадратов элементов.

Возможно, вы захотите рассмотреть возможность использования структуры Set вместо списка, или сначала создать набор, а затем превратить его в список.

Ответ 12

Самый чистый способ:

List<XXX> lstConsultada = dao.findByPropertyList(YYY);
List<XXX> lstFinal = new ArrayList<XXX>(new LinkedHashSet<GrupoOrigen>(XXX));

и переопределить hascode и equals по свойствам Id каждого объекта

Ответ 13

ИМХО лучший способ, как это сделать в наши дни:

Предположим, что у вас есть коллекция " dups", и вы хотите создать другую коллекцию, содержащую те же элементы, но со всеми дублирующимися исключениями. Следующий однострочный трюк делает трюк.

Collection<collectionType> noDups = new HashSet<collectionType>(dups);

Он работает, создавая набор, который по определению не может содержать дубликатов.

Основываясь на документе оракула. ​​

Ответ 14

Правильный ответ для Java - это Set. Если у вас уже есть List<Customer> и вы хотите его дублировать

Set<Customer> s = new HashSet<Customer>(listCustomer);

В другом случае просто используйте Set реализацию HashSet, TreeSet и пропустите этап построения List.

Вам необходимо переопределить hashCode() и equals() в своих классах домена, которые помещаются в Set, а также убедитесь, что поведение, которое вы хотите, действительно то, что вы получаете. equals() может быть таким же простым, как сравнение уникальных идентификаторов объектов с такими сложными, как сравнение каждого поля. hashCode() может быть таким же простым, как возврат hashCode() уникального представления id 'String или hashCode().

Ответ 15

Использование java 8 stream api.

    List<String> list = new ArrayList<>();
    list.add("one");
    list.add("one");
    list.add("two");
    System.out.println(list);
    Collection<String> c = list.stream().collect(Collectors.toSet());
    System.out.println(c);

Вывод:

До значений: [один, один, два]

После значений: [один, два]

Ответ 16

Class removeduplicates 
{
    public static void main(string args[[])
    {   
        int I;
        for(int =0;i'<10;I++)
        {
            system.out.println(+i);
            if([]I=[j])
            {
                system.out.println(1,2,3,1,1,1,2,2,2)
            }
        }
    }
}