Если вы проверяете дубликат перед вставкой в ​​набор

Я изучаю использование наборов. Мой вопрос: наборы не содержат дубликатов. Когда мы пытаемся вставить дубликаты, это не вызывает никакой ошибки и автоматически удаляет дубликаты. Является ли хорошей практикой проверять каждое значение перед вставкой в ​​набор, существует ли он или нет? Или это нормально делать что-то вроде приведенного ниже кода? Я думаю, что Java будет делать внутреннюю проверку, используя .contains(value). Как вы думаете?

Какова была бы сложность Big O в обоих случаях, учитывая, что в набор входит n элементов?

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

public class DuplicateTest {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
         Set<Integer> mySet = new HashSet<Integer>();

         mySet.add(10);
         mySet.add(20);
         mySet.add(30);
         mySet.add(40);
         mySet.add(50);
         mySet.add(50);
         mySet.add(50);
         mySet.add(50);
         mySet.add(50);
         mySet.add(50);

         System.out.println("Contents of the Hash Set :"+mySet);
    }

}

Ответы

Ответ 1

В соответствии с docs:

public boolean add(E e)

Добавляет указанный элемент к этому набору, если он еще не присутствует. Более формально добавляет указанный элемент e к этому набору, если этот набор не содержит элемента e2, такого, что (e == null? E2 == null: e.equals(e2)). Если этот набор уже содержит элемент, вызов оставляет неизменным и возвращает false.

Итак, метод add() уже возвращает вам значение true или false. Поэтому вам не нужно делать дополнительную проверку.

Ответ 2

Сравните с документацию API Set.add(E)

Метод add проверяет, находится ли элемент уже в Set. Если элемент уже присутствует, то новый элемент не добавляется, а Set остается неизменным. В большинстве случаев вам не нужно ничего проверять.

Сложность метода зависит от конкретной реализации Set, который вы используете.

Ответ 3

Его нормально не проверять. Это основное преимущество над наборами списков, поскольку они автоматически отфильтровывают дубликаты.

HashSet имеет постоянную производительность (http://docs.oracle.com/javase/8/docs/api/java/util/HashSet.html)

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

Ответ 4

Функция add возвращает логическое значение, которое вы можете проверить, чтобы определить, был ли элемент уже установлен в Set. Это, конечно, основывается на ваших потребностях и не является лучшей практикой. Хорошо знать, что он не удалит элемент, который уже существует, поэтому он не может зависеть, чтобы обновить существующее значение с помощью новой информации, если вы определяете равные на основе суррогатных ключей из своей базы данных. Это противоположно тому, как Карты работают как карта, возвратит любое существующее значение и заменит его новым значением.

Ответ 5

Вот ответы на ваши вопросы:

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

Ваше понимание неверно. Вызов Set.add() не будет добавлять новый элемент, если он уже находится в наборе; это утверждение применяется ко всем реализациям Set, включая HashSet и TreeSet.

Хорошо ли проверять каждое значение перед вставкой в ​​набор существует ли это или нет? или это нормально сделать что-то вроде ниже код? Я думаю, что java будет внутренне выполнять проверку, используя .contains(значение). Как вы думаете?

Поскольку ваше понимание было неправильным с самого начала, вам не нужно проверять каждое значение перед вставкой в ​​набор, чтобы увидеть, существует ли он уже. Да, внутри, он делает что-то вроде contains().

Какова будет сложность Big Oh в обоих случаях, учитывая есть "n" элементов, входящих в множество?

Для HashSet временная сложность O(1) для каждого add(). Для TreeSet() - который вы не использовали - временная сложность O(lg N) для каждого add().