Jak pobrać element z HashMap według jego pozycji, czy to w ogóle możliwe?
Jak pobrać element z HashMap według jego pozycji, czy to w ogóle możliwe?
Odpowiedzi:
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.
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);
Jeśli chcesz zachować kolejność, w jakiej dodałeś elementy do mapy, użyj LinkedHashMap
zamiast 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 ] );
}
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]);
String myKey = keys[i].toString();
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.
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.
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;
}
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ą.
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
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.
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);
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ę.
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.