Как сохранить уникальный список в Java?


Как создать список уникальных / различных объектов (без дубликатов) в Java?

сейчас я использую HashMap<String, Integer> чтобы сделать это, как ключ перезаписывается и, следовательно, в конце мы можем получить HashMap.getKeySet() что было бы уникальным. Но я уверен, что должен быть лучший способ сделать это, поскольку часть стоимости здесь теряется.

7 77

7 ответов:

можно использовать Set реализация:

некоторая информация из JAVADoc:

коллекция, которая содержит нет повторяющихся элементов. Более формально, множества не содержат пары элементов e1 и e2 таких, что e1.равно (e2), и не более одного нулевого элемента. Как следует из его названия, этот интерфейс моделирует математическую абстракцию множества.

Примечание: следует проявлять большую осторожность, если изменяемые объекты используется как набор элементов. Поведение набора не задается, если значение объекта изменяется таким образом, что влияет на сравнения equals, в то время как объект является элементом в наборе. Особым случаем этого запрета является то, что набор не может содержать себя в качестве элемента.-

это реализаций:

  • HashSet

    этот класс обеспечивает постоянную производительность времени для основных операции (add, remove, contains и size), предполагая, что хэш-функция правильно распределяет элементы между сегментами. Итерация по этому набору требует времени, пропорционального сумме размера экземпляра HashSet (количество элементов) плюс "емкость" резервного экземпляра HashMap (количество сегментов). Таким образом, очень важно не устанавливать начальную емкость слишком высокой (или коэффициент нагрузки слишком низкий), если важна производительность итерации.

    при итерации a HashSet порядок данных элементов не определен.

  • LinkedHashSet

    реализация хэш-таблицы и связанного списка заданного интерфейса с предсказуемым порядком итераций. Эта реализация отличается от HashSet тем, что она поддерживает двусвязный список, проходящий через все его записи. Этот связанный список определяет порядок итераций, который является порядком, в котором элементы были вставлены в набор (порядок вставки). Заметить что порядок вставки не влияют, если элемент вставлен в набор. (Элемент e повторно вставляется в набор s, Если s.add(e) вызывается, когда s.contains(e) возвращает true непосредственно перед вызовом.)

    Итак, вывод кода выше...

     Set<Integer> linkedHashSet = new LinkedHashSet<>();
     linkedHashSet.add(3);
     linkedHashSet.add(1);
     linkedHashSet.add(2);
    
     for (int i : linkedHashSet) {
         System.out.println(i);
     }
    

    ...обязательно будет

    3
    1
    2
    
  • TreeSet

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

     Set<Integer> treeSet = new TreeSet<>();
     treeSet.add(3);
     treeSet.add(1);
     treeSet.add(2);
    
     for (int i : treeSet) {
         System.out.println(i);
     }
    

    ...выведет это:

    1
    2
    3
    

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

    обратите внимание, что порядок, поддерживаемый набором (независимо от того, предоставляется ли явный компаратор), должен быть согласован с equals, если он равен правильно реализуйте заданный интерфейс. (См. сопоставимые или компаратором для точного определения непротиворечивым с, равняется.) Это так, потому что интерфейс набора определяется в терминах операции equals, но экземпляр TreeSet выполняет все сравнения элементов с помощью своего метода compareTo (или compare), поэтому два элемента, которые считаются равными этим методом, с точки зрения набора равны. Поведение множества хорошо определено, даже если его упорядочение несовместимо с равными; это просто не соблюдает общий контракт установленного интерфейса.

Я хочу прояснить некоторые вещи здесь для оригинального плаката, на который другие ссылались, но на самом деле явно не заявили. Когда вы говорите, что вам нужен уникальный список, это само определение упорядоченного набора. Некоторые другие ключевые различия между интерфейсом Set и интерфейсом List заключаются в том, что List позволяет указать индекс вставки. Итак, вопрос в том, действительно ли вам нужен интерфейс списка (т. е. для совместимости с библиотекой 3rd party и т. д.), или вы можете раскрутить программное обеспечение для использования установленного интерфейса? Вы также должны рассмотреть, что вы делаете с интерфейсом. Важно ли находить элементы по их индексу? Сколько элементов вы ожидаете в своем наборе? Если у вас будет много элементов, важен ли заказ?

Если вам действительно нужен список, который просто имеет уникальное ограничение, есть Apache Common Utils class org.апаш.палата общин.коллекции.список.SetUniqueList, который предоставит вам интерфейс списка и уникальный ограничение. Однако имейте в виду, что это нарушает интерфейс списка. Однако вы получите лучшую производительность от этого, если вам нужно искать в списке по индексу. Если вы можете иметь дело с интерфейсом Set, и у вас есть меньший набор данных, то LinkedHashSet может быть хорошим способом пойти. Это просто зависит от дизайна и намерений вашего программного обеспечения.

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

использовать new HashSet<String> Пример:

import java.util.HashSet;
import java.util.Set;

public class MainClass {
  public static void main(String args[]) {
    String[] name1 = { "Amy", "Jose", "Jeremy", "Alice", "Patrick" };

    String[] name2 = { "Alan", "Amy", "Jeremy", "Helen", "Alexi" };

    String[] name3 = { "Adel", "Aaron", "Amy", "James", "Alice" };

    Set<String> letter = new HashSet<String>();

    for (int i = 0; i < name1.length; i++)
      letter.add(name1[i]);

    for (int j = 0; j < name2.length; j++)
      letter.add(name2[j]);

    for (int k = 0; k < name3.length; k++)
      letter.add(name3[k]);

    System.out.println(letter.size() + " letters must be sent to: " + letter);

  }
}

вы могли бы просто использовать HashSet<String> для поддержания коллекции уникальных объектов. Если Integer значения в вашей карте важны, то вы можете вместо этого использовать containsKey способ Карты, чтобы проверить, является ли ваш ключ уже в карте.

HashSet<String> (или)Set реализация может сделать работу за вас. Set не допускает дубликатов.

здесь документация для HashSet.

Вы можете использовать один из классов реализации java.util.Set<E> интерфейс, например,java.util.HashSet<String> класс коллекции.

коллекция, которая не содержит повторяющихся элементов. Более формально, множества не содержат пары элементов e1 и e2 таких, что e1.равно (e2), и не более одного нулевого элемента. Как следует из его названия, этот интерфейс моделирует математическую абстракцию множества.

Я не знаю, насколько это эффективно, однако работал для меня в простом контексте.

List<int> uniqueNumbers = new ArrayList<>();

   public void AddNumberToList(int num)
    {
        if(!uniqueNumbers .contains(num)) {
            uniqueNumbers .add(num);
        }
    }