Как мне разобрать карту (foreach) в том же порядке, в котором я ее создал (JAVA) - PullRequest
6 голосов
/ 23 мая 2010

Итак, у меня есть карта, которую я создал (вставил данные) в нужном мне порядке. При разборе карты 1-й ключ, возвращенный в foreach, не является первым ключом, который я вставил. Есть ли способ для этого?

Кроме того, сортировать мою карту довольно сложно, потому что она должна быть отсортирована по значению и в определенном поле значения. Ty

Ответы [ 3 ]

5 голосов
/ 23 мая 2010

Проверьте http://java.sun.com/j2se/1.4.2/docs/api/java/util/LinkedHashMap.html для реализации Map с предсказуемым порядком итерации. Вы также можете рассмотреть возможность использования списка, если вы не выполняете поиск по ключам.

4 голосов
/ 23 мая 2010

Посмотрим. Ваши требования выглядят так:

  1. У вас есть набор пар ключ / значение, где ключи уникальны.
  2. Вы хотите иметь возможность быстрого поиска значения для данного ключа.
  3. Вы хотите иметь возможность перебирать ключи (или пары) в порядке вставки.
  4. Вы хотите иметь возможность перебирать значения в порядке некоторого поля типа значения.

Не существует единого стандартного класса коллекции Java, который удовлетворял бы всем этим требованиям. И я не думаю, что коллекции Commons или коллекции Google тоже ...

Если вы отбросите требование 3, тогда TreeSet (созданный с помощью пользовательского Comparator) сделает эту работу. Если бы вы выбросили требование 4, то LinkedHashMap справился бы с этой задачей.

Чтобы удовлетворить все требования, вам необходимо выполнить одно из следующих действий:

  • Используйте LinkedHashMap, и когда вы хотите выполнить итерацию в некотором порядке, зависящем от значений, извлеките коллекцию values карты, отсортируйте ее, используя свой собственный компаратор, и вернуть итератор для отсортированной коллекции.

  • Используйте оба параметра LinkedHashMap и TreeMap и обновляйте их параллельно.

  • Создайте пользовательский класс фасада для LinkedHashMap и TreeMap. Это должно поддерживать обе структуры данных в актуальном состоянии при вызове put, remove и так далее, а также предоставлять дополнительные методы для получения отсортированных значений.

0 голосов
/ 23 мая 2010

Если вы можете отсортировать ваши элементы заранее по атрибуту value, тогда вы можете использовать LinkedListHashMap, поскольку это сохраняет указанный вами порядок. Тем не менее, это выглядит немного хрупким и не подходит, если вам нужно позже добавить больше элементов на карту.

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

Вы можете даже обернуть все это и поместить его в Map интерфейс.

Класс Collections предоставляет binarySearch . Вот схема:

  • Поместите свой класс Value в список, List<Value> values.
  • Реализуйте класс Comparable<Value>, который сравнивает значения, используя атрибут, по которому вы хотите их отсортировать.
  • Используйте Comparator<Value> для сортировки списка.
  • Теперь, когда список отсортирован, вы можете использовать Collections.binarySearch(values, aValue, Comparator<Value>), чтобы найти индекс фактического значения. Обратите внимание, что aValue не является реальным значением - это значение с атрибутами, установленными для предоставления ключа, но остальная часть неинициализирована. Значение aValue используется только для удержания ключа сортировки.

В коде

List<Value> values = new ArrayList<Values>();
// .. add values
values.add(new Value(key, data1, data2, etc..));
Comparator<Value> compValue = new Comparator<Value>() {
  public int compare(Value v1, Value v2) {
     return v1.getKey()>v2.getKey();
  }
}

Collections.sort(values, compValue);
// now we can search on key
int index = Collections.binarySearch(values, new Value(keyTofind), valueComp);
Value foundValue = null;  // value with the key may not be in the list
if (index>=0) 
   foundValue = values.get(index);

// we can also update the list
Value newValue = new Value(key, data, data2, etc...);
int insert = Collections.binarySearch(values, newValue, valueComp);
// insert will be negative
values.add((-insert)-1, newValue);

РЕДАКТИРОВАТЬ: Если вы оберните это в интерфейсе карты, например, расширяя AbstractMap, он будет сериализуем.

...