Czy można pobrać element z HashMap na podstawie jego pozycji?


99

Jak pobrać element z HashMap według jego pozycji, czy to w ogóle możliwe?


11
Co masz na myśli mówiąc „stanowisko”? HashMapy nie są uporządkowane, więc nie mają zwykłego pojęcia „pozycji”, które można uzyskać za pomocą czegoś takiego jak Vector.
Mat

1
Czy masz na myśli jego kolejność reklamową czy inną kolejność?
Mark Elliot

Odpowiedzi:


94

HashMapy nie zachowują kolejności:

Ta klasa nie gwarantuje kolejności map; w szczególności nie gwarantuje, że zamówienie pozostanie niezmienne w czasie.

Spójrz na LinkedHashMap , który gwarantuje przewidywalną kolejność iteracji.


16
To naprawdę nie odpowiada na pytanie. Inne odpowiedzi poniżej są bardziej przydatne.
forresthopkinsa

6
Z całym szacunkiem cytuję dokumentację, która bezpośrednio odpowiada na pytanie
Wayne

1
Nawet jeśli kolejność nie jest stała w czasie, nadal istnieje możliwość pobrania jednego z członków na dane stanowisko.
Początkujący

Nie nadążam. Wyjaśnić?
Wayne,

Link HashMap jest uszkodzony / 404.
Raf

110

Użyj LinkedHashMap, a gdy chcesz pobrać według pozycji, przekonwertuj wartości na ArrayList.

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
Zawsze jest potrzebne do utworzenia kopii kluczy z HashMap ??
Richard

spowoduje to utworzenie nowego obiektu ArrayList za każdym razem, gdy pobieramy wartość, co prowadzi do wycieków pamięci
NullByte08

48

Jeśli chcesz zachować kolejność, w jakiej dodałeś elementy do mapy, użyj LinkedHashMapzamiast just HashMap.

Oto podejście, które pozwoli Ci uzyskać wartość na podstawie jej indeksu na mapie:

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

1
Najprościej muszę powiedzieć ... Zamiast konwertować wszystko, używasz tylko zestawu kluczy. Znakomity
kirtan403

19

Jeśli z jakiegoś powodu musisz trzymać się hashMap, możesz przekonwertować zestaw kluczy na tablicę i zindeksować klucze w tablicy, aby uzyskać wartości z mapy w następujący sposób:

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

Możesz wtedy uzyskać dostęp do mapy, na przykład:

map.get(keys[i]);

Zauważ, że arr [i] należy zmienić na: keys [i]
Mohsen Abasi

Ok, mam Strings jako klawisze mapy, żeby dostać jeden z nich, druga część to:String myKey = keys[i].toString();
Orici

12

Zastosowanie LinkedHashMap:

Implementacja tabeli skrótów i połączonych list interfejsu Map z przewidywalną kolejnością iteracji. Ta implementacja różni się od HashMap tym, że utrzymuje podwójnie połączoną listę obejmującą wszystkie jej wpisy.


27
To pozwoli zachować kolejność, ale nadal nie możesz uzyskać dostępu do elementów za pomocą ich indeksu. Musiałbyś iterować
Bozho

to łącze prowadzi do starej wersji interfejsu API. Sugerowałbym linkowanie do API Java 6 lub 7.
jzd

6

Użyj LinkedHashMap i użyj tej funkcji.

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

Zdefiniuj w ten sposób i.

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;
    }

Funkcja może zwrócić wybrany wpis.


3

Zakładam, że przez „pozycję” masz na myśli kolejność, w której wstawiłeś elementy do HashMap. W takim przypadku chcesz używać LinkedHashMap. Jednak LinkedHashMap nie oferuje metody dostępu; będziesz musiał napisać jedno polubienie

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

3

Innym działającym podejściem jest przekształcenie wartości mapy w tablicę, a następnie pobranie elementu w indeksie. Uruchomienie testowe 100 000 elementów przy wyszukiwaniu indeksu w LinkedHashMap obejmującym 100 000 obiektów przy użyciu następujących podejść doprowadziło do następujących wyników:

//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

Podsumowując, pobieranie elementu po indeksie z LinkedHashMap wydaje się być dość ciężką operacją.


2

HashMap - i podstawowa struktura danych - tabele skrótów, nie mają pojęcia pozycji. W przeciwieństwie do LinkedList lub Vector klucz wejściowy jest przekształcany w „zasobnik”, w którym przechowywana jest wartość. Te zasobniki nie są uporządkowane w sposób, który ma sens poza interfejsem HashMap i jako takie, elementy, które umieszczasz w HashMap nie są w takim sensie, jakiego można by się spodziewać po innych strukturach danych


2

HashMap nie ma pojęcia pozycji, więc nie ma możliwości uzyskania obiektu według pozycji. Obiekty w Mapach są ustawiane i pobierane za pomocą kluczy.


2

możesz użyć poniższego kodu, aby uzyskać klucz: String [] keys = (String[]) item.keySet().toArray(new String[0]);

i pobierz obiekt lub listę, która wstawia do HashMap z kluczem tego elementu: item.get(keys[position]);


2

Domyślnie java LinkedHasMap nie obsługuje pobierania wartości według pozycji. Więc proponuję wybrać dostosowaneIndexedLinkedHashMap

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);
    }
}

Następnie możesz użyć tej dostosowanej LinkedHasMap jako

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

Aby dodać wartości

indexedLinkedHashMap.add("key1",UserModel);

Aby uzyskać wartość według indeksu

indexedLinkedHashMap.getItemByIndex(position);

1

HashMaps nie zezwala na dostęp według pozycji, wie tylko o kodzie skrótu i ​​może pobrać wartość, jeśli może obliczyć kod skrótu klucza. TreeMaps ma pojęcie porządkowania. Mapy w serwisie Linkedhas zachowują kolejność, w jakiej zostały wprowadzone na mapę.


0

Możesz spróbować zaimplementować coś takiego, spójrz na:

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

Mam nadzieję, że to działa dla Ciebie.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.