Ist es möglich, ein Element anhand seiner Position aus HashMap abzurufen?


98

Wie kann man ein Element anhand seiner Position aus HashMap abrufen? Ist das überhaupt möglich?


11
Was meinst du mit "Position"? HashMaps werden nicht bestellt, daher haben sie nicht die übliche Vorstellung von "Position", die Sie mit so etwas wie einem Vektor erhalten würden.
Mat

1
Meinen Sie damit die Einfügereihenfolge oder eine andere Reihenfolge?
Mark Elliot

Antworten:


93

HashMaps behält die Reihenfolge nicht bei:

Diese Klasse übernimmt keine Garantie für die Reihenfolge der Karte. Insbesondere kann nicht garantiert werden, dass die Bestellung über die Zeit konstant bleibt.

Schauen Sie sich LinkedHashMap an , das eine vorhersehbare Iterationsreihenfolge garantiert.


16
Dies beantwortet die Frage nicht wirklich. Die anderen Antworten unten sind nützlicher.
Forresthopkinsa

6
In Bezug auf diese zitiert Dokumentation, die die Frage direkt beantwortet
Wayne

1
Selbst wenn die Reihenfolge über die Zeit nicht konstant ist, kann es dennoch möglich sein, eines der Mitglieder an einer bestimmten Position abzurufen.
Anfänger

Ich folge nicht. Erklären?
Wayne

Die HashMap-Verbindung ist unterbrochen / 404.
Raf

109

Verwenden Sie eine LinkedHashMap und konvertieren Sie die Werte in eine ArrayList, wenn Sie sie nach Position abrufen müssen.

LinkedHashMap<String,String> linkedHashMap = new LinkedHashMap<String,String>();
/* Populate */
linkedHashMap.put("key0","value0");
linkedHashMap.put("key1","value1");
linkedHashMap.put("key2","value2");
/* Get by position */
int pos = 1;
String value = (new ArrayList<String>(linkedHashMap.values())).get(pos);

2
Wird immer benötigt, um eine Kopie der Schlüssel von HashMap zu instanziieren?
Richard

Dadurch wird jedes Mal, wenn wir einen Wert abrufen, ein neues ArrayList-Objekt erstellt, was zu Speicherlecks führt
NullByte08

48

Wenn Sie die Reihenfolge beibehalten möchten, in der Sie die Elemente zur Karte hinzugefügt haben, verwenden Sie LinkedHashMapim Gegensatz zu nur HashMap.

Hier ist ein Ansatz, mit dem Sie einen Wert anhand seines Index in der Karte ermitteln können:

public Object getElementByIndex(LinkedHashMap map,int index){
    return map.get( (map.keySet().toArray())[ index ] );
}

1
Am einfachsten muss ich sagen ... Anstatt alles zu konvertieren, verwenden Sie nur das Keyset. Superb
kirtan403

19

Wenn Sie sich aus irgendeinem Grund an die HashMap halten müssen, können Sie das keySet in ein Array konvertieren und die Schlüssel im Array indizieren, um die Werte in der Map wie folgt zu erhalten:

Object[] keys = map.keySet().toArray();

Sie können dann wie folgt auf die Karte zugreifen:

map.get(keys[i]);

Beachten Sie, dass arr [i] geändert werden sollte in: keys [i]
Mohsen Abasi

Ok, ich habe Strings als Kartenschlüssel, um einen davon zu bekommen, wird der zweite Teil sein:String myKey = keys[i].toString();
Orici

12

Verwendung LinkedHashMap:

Implementierung der Hash-Tabelle und der verknüpften Liste der Map-Schnittstelle mit vorhersagbarer Iterationsreihenfolge. Diese Implementierung unterscheidet sich von HashMap dadurch, dass eine doppelt verknüpfte Liste geführt wird, die alle Einträge durchläuft.


27
Dadurch bleibt die Reihenfolge erhalten, aber Sie können immer noch nicht über den Index auf Elemente zugreifen. Sie
müssten

Dieser Link verweist auf eine alte Version der API. Ich würde vorschlagen, auf eine Java 6 oder 7 API zu verlinken.
jzd

6

Verwenden Sie LinkedHashMap und verwenden Sie diese Funktion.

private LinkedHashMap<Integer, String> map = new LinkedHashMap<Integer, String>();

Definieren Sie so und.

private Entry getEntry(int id){
        Iterator iterator = map.entrySet().iterator();
        int n = 0;
        while(iterator.hasNext()){
            Entry entry = (Entry) iterator.next();
            if(n == id){
                return entry;
            }
            n ++;
        }
        return null;
    }

Die Funktion kann den ausgewählten Eintrag zurückgeben.


3

Ich gehe davon aus, dass Sie sich mit 'Position' auf die Reihenfolge beziehen, in der Sie die Elemente in die HashMap eingefügt haben. In diesem Fall möchten Sie eine LinkedHashMap verwenden. Die LinkedHashMap bietet jedoch keine Zugriffsmethode. Sie müssen eine wie schreiben

public Object getElementAt(LinkedHashMap map, int index) {
    for (Map.Entry entry : map.entrySet()) {
        if (index-- == 0) {
            return entry.value();
        }
    }
    return null;
}

3

Ein anderer Arbeitsansatz besteht darin, Kartenwerte in ein Array umzuwandeln und dann das Element am Index abzurufen. Der Testlauf von 100 000 Elementen durch Indexsuche in LinkedHashMap von 100 000 Objekten unter Verwendung der folgenden Ansätze führte zu folgenden Ergebnissen:

//My answer:
public Particle getElementByIndex(LinkedHashMap<Point, Particle> map,int index){
    return map.values().toArray(new Particle[map.values().size()])[index];
} //68 965 ms

//Syd Lambert's answer:
public Particle getElementByIndex(LinkedHashMap<Point, Particle> map,int index){
    return map.get( (map.keySet().toArray())[ index ] );
} //80 700 ms

Alles in allem scheint das Abrufen von Elementen per Index aus LinkedHashMap eine ziemlich schwere Operation zu sein.


2

HashMap - und die zugrunde liegende Datenstruktur - Hash-Tabellen haben keine Vorstellung von Position. Im Gegensatz zu einer LinkedList oder einem Vektor wird der Eingabeschlüssel in einen 'Bucket' umgewandelt, in dem der Wert gespeichert wird. Diese Buckets sind nicht in einer Weise angeordnet, die außerhalb der HashMap-Schnittstelle sinnvoll ist. Daher sind die Elemente, die Sie in die HashMap einfügen, nicht in dem Sinne angeordnet, wie Sie es von den anderen Datenstrukturen erwarten würden


2

HashMap hat kein Positionskonzept, daher gibt es keine Möglichkeit, ein Objekt nach Position zu ermitteln. Objekte in Karten werden gesetzt und über Schlüssel abgerufen.


2

Sie können den folgenden Code verwenden, um den Schlüssel zu erhalten: String [] keys = (String[]) item.keySet().toArray(new String[0]);

und erhalten Sie ein Objekt oder eine Liste, die mit dem Schlüssel dieses Elements wie folgt in HashMap eingefügt werden: item.get(keys[position]);


2

Standardmäßig unterstützt Java LinkedHasMap das Abrufen von Werten nach Position nicht. Also schlage ich vor, mit maßgeschneiderten zu gehenIndexedLinkedHashMap

public class IndexedLinkedHashMap<K, V> extends LinkedHashMap<K, V> {

    private ArrayList<K> keysList = new ArrayList<>();

    public void add(K key, V val) {
        super.put(key, val);
        keysList.add(key);
    }

    public void update(K key, V val) {
        super.put(key, val);
    }

    public void removeItemByKey(K key) {
        super.remove(key);
        keysList.remove(key);
    }

    public void removeItemByIndex(int index) {
        super.remove(keysList.get(index));
        keysList.remove(index);
    }

    public V getItemByIndex(int i) {
        return (V) super.get(keysList.get(i));
    }

    public int getIndexByKey(K key) {
        return keysList.indexOf(key);
    }
}

Dann können Sie diese angepasste LinkedHasMap als verwenden

IndexedLinkedHashMap<String,UserModel> indexedLinkedHashMap=new IndexedLinkedHashMap<>();

Werte hinzufügen

indexedLinkedHashMap.add("key1",UserModel);

Um den Wert nach Index zu erhalten

indexedLinkedHashMap.getItemByIndex(position);

1

HashMaps erlauben keinen Zugriff nach Position, kennen nur den Hash-Code und können den Wert abrufen, wenn sie den Hash-Code des Schlüssels berechnen können. TreeMaps haben einen Begriff der Bestellung. Linkedhas-Karten behalten die Reihenfolge bei, in der sie in die Karte eingegeben wurden.


0

Sie können versuchen, so etwas zu implementieren. Schauen Sie sich Folgendes an:

Map<String, Integer> map = new LinkedHashMap<String, Integer>();
map.put("juan", 2);
map.put("pedro", 3);
map.put("pablo", 5);
map.put("iphoncio",9)

List<String> indexes = new ArrayList<String>(map.keySet()); // <== Parse

System.out.println(indexes.indexOf("juan"));     // ==> 0
System.out.println(indexes.indexOf("iphoncio"));      // ==> 3

Ich hoffe das funktioniert bei dir.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.