Итерации, чтобы найти запись в карте по индексу?

У меня есть LinkedHashMap. Я хочу получить Foo в индексе N. Есть ли лучший способ сделать это, кроме повторения, пока я не найду?:

int target = N;
int index = 0;
for (Map.Entry<String, Foo> it : foos.entrySet()) {
    if (index == target) {
        return it.getValue();
    }
    index++;
}

Мне нужно сделать случайные элементы с карты индексом около 50 раз для некоторой операции. Карта будет содержать около 20 элементов.

Спасибо

Ответ 1

List<Entry<String,Foo>> randAccess = new ArrayList<Entry<String,Foo>>(foos.entrySet());

Затем для индекса N с доступом O (1)...

randAccess.get(N)

Ответ 2

Решение @Mark находится на месте. Я просто хотел бы указать, что смещения (позиции) записей на карте (любого вида) нестабильны. Каждый раз, когда запись добавляется или удаляется, смещения остальных записей могут меняться. Для HashMap или LinkedHashMap вы не знаете, какие изменения смещения будут изменены.

  • Для обычного HashMap одна вставка может, по-видимому, "рандомизировать" смещения входа.
  • Для LinkedHashMap порядок записей стабилен, фактические смещения входа не являются.

Нестабильность смещений и тот факт, что поиск записи при заданном смещении является дорогостоящим для всех стандартных реализаций карт, являются причинами, по которым интерфейс Map не предоставляет метод get(int offset). Также должно быть намеком на то, что алгоритм не является хорошей идеей для этого.

Ответ 3

Упрощение решения @Mark... Вам нужны только значения, поэтому каждый раз, когда вы изменяете значение на карте foos, также обновляете массив.

Map<String, Foo> foos =;
Foo[] fooValues = {};

foos.put(foos.name(), foo);
fooValues = foos.values().toArray(new Foo[foos.size()]);

// later
Foo foo = fooValues[N];

Ответ 4

Библиотека Guava может помочь в этом случае:

public static <T> T com.google.common.collect.Iterables.get(Iterable<T> iterable, int position)

см. javadoc: Iterables.get

В вашем случае код может быть таким:

Iterables.get(foos.values(), N);