Каков наилучший способ удаления дубликатов в массиве в Java?

У меня есть массив объектов, для которого дубликаты удаляются / фильтруются. Я собирался просто переопределить equals & hachCode на элементах Object, а затем вставить их в Set … но я решил, что должен по крайней мере опросить stackoverflow, чтобы узнать, есть ли другой способ, возможно, какой-нибудь умный метод какого-либо другого API?

Я бы согласился с вашим подходом переопределить hashCode() и equals() и использовать то, что реализует Set .

Это также делает абсолютно ясным для любых других разработчиков, что требуется недвойственная характеристика.

Другая причина – теперь вы можете выбрать реализацию, которая наилучшим образом отвечает вашим потребностям:

  • HashSet
  • TreeSet
  • LinkedHashSet

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

Я нашел это в Интернете

Вот два метода, которые позволяют удалять дубликаты в ArrayList. removeDuplicate не поддерживает порядок, когда removeDuplicateWithOrder поддерживает заказ с некоторыми издержками производительности.

  1. Метод removeDuplicate:

     /** List order not maintained **/ public static void removeDuplicate(ArrayList arlList) { HashSet h = new HashSet(arlList); arlList.clear(); arlList.addAll(h); } 
  2. Метод removeDuplicateWithOrder:

     /** List order maintained **/ public static void removeDuplicateWithOrder(ArrayList arlList) { Set set = new HashSet(); List newList = new ArrayList(); for (Iterator iter = arlList.iterator(); iter.hasNext();) { Object element = iter.next(); if (set.add(element)) newList.add(element); } arlList.clear(); arlList.addAll(newList); } 

Первой мыслью было переопределение equals и hashCode и создание набора. Хорошая практика – иметь некоторую переопределенную версию этих методов в любом случае в вашей иерархии наследования.

Я думаю, что если вы используете LinkedHashSet вы даже сохраните порядок уникальных элементов …

В принципе, вам нужна реализация LinkedHashSet которая поддерживает интерфейс List для произвольного доступа. Следовательно, это то, что вам нужно:

public class LinkedHashSetList extends LinkedHashSet implements List {

// Implementations for List methods here ...

}

Реализация методов List позволит получить доступ к базовому LinkedHashSet и манипулировать им. Хитрость заключается в том, чтобы этот class вел себя правильно, когда пытались добавить дубликаты с помощью методов List add (исключение или повторное добавление элемента в другом индексе были бы параметрами: вы можете либо выбрать один из них, либо сделать настраиваемый пользователями classа).

Я хотел бы повторить точку зрения Джейсона в комментариях:

Зачем ставить себя на этот счет?

Зачем использовать массив для структуры данных, в которой не должно быть дубликатов?

Используйте Set или SortedSet (когда элементы также имеют естественный порядок), чтобы удерживать элементы. Если вам нужно сохранить порядок вставки, вы можете использовать LinkedHashSet как было указано.

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

Конечно, исходный пост задает вопрос: «Как вы получили этот массив (который мог содержать дублированные записи) в первую очередь?»

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

В качестве альтернативы, если вам нужно знать количество вхождений каждого значения, вы можете использовать Map для отслеживания подсчетов. Кроме того, определение classов Multimap в Google Collections может быть полезным.

Используйте List toRemove для записи элемента в первый раз, когда iterator наткнется на него, а затем, когда снова встретите записанный элемент, удалите его с помощью iterator.remove()

  private void removeDups (Список списка) {
         Список toRemove = новый ArrayList ();
         for (Итератор it = list.iterator (); it.hasNext ();) {
             Объект next = it.next ();
             if (! toRemove.contains (next)) {
                 toRemove.add (далее);
             } else {
                 it.remove ();
             }
         }
         toremove.clear ();
    } 

Set , безусловно, лучший выбор. Единственный способ удалить вещи из массива (без создания нового) – это их исключить, а затем вы получите много нулевых проверок позже.

Говоря из общего стандарта программирования, вы всегда можете удвоить перечисление коллекций, а затем сравнить источник и цель.

И если ваше внутреннее перечисление всегда запускает одну запись после источника, это довольно эффективно (псевдокод следует следовать)

 foreach ( array as source ) { // keep track where we are in the array place++; // loop the array starting at the entry AFTER the current one we are comparing to for ( i=place+1; i < max(array); i++ ) { if ( source === array[place] ) { destroy(array[i]); } } } 

Вы могли бы, возможно, добавить перерыв; после уничтожения, но тогда вы обнаружите только первый дубликат, но если это все, что вы когда-либо имели, то это была бы небольшая оптимизация.

  • Вопросы, на которые должен отвечать каждый хороший Java / Java EE Developer?
  • Полиморфизм против переопределения и перегрузки
  • Темабезопасный одноэлементный class
  • Что делает InputStream.available () в Java?
  • Как преобразовать строку, разделенную запятой, в ArrayList?
  • Java-соединение и HTTPS-соединение без скачивания сертификата
  • Когда запрос com port возвращает тот же запрос
  • JApplet создает мяч, который отскакивает и становится все более низким в Java
  • JFreeChart PolarPlot: математическая ориентация
  • Захват SIGINT в Java
  • Время Джоды: первый день недели?
  • Давайте будем гением компьютера.