Коллекция с доступом как по порядку, так и по ключевому поиску

Что мне нужно, так это неупорядоченная коллекция по умолчанию, поддерживаемая массивом или массивом, который позволяет выполнять поиск по ключу. Или ассоциативная карта, по которой можно путешествовать по времени вставки.

Дело в следующем, у меня есть адаптер, который перемещается по коллекции через позицию, а вставка — это как список, но при этом хотелось бы менять отдельные элементы, находя их по ключу, а не перебирать весь список.

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


person MLProgrammer-CiM    schedule 06.02.2015    source источник


Ответы (4)


Лучше всего подойдет LinkedHashMap.

Он работает как HashMap, у которого есть двусвязный список, проходящий через его элементы Map.Entry. Вы можете использовать список для итерации, и, будучи HashMap, он даст вам поиск O (1).

Вы можете выбрать порядок вставки или порядок доступа.

person aa333    schedule 06.02.2015
comment
Как мне получить запись в позиции 5, не перебирая ключи? - person MLProgrammer-CiM; 06.02.2015
comment
Мне, вероятно, нужно переформатировать вопрос, я использую ArrayMap, который дает мне indexOfKey и keyAt, но не поддерживает порядок вставки. - person MLProgrammer-CiM; 06.02.2015
comment
Итак, вы хотите, чтобы произвольный доступ по порядковому номеру, а также O (1) искал какой-то указанный непорядковый ключ? - person robert_difalco; 06.02.2015
comment
Я знаю, что мне нужно много спросить, поэтому я ничего не нашел в документе сам. - person MLProgrammer-CiM; 06.02.2015
comment
Существует реализация ArrayMap, которая поддерживает упорядочение, но она связана с другими классами libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/ - person MLProgrammer-CiM; 06.02.2015
comment
Вызов get ArrayMap равен O(n), FWIW. - person Louis Wasserman; 06.02.2015
comment
Я не могу придумать другого способа разрешить индексированный доступ, кроме как расширить LinkedHashMap, чтобы иметь резервную карту с индексом в качестве ключей. Не знаю, существует ли такая DS в какой-нибудь библиотеке. Но попробую найти или на скорую руку реализовать. - person aa333; 06.02.2015
comment
@ aa333 это то, что я искал, просто не реализовывал это сам, потому что я уже был на этом пути раньше. См. тот, который у меня есть выше от LibGDX. Они также заказали карту. - person MLProgrammer-CiM; 06.02.2015
comment
Я связал ниже ImmutableMap, который поддерживает все упомянутые вами операции, но не поддерживает добавление или удаление записей. - person Louis Wasserman; 06.02.2015
comment
К сожалению, это изменяемый список. - person MLProgrammer-CiM; 06.02.2015

LinkedHashMap даст вам близко к O (1) с порядком размещения

person jmj    schedule 06.02.2015

Если вам нужен индексированный поиск O (1), а также поиск O (1) по ключу, вы можете сделать это, если вам не нужно помещать новые записи в карту, только создавая карту один раз (хотя, возможно, изменяя записи в карту) с Гуава ImmutableMap, который также сохраняет порядок вставки. Как и обычный Map, вы можете выполнять поиск по ключу, а также можете выполнять map.values().asList().get(i), который извлекает элемент за постоянное время. Однако я не верю, что в JDK есть что-то, что делает и то, и другое.

person Louis Wasserman    schedule 06.02.2015

Основываясь на комментарии @aa333, я сделал свою собственную реализацию, возможно, она неполная, поэтому предложения приветствуются.

https://gist.github.com/anonymous/7a93535a3cfb63623a54

Он проходит эти тестовые случаи Q & D:

public static void main(String[] args) {
    Map<String, String> preMap = new HashMap<String, String>();
    preMap.put("subZero", "-1");
    preMap.put("zero", "0");
    IterableLinkedMap<String, String> map = new IterableLinkedMap<String, String>();
    map.putAll(preMap);
    map.put("one", "1");
    map.put("two", "2");
    map.put("three", "3");
    map.put("four", "4");
    map.put("five", "5");
    map.put("six", "6");
    map.remove("three");
    map.put("eight", "8");
    map.put("seven", "7");
    map.remove("one");
    map.put("three", "33");
    map.put("five", "actually five");
    for (int i = 0; i < map.size(); i++){
        System.out.println(map.getPosition(i));
    }
    map.clear();
    System.out.println(map.getPosition(0));
}

Полученные результаты:

0
-1
2
4
actually five
6
8
7
33
null
person MLProgrammer-CiM    schedule 07.02.2015
comment
Это была отправная точка, но требовалось больше вещей, чтобы заставить его работать в O (1) для вставки и поиска как позиции, так и ключа. Стоимость удаления составляет O (n), что является небольшой ценой для ИМО. - person MLProgrammer-CiM; 09.02.2015