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

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

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

7 ответов


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

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

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

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

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

  • поиска HashSet

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

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

  • LinkedHashSet

    хэш-таблица и реализация связанного списка интерфейса Set с предсказуемым порядком итераций. Эта реализация отличается от 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, если он правильно реализуйте интерфейс Set. (См. Comparable или Comparator для точного определения согласованного с равными.) Это так, потому что интерфейс Set определен в терминах операции equals, но экземпляр TreeSet выполняет все сравнения элементов с помощью своего метода compareTo (или compare), поэтому два элемента, которые считаются равными этим методом, с точки зрения множества равны. Поведение множества хорошо определено, даже если его упорядочение несовместимо с equals; это просто не выполняет общий контракт интерфейса Set.


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

Если вам действительно нужен список, который просто имеет уникальное ограничение, есть 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 не допускает дубликатов.

здесь javadoc для 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);
        }
    }