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

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

Я пытаюсь найти реализацию java.util.List и java.util.Set одновременно в Java. Я хочу, чтобы этот класс допускал только уникальные элементы (как Set) и сохранял их порядок (например, List). Он существует в JDK 6?

Важно иметь List<T>#add(int, T), поэтому я могу вставить его в определенную позицию.

4b9b3361

Ответ 1

TreeSet отсортирован по порядку элементов; LinkedHashSet сохраняет порядок вставки. Надеюсь, один из них - это то, что вы искали.

Вы указали, что хотите иметь возможность вставлять в произвольном месте, я подозреваю, что вам придется написать свой собственный - просто создайте класс, содержащий HashSet<T> и ArrayList<T>; при добавлении элемента, проверьте, есть ли он в наборе, прежде чем добавить его в список.

В качестве альтернативы Apache commons-collection4 предлагает ListOrderedSet и SetUniqueList, которые ведут себя аналогично и должны отвечать заданным требованиям.

Ответ 3

Вы имеете в виду как LinkedHashSet? Это сохраняет порядок ввода, но не позволяет дублировать.

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

class SetList<T> extends ArrayList<T> {
    @Override
    public boolean add(T t) {
        return !super.contains(t) && super.add(t);
    }

    @Override
    public void add(int index, T element) {
        if (!super.contains(element)) super.add(index, element);
    }

    @Override
    public boolean addAll(Collection<? extends T> c) {
        boolean added = false;
        for (T t : c)
            added |= add(t);
        return added;
    }

    @Override
    public boolean addAll(int index, Collection<? extends T> c) {
        boolean added = false;
        for (T t : c)
            if (!super.contains(t)) {
                super.add(index++, t);
                added = true;
            }
        return added;
    }
}

Ответ 4

Вы не можете реализовать List и Set сразу без нарушения контракта. См., Например, контракт Set.hashCode:

Хэш-код набора определяется как сумма хэш-кодов элементов в наборе, где хэш-код нулевого элемента определяется как нуль.

С другой стороны, здесь заключен договор List.hashCode:

Хэш-код списка определяется как результат следующего вычисления:

int hashCode = 1;
for (E e : list)
    hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());

Таким образом, невозможно реализовать единый класс, который гарантирует выполнение обоих контрактов. Эта же проблема для реализации equals.

Ответ 5

Если вы не будете ограничивать себя JDK 6, вы можете использовать коллекцию общих коллекций Apache, которая предлагает точное соответствие для вашей потребности - ListOrderedSet. Это как List и Set вместе взятые:)

Ответ 6

У меня была аналогичная проблема, поэтому я написал свой собственный. См. здесь. IndexedArraySet расширяет ArrayList и реализует Set, поэтому он должен поддерживать все операции, которые вам нужны. Обратите внимание: вставка элементов в середину ArrayList может быть медленной для больших списков, потому что все перечисленные элементы необходимо переместить. Мой IndexedArraySet не меняет этого.

Ответ 7

Другой вариант (минус требование интерфейса List) - это Guava ImmutableSet, который сохраняет порядок вставки. Из их wiki-страница:

За исключением отсортированных коллекций, порядок сохраняется из времени построения. Например,

ImmutableSet.of("a", "b", "c", "a", "d", "b")

будет перебирать свои элементы в порядке "a", "b", "c", "d".