Существует ли дублирующая реализация списка?

Я знаю о SortedSet, но в моем случае мне нужно что-то, что реализует List, а не Set. Так есть ли реализация там, в API или где-то еще?

Нельзя было бы реализовать себя, но я решил, почему сначала не спрашивать людей здесь?

Ответ 1

В стандартной библиотеке нет коллекции Java. LinkedHashSet<E> сохраняет упорядочение аналогично List, поэтому, если вы завернете свой набор в List, когда хотите использовать это как List вы получите семантику, которую хотите.

В качестве альтернативы Commons Collections (или commons-collections4 для общей версии) имеет List, который делает то, что вы хотите уже: SetUniqueList/SetUniqueList<E>.

Ответ 2

Итак, вот что я сделал в конце концов. Надеюсь, это поможет кому-то другому.

class NoDuplicatesList<E> extends LinkedList<E> {
    @Override
    public boolean add(E e) {
        if (this.contains(e)) {
            return false;
        }
        else {
            return super.add(e);
        }
    }

    @Override
    public boolean addAll(Collection<? extends E> collection) {
        Collection<E> copy = new LinkedList<E>(collection);
        copy.removeAll(this);
        return super.addAll(copy);
    }

    @Override
    public boolean addAll(int index, Collection<? extends E> collection) {
        Collection<E> copy = new LinkedList<E>(collection);
        copy.removeAll(this);
        return super.addAll(index, copy);
    }

    @Override
    public void add(int index, E element) {
        if (this.contains(element)) {
            return;
        }
        else {
            super.add(index, element);
        }
    }
}   

Ответ 3

Вот что я сделал, и он работает.

Предполагая, что у меня есть ArrayList для работы с первым, что я сделал, был создан новый LinkedHashMap.

LinkedHashSet<E> hashSet = new LinkedHashSet<E>()

Затем я пытаюсь добавить свой новый элемент в LinkedHashSet. Метод добавления не изменяет LinkedHasSet и возвращает false, если новый элемент является дубликатом. Таким образом, это условие, которое я могу проверить перед добавлением в ArrayList.

if (hashSet.add(E)) arrayList.add(E);

Это простой и элегантный способ предотвратить добавление дубликатов в список массивов. Если вы хотите, вы можете инкапсулировать его и переопределить метод add в классе, который расширяет ArrayList. Просто помните, что нужно иметь дело с addAll, перейдя через элементы и вызывая метод добавления.

Ответ 4

Вы должны серьезно рассмотреть ответ dhiller:

  • Вместо того, чтобы беспокоиться о добавлении ваших объектов в список, не содержащий дубликатов, добавьте их в Set (любая реализация), которая по своей природе будет фильтровать дубликаты.
  • Когда вам нужно вызвать метод, требующий List, оберните его в new ArrayList(set) (или a new LinkedList(set), что угодно).

Я думаю, что решение, которое вы разместили с NoDuplicatesList, имеет некоторые проблемы, в основном с помощью метода contains(), а также ваш класс не обрабатывает проверку дубликатов в коллекции, переданной вашему методу addAll().

Ответ 5

Почему бы не инкапсулировать набор со списком, вроде как:

new ArrayList( new LinkedHashSet() )

Это оставляет другую реализацию для кого-то, кто является настоящим мастером коллекций; -)

Ответ 6

Мне нужно было что-то вроде этого, поэтому я пошел в коллекцию commons и использовал SetUniqueList, но когда я запустил некоторый тест производительности, я обнаружил, что он не оптимизирован по сравнению с случаем, если я хочу использовать Set и получить Массив с использованием метода Set.toArray(), SetUniqueTest занял 20: 1 раз, чтобы заполнить, а затем пересечь 100 000 строк по сравнению с другой реализацией, что является большой разницей, поэтому, если вы беспокоитесь об эффективности, я рекомендую вам использовать Set и получить Array вместо использования SetUniqueList, если вам действительно не нужна логика SetUniqueList, тогда вам нужно проверить другие решения...

Основной метод тестового кода:

public static void main (String [] args) {

SetUniqueList pq = SetUniqueList.decorate(new ArrayList());
Set s = new TreeSet();

long t1 = 0L;
long t2 = 0L;
String t;


t1 = System.nanoTime();
for (int i = 0; i < 200000; i++) {
    pq.add("a" + Math.random());
}
while (!pq.isEmpty()) {
    t = (String) pq.remove(0);
}
t1 = System.nanoTime() - t1;

t2 = System.nanoTime();
for (int i = 0; i < 200000; i++) {
    s.add("a" + Math.random());
}

s.clear();
String[] d = (String[]) s.toArray(new String[0]);
s.clear();
for (int i = 0; i < d.length; i++) {
    t = d[i];

}
t2 = System.nanoTime() - t2;

System.out.println((double)t1/1000/1000/1000); //seconds
System.out.println((double)t2/1000/1000/1000); //seconds
System.out.println(((double) t1) / t2);        //comparing results

}

Отношения Мохаммед Слейм http://abusleem.net/blog

Ответ 7

Документация для интерфейсов коллекции:

Set - коллекция, которая не может содержать повторяющиеся элементы.
Список - упорядоченная коллекция (иногда называемая последовательностью). Списки могут содержать повторяющиеся элементы.

Итак, если вы не хотите дубликатов, вы, вероятно, не должны использовать список.

Ответ 8

Сверху моей головы списки позволяют дублировать. Вы можете быстро реализовать UniqueArrayList и переопределить все функции add/insert, чтобы проверить contains() перед вызовом унаследованных методов. Для личного использования вы можете использовать только метод add, который вы используете, и переопределить остальные, чтобы исключить исключение, если будущие программисты попытаются использовать список другим способом.

Ответ 9

в add, почему бы не использовать HashSet.add() для проверки дубликатов вместо HashSet.consist(). HashSet.add() вернет true, если нет дубликата и false в противном случае.

Ответ 10

ПРИМЕЧАНИЕ. В него не включена реализация subList.

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

public class UniqueList<T> extends ArrayList<T> {

    private static final long serialVersionUID = 1L;

    /** Unique elements SET */
    private final Set<T> set=new HashSet();

    /** Used by addAll methods */
    private Collection<T> addUnique(Collection<? extends T> col) {
        Collection<T> unique=new ArrayList();
        for(T e: col){
            if (set.add(e)) unique.add(e);
        }
        return unique;
    }

    @Override
    public boolean add(T e) {
        return set.add(e) ? super.add(e) : false;
    }

    @Override
    public boolean addAll(Collection<? extends T> col) {
        return super.addAll(addUnique(col));
    }

    @Override
    public void add(int index, T e) {
        if (set.add(e)) super.add(index, e);
    }

    @Override
    public boolean addAll(int index, Collection<? extends T> col) {
        return super.addAll(index, addUnique(col));
    }

}

Ответ 11

Я просто сделал свой собственный UniqueList в своей собственной маленькой библиотеке, например:

package com.bprog.collections;//my own little set of useful utilities and classes

import java.util.HashSet;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author Jonathan
*/
public class UniqueList {

private HashSet masterSet = new HashSet();
private ArrayList growableUniques;
private Object[] returnable;

public UniqueList() {
    growableUniques = new ArrayList();
}

public UniqueList(int size) {
    growableUniques = new ArrayList(size);
}

public void add(Object thing) {
    if (!masterSet.contains(thing)) {
        masterSet.add(thing);
        growableUniques.add(thing);
    }
}

/**
 * Casts to an ArrayList of unique values
 * @return 
 */
public List getList(){
    return growableUniques;
}

public Object get(int index) {
    return growableUniques.get(index);
}

public Object[] toObjectArray() {
    int size = growableUniques.size();
    returnable = new Object[size];
    for (int i = 0; i < size; i++) {
        returnable[i] = growableUniques.get(i);
    }
    return returnable;
    }
}

У меня есть класс TestCollections, который выглядит так:

package com.bprog.collections;
import com.bprog.out.Out;
/**
*
* @author Jonathan
*/
public class TestCollections {
    public static void main(String[] args){
        UniqueList ul = new UniqueList();
        ul.add("Test");
        ul.add("Test");
        ul.add("Not a copy");
        ul.add("Test"); 
        //should only contain two things
        Object[] content = ul.toObjectArray();
        Out.pl("Array Content",content);
    }
}

Прекрасно работает. Все, что он делает, это добавление к множеству, если оно уже не имеет его, и есть возвращаемый Arraylist, а также массив объектов.