it-swarm.com.de

Gibt es eine List-Implementierung ohne Duplikate?

Ich kenne SortedSet , aber in meinem Fall brauche ich etwas, das List und nicht Set implementiert. Gibt es eine Implementierung in der API oder anderswo?

Es sollte nicht schwer sein, mich umzusetzen, aber ich dachte mir, warum fragst du nicht zuerst die Leute hier?

81
Yuval

Es gibt keine Java -Auflistung in der Standardbibliothek, um dies zu tun. LinkedHashSet<E> behält jedoch die Reihenfolge ähnlich wie bei einem List bei. Wenn Sie also Ihr Set in ein List einwickeln, wenn Sie es als List verwenden möchten, werden Sie Holen Sie sich die Semantik, die Sie wollen.

Alternativ kann die Commons Collections (oder commons-collections4, für die generische Version) hat ein List, das macht, was Sie bereits wollen: SetUniqueList / SetUniqueList<E> .

86
Calum

Hier ist was ich getan habe und es funktioniert.

Angenommen, ich habe ein ArrayList, um mit dem ersten, was ich getan habe, zu arbeiten, wurde ein neues LinkedHashMap erstellt.

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

Dann versuche ich, mein neues Element zum LinkedHashSet hinzuzufügen. Die add-Methode ändert das LinkedHasSet nicht und gibt false zurück, wenn das neue Element ein Duplikat ist. Dies wird zu einer Bedingung, die ich testen kann, bevor ich sie zum ArrayList hinzufüge.

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

Dies ist eine einfache und elegante Methode, um das Hinzufügen von Duplikaten zu einer Array-Liste zu verhindern. Wenn Sie möchten, können Sie es in eine Klasse einkapseln und die add-Methode überschreiben, die das ArrayList erweitert. Denken Sie daran, mit addAll umzugehen, indem Sie die Elemente durchlaufen und die Methode add aufrufen.

12
user3570018

Also hier ist, was ich letztendlich getan habe. Ich hoffe das hilft jemand anderem.

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);
        }
    }
}   
10
Yuval

Sie sollten ernsthaft über die Antwort von dhiller nachdenken:

  1. Anstatt sich Gedanken über das Hinzufügen Ihrer Objekte zu einer Liste ohne Duplikate zu machen, fügen Sie sie einem Set (einer beliebigen Implementierung) hinzu, das die Duplikate von Natur aus herausfiltert.
  2. Wenn Sie die Methode aufrufen müssen, für die eine Liste erforderlich ist, müssen Sie sie in eine new ArrayList(set) (oder eine new LinkedList(set) (was auch immer) einschließen.

Ich denke, dass die Lösung, die Sie mit NoDuplicatesList gepostet haben, einige Probleme hat, hauptsächlich mit der contains() -Methode, und Ihre Klasse kann nicht nach Duplikaten in der Sammlung suchen, die an Ihre addAll() Methode.

4
matt b

Warum nicht eine Menge mit einer Liste kapseln, sortieren wie:

new ArrayList( new LinkedHashSet() )

Dies lässt die andere Implementierung für jemanden, der ein echter Meister der Sammlungen ist ;-)

4
Daniel Hiller

Ich brauchte so etwas, also ging ich zu den allgemeinen Sammlungen und verwendete die SetUniqueList. Als ich jedoch einen Leistungstest durchführte, stellte ich fest, dass sie im Vergleich zu dem Fall nicht optimiert zu sein scheint, wenn ich ein Set verwenden und ein Array mit dem Array erhalten möchte Bei der Set.toArray () -Methode dauerte der SetUniqueTest 20: 1, um 100.000 Strings zu füllen und dann zu durchlaufen, verglichen mit der anderen Implementierung. Dies ist ein großer Unterschied. Wenn Sie sich also Gedanken über die Leistung machen, empfehle ich Ihnen, Set und zu verwenden Holen Sie sich ein Array, anstatt die SetUniqueList zu verwenden. Wenn Sie die Logik der SetUniqueList nicht wirklich benötigen, müssen Sie andere Lösungen überprüfen ...

Die Testcode-Hauptmethode:

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

}

Grüße Mohammed Sleem http://abusleem.net/blog

3
Mohammed Sleem

HINWEIS: Die Implementierung von subList wird nicht berücksichtigt.

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));
    }

}
1
marcolopes

Das Dokumentation für Collection Interfaces sagt:

Set - Eine Sammlung, die keine doppelten Elemente enthalten darf.
Liste - eine geordnete Sammlung (manchmal auch als Sequenz bezeichnet). Listen können doppelte Elemente enthalten.

Wenn Sie also keine Duplikate möchten, sollten Sie wahrscheinlich keine Liste verwenden.

0
Hauch