É possível obter o elemento do HashMap por sua posição?


99

Como recuperar um elemento do HashMap por sua posição, isso é possível?


11
O que você quer dizer com "posição"? HashMaps não são ordenados, portanto, eles não têm a noção usual de "posição" que você obteria com algo como um vetor.
Mat,

1
Você quer dizer com seu pedido de inserção ou algum outro pedido?
Mark Elliot,

Respostas:


94

HashMaps não preservam a ordem:

Essa classe não oferece garantias quanto à ordem do mapa; em particular, não garante que o pedido permanecerá constante ao longo do tempo.

Dê uma olhada em LinkedHashMap , que garante uma ordem de iteração previsível.


16
Isso realmente não responde à pergunta. As outras respostas abaixo são mais úteis.
forresthopkinsa

6
Com todo respeito, cita documentação que responde diretamente à pergunta
Wayne

1
Mesmo que a ordem não seja constante ao longo do tempo, ainda pode ser possível recuperar um dos membros por uma determinada posição.
Principiante de

Eu não sigo. Explicar?
Wayne

O link HashMap está quebrado / 404.
Raf

109

Use um LinkedHashMap e quando precisar recuperar por posição, converta os valores em um 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
Sempre é necessário instanciar uma cópia das chaves do HashMap ??
Richard

isso criará um novo objeto ArrayList toda vez que recuperarmos o valor, levando a vazamentos de memória
NullByte08

48

Se você deseja manter a ordem em que adicionou os elementos ao mapa, use LinkedHashMapem vez de apenas HashMap.

Aqui está uma abordagem que permitirá que você obtenha um valor por seu índice no mapa:

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

1
Mais simples, devo dizer ... Em vez de converter tudo, você está usando apenas o conjunto de chaves. Excelente
kirtan403

19

Se você, por algum motivo, tiver que ficar com o hashMap, poderá converter o keySet em uma matriz e indexar as chaves na matriz para obter os valores no mapa da seguinte maneira:

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

Você pode acessar o mapa como:

map.get(keys[i]);

Observe que arr [i] deve ser alterado para: keys [i]
Mohsen Abasi

Ok, eu tenho Strings como chaves do mapa, para pegar uma delas, a segunda parte será:String myKey = keys[i].toString();
Orici

12

Use LinkedHashMap:

Implementação de tabela de hash e lista vinculada da interface Map, com ordem de iteração previsível. Essa implementação difere do HashMap porque mantém uma lista duplamente vinculada em todas as suas entradas.


27
isso preservará o pedido, mas você ainda não pode acessar os itens por seu índice. Você teria que iterar
Bozho,

este link é para uma versão antiga da API. Eu sugeriria um link para uma API Java 6 ou 7.
jzd

6

Use LinkedHashMap e use esta função.

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

Defina assim e.

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

A função pode retornar a entrada selecionada.


3

Estou supondo que por 'posição' você está se referindo à ordem em que inseriu os elementos no HashMap. Nesse caso, você deseja usar um LinkedHashMap. O LinkedHashMap não oferece um método de acessador; você precisará escrever um like

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

3

Outra abordagem de trabalho é transformar os valores do mapa em uma matriz e, em seguida, recuperar o elemento no índice. A execução de teste de 100.000 elementos por pesquisas de índice em LinkedHashMap de 100.000 objetos usando as seguintes abordagens levou aos seguintes resultados:

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

Resumindo, recuperar elemento por índice de LinkedHashMap parece ser uma operação bastante pesada.


2

HashMap - e a estrutura de dados subjacente - tabelas de hash, não têm uma noção de posição. Ao contrário de LinkedList ou Vector, a chave de entrada é transformada em um 'balde' onde o valor é armazenado. Esses depósitos não são ordenados de uma forma que faça sentido fora da interface HashMap e, como tal, os itens que você coloca no HashMap não estão em ordem no sentido que você esperaria com outras estruturas de dados


2

O HashMap não tem conceito de posição, portanto, não há como obter um objeto por posição. Os objetos no Maps são definidos e obtidos por teclas.


2

você pode usar o código abaixo para obter a chave: String [] keys = (String[]) item.keySet().toArray(new String[0]);

e obter o objeto ou lista que se insere no HashMap com a chave deste item assim: item.get(keys[position]);


2

Por padrão, java LinkedHasMap não suporta a obtenção de valor por posição. Então, eu sugiro ir com personalizadoIndexedLinkedHashMap

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

Então você pode usar este LinkedHasMap personalizado como

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

PARA adicionar valores

indexedLinkedHashMap.add("key1",UserModel);

Para obter o valor por índice

indexedLinkedHashMap.getItemByIndex(position);

1

HashMaps não permitem acesso por posição, ele só conhece o código hash e pode recuperar o valor se puder calcular o código hash da chave. TreeMaps tem uma noção de ordenação. Os mapas do Linkedhas preservam a ordem em que entraram no mapa.


0

Você pode tentar implementar algo assim, observe:

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

Espero que isso funcione pra você.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.