90 votes

l'ordre d'itération de keySet () Java HashMap est-il cohérent?

Je comprends que le Jeu retourné à partir d'une Carte du keySet() la méthode ne garantit pas un ordre particulier.

Ma question est, faut-il garantir le même ordre d'itérations multiples. Par exemple

Map<K,V> map = getMap();

for( K k : map.keySet() )
{
}

...

for( K k : map.keySet() )
{
}

Dans le code ci-dessus, en supposant que la carte n'est pas modifié, l'itération sur les claviers être dans le même ordre. À l'aide du Soleil jdk15 il ne itérer dans le même ordre, mais avant que je dépend de ce comportement, je voudrais savoir si tous les Jdk va faire la même chose.

MODIFIER

Je vois dans les réponses que je ne peux pas compter sur elle. Trop mauvais. J'ai été l'espoir de s'en sortir sans avoir à construire une nouvelle Collection pour garantir ma commande. Mon code nécessaire pour la parcourir, faire un peu de logique, et de parcourir par le biais de nouveau avec la même commande. Je vais créer une nouvelle liste de tableaux à partir du clavier, qui permettra de garantir l'ordre.

66voto

ciamej Points 2169

Vous pouvez utiliser un LinkedHashMap si vous voulez un HashMap dont l'ordre d'itération ne change pas.

De plus, vous devriez toujours l'utiliser si vous parcourez la collection. Itérer sur entrySet ou keySet de HashMap est beaucoup plus lent que sur celui de LinkedHashMap.

58voto

Ken Liu Points 7779

Si cela n'est pas indiqué comme étant garanti dans la documentation de l'API, vous ne devriez pas en dépendre. Le comportement peut même changer d'une version du JDK à l'autre, même à partir du JDK du même fournisseur.

Vous pouvez facilement obtenir le jeu et ensuite le trier vous-même, non?

9voto

mpobrien Points 3305

La carte n'est qu'une interface (plutôt que d'une classe), ce qui signifie que le sous-jacent de classe qui l'implémente (et ils sont nombreux) pourrait se comporter différemment, et le contrat de keySet() de l'API n'indiquent pas que la cohérence de l'itération est nécessaire.

Si vous êtes à la recherche à une classe qui implémente la Carte (HashMap, LinkedHashMap, TreeMap, etc) vous pouvez voir comment il met en œuvre le keySet() fonction pour déterminer ce que le comportement serait en vérifiant la source, vous devriez vraiment jeter un oeil de près l'algorithme de voir si le bien que vous cherchez, est préservé (qui est, conformément à l'itération de l'ordre quand la carte n'a pas eu d'insertions/suppressions entre les itérations). La source pour table de hachage, par exemple, est ici (open JDK 6): http://www.docjar.com/html/api/java/util/HashMap.java.html

Il peut varier considérablement d'un JDK pour la prochaine, donc je ne voudrais pas compter sur elle.

Cela étant dit, si elle est conforme à l'itération de l'ordre est quelque chose que vous avez vraiment besoin, vous pourriez vouloir essayer une LinkedHashMap.

7voto

Andrzej Doyle Points 52541

L'API de la Carte ne garantit pas quelque commande que ce soit, même entre les multiples appels de la méthode sur le même objet.

Dans la pratique, je serais très surpris si l'itération ordre a changé pour plusieurs des appels successifs (en supposant que la carte elle-même n'a pas changé entre les deux) - mais vous ne devez pas (et en fonction de l'API ne peut pas) s'appuient sur cette.

EDIT - si vous voulez compter sur l'itération afin d'être cohérent, alors vous voulez une SortedMap qui fournit exactement ces garanties.

5voto

TofuBeer Points 32441

Juste pour le fun, j'ai décidé d'écrire un peu de code que vous pouvez utiliser pour garantir un ordre aléatoire à chaque fois. Ceci est utile de sorte que vous pouvez attraper le cas où vous êtes en fonction sur le bon de commande, mais vous ne devriez pas être. Si vous voulez dépendent de l'ordre, que comme d'autres l'ont dit, vous devez utiliser un SortedMap. Si vous utilisez une Carte et d'arriver à s'appuyer sur le bon de commande, puis en utilisant les suivantes RandomIterator va rattraper ça. J'avais seulement l'utiliser dans le code de test, car il utilise plus de mémoire, ne pas le faire serait.

Vous pouvez aussi envelopper la Carte (ou le Jeu) pour avoir de retour de la RandomeIterator qui serait alors de vous permettre d'utiliser la boucle for-each.

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class Main
{
    private Main()
    {
    }

    public static void main(final String[] args)
    {
        final Map<String, String> items;

        items = new HashMap<String, String>();
        items.put("A", "1");
        items.put("B", "2");
        items.put("C", "3");
        items.put("D", "4");
        items.put("E", "5");
        items.put("F", "6");
        items.put("G", "7");

        display(items.keySet().iterator());
        System.out.println("---");

        display(items.keySet().iterator());
        System.out.println("---");

        display(new RandomIterator<String>(items.keySet().iterator()));
        System.out.println("---");

        display(new RandomIterator<String>(items.keySet().iterator()));
        System.out.println("---");
    }

    private static <T> void display(final Iterator<T> iterator)
    {
        while(iterator.hasNext())
        {
            final T item;

            item = iterator.next();
            System.out.println(item);
        }
    }
}

class RandomIterator<T>
    implements Iterator<T>
{
    private final Iterator<T> iterator;

    public RandomIterator(final Iterator<T> i)
    {
        final List<T> items;

        items = new ArrayList<T>();

        while(i.hasNext())
        {
            final T item;

            item = i.next();
            items.add(item);
        }

        Collections.shuffle(items);
        iterator = items.iterator();
    }

    public boolean hasNext()
    {
        return (iterator.hasNext());
    }

    public T next()
    {
        return (iterator.next());
    }

    public void remove()
    {
        iterator.remove();
    }
}

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