Подтвердить что ты не робот

Как получить позицию ключа/значения в LinkedHashMap, используя его ключ

Привет У меня есть LinkedHashMap (называемый info), который содержит пары name/age (string/int). Я хочу узнать, как я могу получить позицию ключа/значения, если я введу ключ. Например, если мой LinkedHashMap выглядел так: {bob = 12, jeremy = 42, carly = 21}, и я должен был искать jeremy, он должен был бы вернуть 1 как это в позиции 1. Я надеялся, что смогу использовать что-то вроде info.getIndex( "Jeremy" )

4b9b3361

Ответ 1

HashMap реализации вообще не упорядочены для Iteration.

LinkedHashMap предсказуемо упорядочен для Iteration (порядок вставки), но не предоставляет интерфейс List и LinkedList (который является тем, что отражает порядок вставки набора ключей) не отслеживать позицию индекса, либо очень эффективно найти индекс. LinkedHashMap не выводит ссылку на внутренний LinkedList.

Фактическое поведение "Связанный список" является специфичным для реализации. Некоторые может фактически использовать экземпляр LinkedList, некоторые из которых просто имеют Entry отслеживать предыдущий и следующий Entry и использовать это как его реализация. Не предполагайте ничего, не глядя на источник.

KeySet, который содержит ключи, также не гарантирует порядок из-за алгоритмов хеширования, используемых для размещения в структуре данных резервного копирования наследуемого HashMap. Поэтому вы не можете использовать это.

Единственный способ сделать это, не записывая собственную реализацию, - это пройти Iterator, который использует зеркалирование LinkedList и сохранить счет, где вы находитесь, это будет очень неэффективно с большими наборами данных.

Решение

Похоже, что вам нужно исходные позиции индекса размещения вставки, вам придется зеркально отображать ключи в KeySet в виде ArrayList, синхронизировать его с обновлениями HashMap и использовать его для нахождения позиции. Создание подкласса HashMap, скажем IndexedHashMap и добавление этого ArrayList внутри, и добавление .getKeyIndex(<K> key), который делегирует внутреннему ArrayList .indexOf(), вероятно, лучший способ обойти это.

Это то, что LinkedHashMap делает, но с LinkedList зеркальным отображением KeySet вместо ArrayList.

Ответ 2

int pos = new ArrayList<String>(info.keySet()).indexOf("jeremy")

Ответ 3

LinkedHashMap имеет "предсказуемый порядок итерации" (javadoc). Элементы не знают своего местоположения, поэтому вам придется перебирать коллекцию, чтобы получить ее. Если вы поддерживаете большую карту, вы можете использовать другую структуру для хранения.

Изменить: уточненная итерация

Ответ 4

Вы можете использовать com.google.common.collect.LinkedListMultimap из библиотеки Google Guava. Вам не нужно многомарочное поведение этого класса, что вы хотите, так это то, что метод keys() гарантирует, что они будут возвращены в порядке вставки, и затем их можно использовать для построения списка, вы можете использовать indexOf() для поиска нужного индекса положение

Ответ 5

Я видел предложение от одного из дубликатов этого вопроса на

Как получить значение из LinkedHashMap на основе индекса, а не ключа?

и мне понравилось предложение, описанное как псевдокод от @schippi в комментариях. Я думал, что некоторые работающие Java-коды могут быть полезны для других при таком подходе

import java.util.ArrayList;
import java.util.LinkedHashMap;

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

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    ArrayList<K> al_Index = new ArrayList<K>();

    @Override
    public V put(K key,V val) {
        if (!super.containsKey(key)) al_Index.add(key);
        V returnValue = super.put(key,val);
        return returnValue;
    }

    public V getValueAtIndex(int i){
        return (V) super.get(al_Index.get(i));
    }

    public K getKeyAtIndex(int i) {
        return (K) al_Index.get(i);
    }

    public int getIndexOf(K key) {
        return al_Index.indexOf(key);
    }

}