Можно ли получить элемент из HashMap по его позиции?

99

Как получить элемент из HashMap по его позиции, возможно ли это вообще?

Евгений
источник
11
Что вы подразумеваете под «положением»? HashMaps не упорядочены, поэтому у них нет обычного понятия «позиция», которое вы получили бы с чем-то вроде вектора.
Mat
1
Вы имеете в виду его порядок размещения или какой-то другой порядок?
Марк Эллиот

Ответы:

94

HashMaps не сохраняют порядок:

Этот класс не дает никаких гарантий относительно порядка карты; в частности, это не гарантирует, что порядок останется постоянным с течением времени.

Взгляните на LinkedHashMap , который гарантирует предсказуемый порядок итераций.

Уэйн
источник
16
Это не совсем ответ на вопрос. Другие ответы ниже более полезны.
forresthopkinsa
6
С уважением, здесь цитируется документация, которая прямо отвечает на вопрос
Уэйн
1
Даже если порядок не является постоянным с течением времени, все равно можно получить один из членов по заданной позиции.
Новичок
Я не слежу. Объясните?
Уэйн
Ссылка HashMap не работает / 404.
Raf
111

Используйте LinkedHashMap, и когда вам нужно получить по позиции, преобразуйте значения в 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
Всегда необходимо создавать копию ключей из HashMap ??
Ричард
это будет создавать новый объект ArrayList каждый раз, когда мы получаем значение, что приводит к утечке памяти
NullByte08
48

Если вы хотите сохранить порядок, в котором вы добавляли элементы на карту, используйте LinkedHashMapвместо просто HashMap.

Вот подход, который позволит вам получить значение по его индексу на карте:

public Object getElementByIndex(LinkedHashMap map,int index){
    return map.get( (map.keySet().toArray())[ index ] );
}
Сид Ламберт
источник
1
Самое простое, я должен сказать ... Вместо того, чтобы конвертировать все, вы используете только набор ключей. Superb
kirtan403
19

Если вам по какой-то причине необходимо придерживаться hashMap, вы можете преобразовать keySet в массив и проиндексировать ключи в массиве, чтобы получить значения на карте следующим образом:

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

Затем вы можете получить доступ к карте, например:

map.get(keys[i]);
theNoble247
источник
Обратите внимание, что arr [i] следует изменить на: keys [i]
Mohsen Abasi
Хорошо, у меня есть Strings в качестве ключей карты, чтобы получить один из них, вторая часть будет:String myKey = keys[i].toString();
Orici
12

Использование LinkedHashMap:

Реализация хэш-таблицы и связанного списка интерфейса Map с предсказуемым порядком итераций. Эта реализация отличается от HashMap тем, что поддерживает двусвязный список, проходящий через все его записи.

илалекс
источник
27
это сохранит порядок, но вы по-прежнему не сможете получить доступ к элементам по их индексу. Придется повторить
Божо
эта ссылка ведет к старой версии API. Я бы предложил ссылку на API Java 6 или 7.
jzd 08
6

Используйте LinkedHashMap и используйте эту функцию.

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

Определите вот так и.

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

Функция может вернуть выбранную запись.

Джефф Ли
источник
3

Я предполагаю, что под «позицией» вы имеете в виду порядок, в котором вы вставили элементы в HashMap. В этом случае вы хотите использовать LinkedHashMap. Однако LinkedHashMap не предлагает метода доступа; вам нужно будет написать что-то вроде

public Object getElementAt(LinkedHashMap map, int index) {
    for (Map.Entry entry : map.entrySet()) {
        if (index-- == 0) {
            return entry.value();
        }
    }
    return null;
}
домашнее пиво
источник
3

Другой рабочий подход - преобразование значений карты в массив с последующим извлечением элемента по индексу. Тестовый запуск 100 000 элементов путем поиска по индексу в LinkedHashMap 100 000 объектов с использованием следующих подходов привел к следующим результатам:

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

В целом получение элемента по индексу из LinkedHashMap кажется довольно сложной операцией.

user3738243
источник
2

HashMap - и лежащая в основе структура данных - хеш-таблицы не имеют понятия позиции. В отличие от LinkedList или Vector, ключ ввода преобразуется в «корзину», в которой сохраняется значение. Эти корзины не упорядочены таким образом, который имеет смысл за пределами интерфейса HashMap, и поэтому элементы, которые вы помещаете в HashMap, не упорядочены в том смысле, который вы ожидали бы с другими структурами данных.

dfb
источник
2

HashMap не имеет понятия позиции, поэтому нет возможности получить объект по позиции. Объекты в Картах устанавливаются и достаются ключами.

Робби Пруд
источник
2

вы можете использовать приведенный ниже код, чтобы получить ключ: String [] keys = (String[]) item.keySet().toArray(new String[0]);

и получить объект или список, которые вставляются в HashMap с ключом этого элемента, например: item.get(keys[position]);

маха к
источник
2

По умолчанию java LinkedHasMap не поддерживает получение значения по позиции. Поэтому я предлагаю использовать индивидуальныеIndexedLinkedHashMap

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

Затем вы можете использовать эту настроенную LinkedHasMap как

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

ЧТОБЫ добавить значения

indexedLinkedHashMap.add("key1",UserModel);

Получить значение по индексу

indexedLinkedHashMap.getItemByIndex(position);
Викрам Кодаг
источник
1

HashMaps не разрешает доступ по позиции, он знает только о хэш-коде и может получить значение, если он может вычислить хеш-код ключа. В TreeMaps есть понятие упорядочивания. Карты Linkedhas сохраняют порядок, в котором они были введены на карту.

fastcodejava
источник
0

Можно попробовать реализовать что-то подобное, посмотрите:

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

Надеюсь, это сработает для вас.

Франсиско Хавьер Окампо
источник