27 votes

LinkedHashSet - ordre d'insertion et doublons - garder le plus récent "en haut"

J'ai besoin d'une collection qui maintient l'ordre d'insertion et a des valeurs uniques. LinkedHashSet ressemble à la voie à suivre, mais il ya un problème - lorsque les deux éléments sont égaux, il supprime le plus récent (ce qui est logique), voici un exemple:

set.add("one");
set.add("two");
set.add("three");
set.add("two");

L' LinkedHashSet affichera:

one, two, three

Mais ce dont j'ai besoin est:

one, three, two

Quelle serait la meilleure solution ici? Est-il de la collection/collections méthode qui peut le faire ou dois-je mettre en œuvre manuellement?

26voto

OldCurmudgeon Points 16615

La plupart des collections Java peuvent être étendues pour peaufiner.

Sous-classe LinkedHashSet , remplaçant la méthode add .

 class TweakedHashSet<T> extends LinkedHashSet<T> {

    @Override
    public boolean add(T e) {
        // Get rid of old one.
        boolean wasThere = remove(e);
        // Add it.
        super.add(e);
        // Contract is "true if this set did not already contain the specified element"
        return !wasThere;
    }

}
 

14voto

Holger Points 13789

Vous pouvez tout simplement utiliser une fonction spéciale de l' LinkedHashMap:

Set<String> set = Collections.newSetFromMap(new LinkedHashMap<>(16, 0.75f, true));
set.add("one");
set.add("two");
set.add("three");
set.add("two");
System.out.println(set); // prints [one, three, two]

Dans d'Oracle JRE l' LinkedHashSet , soutenu par un LinkedHashMap de toute façon, donc il n'y a pas beaucoup de différence fonctionnelle, mais que les constructeur utilisé ici configure l' LinkedHashMap pour changer l'ordre sur tous les accès non seulement sur l'insertion. Cela peut paraître comme étant pour beaucoup, mais en fait, affecte l'insertion de contenait déjà des touches (les valeurs dans le sens de l' Set) seulement. Les autres Map des opérations (à savoir, get) ne sont pas utilisés par le retour de l' Set.

Si vous n'êtes pas à l'aide de Java 8, vous devez aider le compilateur un peu à cause de la quantité limitée d'inférence de type:

Set<String> set
    = Collections.newSetFromMap(new LinkedHashMap<String, Boolean>(16, 0.75f, true));

mais la fonctionnalité est la même.

5voto

Toonijn Points 199

Lors de l'initialisation de votre LinkedHashSet, vous pouvez remplacer la méthode add.

 Set<String> set = new LinkedHashSet<String>(){
    @Override
    public boolean add(String s) {
        if(contains(s))
            remove(s);
        return super.add(s);
    }
};
 

Maintenant, cela vous donne:

 set.add("1");
set.add("2");
set.add("3");
set.add("1");
set.addAll(Collections.singleton("2"));

// [3, 1 ,2]
 

même la méthode addAll fonctionne.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X