Упорядоченная карта Java
Есть ли в Java объект, который действует как карта для хранения и доступа к парам ключ / значение, но может возвращать упорядоченный список ключей и упорядоченный список значений, чтобы списки ключей и значений были в одном и том же порядке?
Итак, в качестве объяснения по коду, я ищу что-то, что ведет себя как мой вымышленный OrderedMap:
OrderedMap<Integer, String> om = new OrderedMap<>();
om.put(0, "Zero");
om.put(7, "Seven");
String o = om.get(7); // o is "Seven"
List<Integer> keys = om.getKeys();
List<String> values = om.getValues();
for(int i = 0; i < keys.size(); i++)
{
Integer key = keys.get(i);
String value = values.get(i);
Assert(om.get(key) == value);
}
8 ответов
Интерфейс SortedMap (с реализацией TreeMap) должен быть вашим другом.
Интерфейс имеет методы:
keySet()
который возвращает набор ключей в порядке возрастанияvalues()
который возвращает коллекцию всех значений в порядке возрастания соответствующих ключей
Так что этот интерфейс полностью соответствует вашим требованиям. Однако ключи должны иметь осмысленный порядок. В противном случае вы можете использовать LinkedHashMap, где порядок определяется порядком вставки.
Существует ли объект, который действует как карта для хранения и доступа к парам ключ / значение, но может возвращать упорядоченный список ключей и упорядоченный список значений, чтобы списки ключей и значений были в одном и том же порядке?
Вы ищете java.util.LinkedHashMap. Вы получите список пар Map.EntryComparator
,
LinkedHashMap поддерживает порядок ключей.
java.util.LinkedHashMap, кажется, работает так же, как обычный HashMap в противном случае.
tl;dr
Хранить Map< Integer , String >
в порядке, отсортированном по ключу, используйте любой из двух классов, реализующих SortedMap
/NavigableMap
интерфейсы:
TreeMap
ConcurrentSkipListMap
Если вы управляете картой в одном потоке, используйте первый, TreeMap
. При манипулировании между потоками используйте второй,ConcurrentSkipListMap
.
Подробнее см. В таблице ниже и в следующем обсуждении.
Детали
Вот составленная мной графическая таблица, показывающая особенности десяти Map
реализации в комплекте с Java 11.
В NavigableMap
интерфейс это то, что SortedMap
должен был быть на первом месте. ВSortedMap
логически должен быть удален, но не может быть удален, поскольку некоторые сторонние реализации карт могут использовать интерфейс.
Как видно из этой таблицы, только два класса реализуют SortedMap
/NavigableMap
интерфейсы:
Оба они хранят ключи в отсортированном порядке, либо в их естественном порядке (используя compareTo
метод Comparable
(https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Comparable.html) интерфейс) или с помощью Comparator
реализацию вы пройдете. Разница между этими двумя классами в том, что второй, ConcurrentSkipListMap
, является потокобезопасным, с высокой степенью параллелизма.
См. Также столбец Порядок итераций в таблице ниже.
- В
LinkedHashMap
class возвращает свои записи в том порядке, в котором они были изначально вставлены. EnumMap
возвращает записи в том порядке, в котором определен класс перечисления ключа. Например, карта, на которой сотрудник какой день недели работает (Map< DayOfWeek , Person >
) используетDayOfWeek
enum класс, встроенный в Java. Это перечисление определяется первым понедельником и последним воскресеньем. Таким образом, записи в итераторе появятся именно в таком порядке.
Остальные шесть реализаций не обещают порядок, в котором они сообщают свои записи.
Я думаю, что ближайшая коллекция, которую вы получите из фреймворка, это SortedMap
Вы можете использовать интерфейс NavigableMap, к которому можно получить доступ и пройти в порядке возрастания или убывания ключа. Этот интерфейс предназначен для замены интерфейса SortedMap. Навигационная карта обычно сортируется в соответствии с естественным порядком ее ключей или с помощью компаратора, предоставляемого во время создания карты.
Существует три наиболее полезных реализации: TreeMap, ImmutableSortedMap и ConcurrentSkipListMap.
Пример TreeMap:
TreeMap<String, Integer> users = new TreeMap<String, Integer>();
users.put("Bob", 1);
users.put("Alice", 2);
users.put("John", 3);
for (String key: users.keySet()) {
System.out.println(key + " (ID = "+ users.get(key) + ")");
}
Выход:
Alice (ID = 2)
Bob (ID = 1)
John (ID = 3)
Я думаю, что интерфейс SortedMap реализует то, что вы просите, и TreeMap реализует это.
http://java.sun.com/j2se/1.5.0/docs/api/java/util/SortedMap.html http://java.sun.com/j2se/1.5.0/docs/api/java/util/TreeMap.html
Начиная с Java 6 существует неблокирующая поточно-ориентированная альтернатива TreeMap. Смотрите ConcurrentSkipListMap.
Современная версия Java ответа Штеффи Керан
public class Solution {
public static void main(String[] args) {
// create a simple hash map and insert some key-value pairs into it
Map<String, Integer> map = new HashMap<>();
map.put("Python", 3);
map.put("C", 0);
map.put("JavaScript", 4);
map.put("C++", 1);
map.put("Golang", 5);
map.put("Java", 2);
// Create a linked list from the above map entries
List<Map.Entry<String, Integer>> list = new LinkedList<>(map.entrySet());
// sort the linked list using Collections.sort()
list.sort(Comparator.comparing(Map.Entry::getValue));
list.forEach(System.out::println);
}
}
Я использовал карту Simple Hash, связанный список и коллекции для сортировки карты по значениям.
import java.util.*;
import java.util.Map.*;
public class Solution {
public static void main(String[] args) {
// create a simple hash map and insert some key-value pairs into it
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("Python", 3);
map.put("C", 0);
map.put("JavaScript", 4);
map.put("C++", 1);
map.put("Golang", 5);
map.put("Java", 2);
// Create a linked list from the above map entries
List<Entry<String, Integer>> list = new LinkedList<Entry<String, Integer>>(map.entrySet());
// sort the linked list using Collections.sort()
Collections.sort(list, new Comparator<Entry<String, Integer>>(){
@Override
public int compare(Entry<String, Integer> m1, Entry<String, Integer> m2) {
return m1.getValue().compareTo(m2.getValue());
}
});
for(Entry<String, Integer> value: list) {
System.out.println(value);
}
}
}
Выход:
C=0
C++=1
Java=2
Python=3
JavaScript=4
Golang=5