web-dev-qa-db-fra.com

Comment ajouter un élément à un index/une position spécifique dans LinkedHashMap?

J'ai commandé un LinkedHashMap et je veux ajouter un élément à un index spécifique, par exemple au premier ou dernier endroit de la carte ..__ Comment puis-je ajouter un élément dans LinkedHashMap à une position spécifique?

Même si je pouvais ajouter un élément à la position FIRST ou LAST dans LinkedHashMap, cela aiderait! 

39
supernova

Vous pouvez faire cet élément en ajoutant à 1. ou à la dernière place:

Ajout au dernier lieu ► Il vous suffit de supprimer l'entrée précédente de la carte, comme ceci:

map.remove(key);
map.put(key,value);

Ajouter à la première place ► C'est un peu plus compliqué, vous devez cloner la carte, la supprimer, lui attribuer la valeur 1., puis y placer la nouvelle carte, comme suit:

J'utilise des cartes avec des clés String et des valeurs Group (ma classe personnalisée):

LinkedHashMap<String, Group> newmap=(LinkedHashMap<String, Group>) map.clone();
map.clear();
map.put(key, value);
map.putAll(newm);

Comme vous le voyez, avec ces méthodes, vous pouvez ajouter un nombre illimité d'éléments au début et à la fin de la carte.

18
gyurix

Solution Apache Commons: ListOrderedMap

Comme la variable LinkedHashMap du JDK garantit uniquement l'extraction de l'ordre d'insertion, si vous souhaitez insérer un index, vous pouvez également utiliser la variable ListOrderedMap d'Apache Commons. Il le fait comme il semble - en ayant une liste pour maintenir l'ordre d'insertion avec l'index correspondant et une carte normale à insérer comme nous le faisons généralement. Voici ce que disent les docs :

public class ListOrderedMap<K,V>
extends AbstractMapDecorator<K,V>
implements OrderedMap<K,V>, Serializable

Décore une Map pour s'assurer que l'ordre d'addition est conservé en utilisant une liste pour maintenir l'ordre.

La commande sera utilisée via les itérateurs et les méthodes toArray sur le fichier vues. La commande est également retournée par le MapIterator. Le La méthode orderedMapIterator() accède à un itérateur qui peut effectuer une itération en avant et en arrière sur la carte. En outre, des méthodes non-interface sont fournies pour accéder à la carte par index.

Si un objet est ajouté à la carte pour la deuxième fois, il restera dans la position d'origine dans l'itération.

Notez que ListOrderedMap n'est pas synchronisé et n'est pas thread-safe . Si vous souhaitez utiliser cette carte à partir de plusieurs threads simultanément, vous doit utiliser la synchronisation appropriée. L'approche la plus simple consiste à envelopper cette carte en utilisant Collections.synchronizedMap(Map). Cette classe peut émet des exceptions en cas d'accès par des threads concurrents sans synchronisation.

Notez que ListOrderedMap ne fonctionne pas avec IdentityHashMap, CaseInsensitiveMap, ou des cartes similaires qui violent le général contrat de Map. La ListOrderedMap (ou, plus précisément, le Sous-jacent List) s'appuie sur equals(). C'est bien, tant que la Map décorée est également basée sur equals() et hashCode(), que IdentityHashMap et CaseInsensitiveMap ne font pas: L'ancien utilise ==, et ce dernier utilise equals() sur une clé minuscule.

Voici son implémentation pour ajouter à une position:

        /**
428     * Puts a key-value mapping into the map at the specified index.
429     * <p>
430     * If the map already contains the key, then the original mapping
431     * is removed and the new mapping added at the specified index.
432     * The remove may change the effect of the index. The index is
433     * always calculated relative to the original state of the map.
434     * <p>
435     * Thus the steps are: (1) remove the existing key-value mapping,
436     * then (2) insert the new key-value mapping at the position it
437     * would have been inserted had the remove not occurred.
438     *
439     * @param index  the index at which the mapping should be inserted
440     * @param key  the key
441     * @param value  the value
442     * @return the value previously mapped to the key
443     * @throws IndexOutOfBoundsException if the index is out of range [0, size]
444     * @since 3.2
445     */
446    public V put(int index, final K key, final V value) {
447        if (index < 0 || index > insertOrder.size()) {
448            throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + insertOrder.size());
449        }
450
451        final Map<K, V> m = decorated();
452        if (m.containsKey(key)) {
453            final V result = m.remove(key);
454            final int pos = insertOrder.indexOf(key);
455            insertOrder.remove(pos);
456            if (pos < index) {
457                index--;
458            }
459            insertOrder.add(index, key);
460            m.put(key, value);
461            return result;
462        }
463        insertOrder.add(index, key);
464        m.put(key, value);
465        return null;
466    }
8
pulp_fiction
public static <K, V> void add(LinkedHashMap<K, V> map, int index, K key, V value) {
  assert (map != null);
  assert !map.containsKey(key);
  assert (index >= 0) && (index < map.size());

  int i = 0;
  List<Entry<K, V>> rest = new ArrayList<Entry<K, V>>();
  for (Entry<K, V> entry : map.entrySet()) {
    if (i++ >= index) {
      rest.add(entry);
    }
  }
  map.put(key, value);
  for (int j = 0; j < rest.size(); j++) {
    Entry<K, V> entry = rest.get(j);
    map.remove(entry.getKey());
    map.put(entry.getKey(), entry.getValue());
  }
}
6
tamalet

Il suffit de vous diviser LinkedHashMap sur 2 tableaux. Faire le premier tableau avec la taille index - 1 et mettre à la fin new Entry Puis remplissez le premier tableau avec les entrées du second

6
rock_walker
...

LinkedHashMap<String, StringExtension> map = new LinkedHashMap<>();

map.put("4", new StringExtension("4", "a"));
map.put("1", new StringExtension("1", "b"));
map.put("3", new StringExtension("3", "c"));
map.put("2", new StringExtension("2", "d"));

for (Map.Entry<String, StringExtension> entry : map.entrySet()) {
    Log.e("Test", "" + entry.getKey() + " - "+ entry.getValue().value);
}


Collection<StringExtension> temp = new ArrayList<>(map.values());
StringExtension value = map.remove("3");
map.clear();
map.put(value.key, value);

for (StringExtension val : temp) {
    map.put(val.key, val);
}

Log.e("Test", "---");

for (Map.Entry<String, StringExtension> entry : map.entrySet()) {
    Log.e("Test", "" + entry.getKey() + " - "+ entry.getValue().value);
}

...

private class StringExtension
{
    String key;
    String value;

    public StringExtension(String key, String value) {
        this.key = key;
        this.value = value;
    }
}
1
Nauman Aejaz