wake-up-neo.com

wie man den einen Eintrag von Hashmap erhält, ohne zu iterieren

Gibt es eine elegante Möglichkeit, nur einen Entry<K,V> von HashMap zu erhalten, ohne zu iterieren, wenn der Schlüssel nicht bekannt ist.

Da die Reihenfolge der Eintragung nicht wichtig ist, können wir etwas sagen

hashMapObject.get(zeroth_index);

Obwohl mir bewusst ist, dass es keine solche "get by index" -Methode gibt.

Wenn ich versucht habe, die unten erwähnte Vorgehensweise zu verwenden, müsste es immer noch den gesamten Eintragssatz der Hashmap erhalten.

for(Map.Entry<String, String> entry : MapObj.entrySet()) {
    return entry;
}

Vorschläge sind willkommen.

BEARBEITEN: Bitte schlagen Sie eine andere Datenstruktur vor, um die Anforderungen zu erfüllen.

153
nilesh

Die Antwort von Jesper ist gut. Eine andere Lösung ist die Verwendung von TreeMap (Sie haben nach anderen Datenstrukturen gefragt).

TreeMap<String, String> myMap = new TreeMap<String, String>();
String first = myMap.firstEntry().getValue();
String firstOther = myMap.get(myMap.firstKey());

TreeMap hat einen Overhead, daher ist HashMap schneller, aber nur als Beispiel für eine alternative Lösung.

89
Per Östlund

Karten sind nicht geordnet, es gibt also nicht den ersten Eintrag. Deshalb gibt es auch keine get-by-index-Methode für Map (oder HashMap).

Sie könnten das tun:

Map<String, String> map = ...;  // wherever you get this from

// Get the first entry that the iterator returns
Map.Entry<String, String> entry = map.entrySet().iterator().next();

(Hinweis: Überprüfung auf leere Karte wurde weggelassen).

Ihr Code erhält nicht alle Einträge in der Map, er wird sofort mit dem ersten gefundenen Eintrag zurückgegeben (und verlässt die Schleife).

So drucken Sie den Schlüssel und den Wert dieses ersten Elements:

System.out.println("Key: "+entry.getKey()+", Value: "+entry.getValue());

Hinweis: Der Aufruf von iterator() bedeutet nicht, dass Sie die gesamte Map durchlaufen.

237
Jesper

Der Iterator könnte die einfachste Lösung sein.

return hashMapObject.entrySet().iterator().next();

Eine andere Lösung (nicht hübsch):

return new ArrayList(hashMapObject.entrySet()).get(0);

Oder doch (nicht besser):

return hashMapObject.entrySet().toArray()[0];
28
cadrian

Werte abrufen, in ein Array umwandeln, erstes Element des Arrays abrufen:

map.values().toArray()[0]

W.

13
Wiktor Misiek

Warum möchten Sie den Aufruf von entrySet() vermeiden, erstellt not im Allgemeinen ein völlig neues Objekt mit seinem eigenen Kontext, sondern stellt nur ein Fassadenobjekt bereit. Einfach gesagt, entrySet() ist eine ziemlich billige Operation.

8
Joachim Sauer

Wenn Sie Java 8 verwenden, ist es so einfach wie findFirst () :

Schnelles Beispiel:

Optional<Car> theCarFoundOpt = carMap.values().stream().findFirst();

if(theCarFoundOpt.isPresent()) {
    return theCarFoundOpt.get().startEngine();
}
6
Cacho Santa

Wenn Sie die von Ihnen vorgeschlagene API wirklich wollen, können Sie HashMap subclassen und beispielsweise die Schlüssel in einer Liste verfolgen. Sehen Sie den Sinn nicht wirklich, aber es gibt Ihnen, was Sie wollen. Wenn Sie den beabsichtigten Anwendungsfall erläutern, können wir vielleicht eine bessere Lösung finden.

import Java.util.ArrayList;
import Java.util.HashMap;
import Java.util.List;
import Java.util.Map;

@SuppressWarnings("unchecked")
public class IndexedMap extends HashMap {

    private List<Object> keyIndex;

    public IndexedMap() {
        keyIndex = new ArrayList<Object>();
    }

    /**
     * Returns the key at the specified position in this Map's keyIndex.
     * 
     * @param index
     *            index of the element to return
     * @return the element at the specified position in this list
     * @throws IndexOutOfBoundsException
     *             if the index is out of range (index < 0 || index >= size())
     */
    public Object get(int index) {
        return keyIndex.get(index);
    }

    @Override
    public Object put(Object key, Object value) {

        addKeyToIndex(key);
        return super.put(key, value);
    }

    @Override
    public void putAll(Map source) {

        for (Object key : source.keySet()) {
            addKeyToIndex(key);
        }
        super.putAll(source);
    }

    private void addKeyToIndex(Object key) {

        if (!keyIndex.contains(key)) {
            keyIndex.add(key);
        }
    }

    @Override
    public Object remove(Object key) {

        keyIndex.remove(key);
        return super.remove(key);
    }
}

EDIT: Ich habe mich bewusst nicht mit der generischen Seite befasst ...

6
Adriaan Koster

Was meinst du mit "ohne zu iterieren"?

Sie können map.entrySet().iterator().next() verwenden, und Sie würden nicht durch die Map durchlaufen (im Sinne von "jedes Objekt berühren"). Sie können einen Entry<K, V> nicht erhalten, ohne einen Iterator zu verwenden. Der Javadoc von Map.Entry sagt:

Die Map.entrySet-Methode gibt eine .__ zurück. Sammlungsansicht der Karte, deren Elemente sind von dieser Klasse. Das einzige So erhalten Sie einen Verweis auf eine Karte Eintrag stammt vom Iterator dieses Sammlungsansicht. Diese Map.Entry Objekte sind nur für die .__ gültig. Dauer der Iteration.

Können Sie uns näher erläutern, was Sie erreichen wollen? Wenn Sie zuerst Objekte behandeln möchten, die einem bestimmten Kriterium entsprechen (z. B. "einen bestimmten Schlüssel haben") und auf die übrigen Objekte zurückgreifen, sehen Sie sich eine PriorityQueue an. Es ordnet Ihre Objekte auf der Grundlage einer natürlichen Reihenfolge oder einer benutzerdefinierten Comparator an, die Sie angeben.

4
janko
import Java.util.*;

public class Friday {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<String, Integer>();

        map.put("code", 10);
        map.put("to", 11);
        map.put("joy", 12);

        if (! map.isEmpty()) {
            Map.Entry<String, Integer> entry = map.entrySet().iterator().next();
            System.out.println(entry);
        }
    }
}

Dieser Ansatz funktioniert nicht, da Sie HashMap verwendet haben. Ich gehe davon aus, dass die Verwendung von LinkedHashMap in diesem Fall die richtige Lösung ist.

4
dmgcodevil

Dies würde einen einzelnen Eintrag von der Karte erhalten, der ungefähr so ​​nah wie möglich ist, wenn "first" nicht wirklich zutrifft.

import Java.util.*;

public class Friday {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<String, Integer>();

        map.put("code", 10);
        map.put("to", 11);
        map.put("joy", 12);

        if (! map.isEmpty()) {
            Map.Entry<String, Integer> entry = map.entrySet().iterator().next();
            System.out.println(entry);
        }
    }
}
3
Michael Easter

Gestolpert hier auf der Suche nach dem gleichen ... Ich erinnerte mich dann an die Iterables-Klasse aus der Guava-Bibliothek .

So erhalten Sie das "erste" Element: Iterables.getFirst( someMap.values(), null );
Entspricht im Wesentlichen dem von Map.values().iterator().next(), ermöglicht aber auch die Angabe eines Standardwerts (in diesem Fall null), falls sich in der Map nichts befindet.

Iterables.getLast( someMap.values(), null ); gibt das letzte Element in der Map zurück.

Iterables.get( someMap.values(), 7, null ); gibt das 7. Element in der Map zurück, falls vorhanden, andernfalls einen Standardwert (in diesem Fall null).

Denken Sie daran, dass HashMaps nicht geordnet sind. Erwarten Sie also nicht, dass Iterables.getFirst den ersten Artikel zurückgibt, den Sie dort hineingeworfen haben ... ebenfalls mit Iterables.getLast. Vielleicht nützlich zu bekommen ein kartierter Wert.

Es ist vielleicht nicht wert, die Guava-Bibliothek für genau das hinzuzufügen, aber wenn Sie zufällig einige der anderen coolen Dienstprogramme in dieser Bibliothek verwenden ...

2
SquidRott

Nach Ihrem BEITRAG folgt hier mein Vorschlag:

Wenn Sie nur einen Eintrag haben, können Sie die Map durch ein duales Objekt ersetzen. Abhängig von den Typen und Ihren Präferenzen:

  • ein Array (aus 2 Werten, Schlüssel und Wert)
  • ein einfaches Objekt mit zwei Eigenschaften
1
KLE
map<string,string>m;
auto it=m.begin();//get iterator to the first element of map(m)
return m->first;//return first string(1st string in map<string,string>m)
//Incase you want the second string 
//you can use return m->second(2st string in map<string,string>m)
//if you want to iterate the whole map you can use loop
for(auto it:m)//m is a map
   cout<<it->first<<endl;
0
Vipul Vikram