Wie füge ich ein Element an einem bestimmten Index / einer bestimmten Position in LinkedHashMap hinzu?
Lesezeit: 8 Minuten
Supernova
Ich habe eine bestellte LinkedHashMap und möchte ein Element an einem bestimmten Index hinzufügen, z. B. an erster oder letzter Stelle in der Karte. Wie kann ich ein Element in LinkedHashMap an einer bestimmten Position hinzufügen?
Selbst wenn ich ein Element zur ERSTEN oder LETZTEN Position in LinkedHashMap hinzufügen könnte, würde das helfen!
Aus den Dokumenten: „Beachten Sie, dass die Einfügungsreihenfolge nicht beeinflusst wird, wenn ein Schlüssel erneut in die Karte eingefügt wird. (Ein Schlüssel k wird erneut in eine Karte m eingefügt, wenn m.put(k, v) aufgerufen wird, wenn m.containsKey(k ) würde unmittelbar vor dem Aufruf true zurückgeben.)”
– Andreas
10. Dezember 2018 um 18:38 Uhr
Gyurix
Sie könnten dieses Element zur 1. oder letzten Stelle hinzufügen:
Hinzufügen zum letzten Platz ► Sie müssen nur den vorherigen Eintrag wie folgt aus der Karte entfernen:
map.remove(key);
map.put(key,value);
Hinzufügen zum ersten Platz ► Es ist etwas komplizierter, Sie müssen die Karte klonen, löschen, den 1. Wert hinzufügen und die neue Karte hinzufügen, wie folgt:
Ich verwende Karten mit String-Schlüsseln und Gruppenwerten (meine benutzerdefinierte Klasse):
Wie Sie sehen, können Sie mit diesen Methoden unbegrenzt viele Dinge am Anfang und am Ende der Karte hinzufügen.
Beachten Sie, dass mit dieser Methode eine Kopie der Objekte in der Karte erstellt wird. Etwas könnte kaputt gehen, wenn Sie diese Objekte anderweitig verwenden.
– Omaraf
3. August 2017 um 7:12 Uhr
Beachten Sie den dadurch entstehenden Speicher-Overhead. Vermeiden Sie es am besten, dies zu verwenden.
– Simon Baar
6. Oktober 2017 um 10:38 Uhr
@Omaraf erstellt eine flache Kopie der Karte. Am Ende ist “map” das gleiche Objekt und Schlüssel und Werte sind auch die gleichen Objekte. Wenn die Karte nicht viele Schlüssel hat, wird der Speicheraufwand nicht riesig sein. Aber natürlich – wenn Sie können – verwenden Sie dafür eine andere Datenstruktur 🙂
– Fehler_
26. Juli 2021 um 9:24 Uhr
Tobias
Sie können die Reihenfolge nicht ändern. es ist insert-order (standardmäßig) oder access-order mit diesem Konstruktor:
public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder)
Erstellt eine leere LinkedHashMap-Instanz mit der angegebenen Anfangskapazität, dem Lastfaktor und dem Sortiermodus.
Parameter: initialCapacity – die Anfangskapazität loadFactor – der Lastfaktor accessOrder – der Sortiermodus – true für die Zugriffsreihenfolge, false für die Einfügungsreihenfolge
Löst aus: IllegalArgumentException – wenn die anfängliche Kapazität negativ oder der Lastfaktor nicht positiv ist
Tks. Es bedeutet, dass NUR die Bestellung, zu der ich ein Element hinzufügen kann, LETZTER Platz ist. Wie Sie bereits erwähnt haben, behält es die Reihenfolge bei, also bin ich davon ausgegangen, dass es am letzten Index jedes neue Element hinzufügen wird! Eigentlich musste ich nur Elemente an der ERSTEN oder LETZTEN Stelle hinzufügen. Letzter Ort, den ich bekommen kann, denn um an erster Stelle hinzuzufügen, kann ich das am Ende zu einer anderen Karte hinzufügen?
– Supernova
6. Oktober 2011 um 20:17 Uhr
Sie könnten eine neue Liste mit dem neuen Element erstellen und die komplette andere Liste danach mit addAll(); aber das ist Speicherverschwendung und die Karte ist nicht für diesen Zweck erstellt.
– Tobias
6. Oktober 2011 um 20:20 Uhr
Tks.That sieht aus wie die einzige Lösung mit LinkedHashMap.
– Supernova
6. Oktober 2011 um 20:27 Uhr
@supernova Sie können jederzeit Ihre eigenen erstellen, dies ist keine Einschränkung einer LinkedHashMap, sondern eine Einschränkung der LinkedHashMap-Implementierung von Java
– Schrittmacher
24. April 2012 um 22:26 Uhr
Apache Commons-Lösung: ListOrderedMap
Da die JDK’s LinkedHashMap stellt nur das Abrufen der Insertionsreihenfolge sicher, falls Sie in einen Index einfügen möchten, können wir alternativ Apache Commons verwenden. ListOrderedMap. Es macht es so, wie es sich anhört – indem es eine Liste hat, um die Reihenfolge des Einfügens mit dem entsprechenden Index und einer normalen Karte zum Einfügen beizubehalten, wie wir es normalerweise tun. Hier ist, was die Dokumente sagen:
public class ListOrderedMap<K,V>
extends AbstractMapDecorator<K,V>
implements OrderedMap<K,V>, Serializable
Schmückt ein Map um sicherzustellen, dass die Reihenfolge des Hinzufügens beibehalten wird, indem eine Liste verwendet wird, um die Reihenfolge aufrechtzuerhalten.
Die Reihenfolge wird über die Iteratoren und verwendet toArray Methoden auf die Ansichten. Die Bestellung wird auch von der zurückgegeben MapIterator. Das orderedMapIterator() -Methode greift auf einen Iterator zu, der sowohl vorwärts als auch rückwärts durch die Karte iterieren kann. Zusätzlich werden schnittstellenfreie Verfahren bereitgestellt, um auf die Karte nach Index zuzugreifen.
Wenn ein Objekt ein zweites Mal zur Karte hinzugefügt wird, bleibt es in der Iteration an der ursprünglichen Position.
Beachten Sie, dass ListOrderedMap wird nicht synchronisiert und ist nicht Thread-sicher. Wenn Sie diese Zuordnung von mehreren Threads gleichzeitig verwenden möchten, müssen Sie eine entsprechende Synchronisierung verwenden. Der einfachste Ansatz besteht darin, diese Karte mit einzuwickeln Collections.synchronizedMap(Map). Diese Klasse kann Ausnahmen auslösen, wenn sie von gleichzeitigen Threads ohne Synchronisierung aufgerufen wird.
Beachten Sie, dass ListOrderedMap funktioniert nicht mit IdentityHashMap, CaseInsensitiveMapoder ähnliche Karten, die gegen den allgemeinen Vertrag verstoßen Map. Das ListOrderedMap (genauer gesagt der Basiswert List) stützt sich auf equals(). Das ist in Ordnung, solange das dekoriert ist Map basiert auch auf equals()und hashCode()die IdentityHashMapund CaseInsensitiveMap don’t: Erstere verwendet ==und letztere verwendet equals() auf einer Kleinbuchstabentaste.
Hier ist die Implementierung zum Hinzufügen zu einer 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 }
Tamalet
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());
}
}
Teile dich einfach LinkedHashMap auf 2 Reihen. Erstellen Sie das erste Array mit der Größe index - 1 und am Ende neu setzen Entry. Füllen Sie dann das erste Array mit Einträgen aus dem zweiten
Es ist ein Map, es hat keine Indizes. Es hat Eimer. Die Art und Weise, wie es funktioniert, ist, wenn Sie a tun
put(key, val)
Es hasht den Schlüssel, um herauszufinden, in welchen Bucket das Val gesteckt werden soll.
Das LinkedHashMap verwaltet eine doppelt verknüpfte Liste, damit sie die Reihenfolge aufzeichnen kann, in der Einträge eingefügt werden (oder auf die zugegriffen wird, je nachdem, wie Sie die Karte instanziieren). Es gibt keine Methode in der API auf der Karte, um ein Schlüssel-Wert-Paar an einem bestimmten Index der verknüpften Liste einzufügen, da dies nicht der Zweck ist, den es erfüllt.
Nauman Aejaz
...
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;
}
}
Das ist ein bisschen lang für eine so einfache Frage.
– Alexander
1. Mai 2018 um 21:32 Uhr
Einverstanden. Ich hatte das gleiche Problem und habe keinen besseren Weg gefunden.
– Nauman Aejaz
3. Mai 2018 um 4:23 Uhr
10624300cookie-checkWie füge ich ein Element an einem bestimmten Index / einer bestimmten Position in LinkedHashMap hinzu?yes
Aus den Dokumenten: „Beachten Sie, dass die Einfügungsreihenfolge nicht beeinflusst wird, wenn ein Schlüssel erneut in die Karte eingefügt wird. (Ein Schlüssel k wird erneut in eine Karte m eingefügt, wenn m.put(k, v) aufgerufen wird, wenn m.containsKey(k ) würde unmittelbar vor dem Aufruf true zurückgeben.)”
– Andreas
10. Dezember 2018 um 18:38 Uhr