Java Collections Framework это коллекция интерфейсов и классов, которые используются для сохранения и обработки данных.
Java Collections Framework состоит из следующих компонентов:
List
это упорядоченный список объектов (иногда еще называют последовательностью объектов). Элементы списка могут вставляться или извлекаться по их индексу в списке (индексация начинается с 0). В эту группу входят: ArrayList
, LinkedList
, Vector
, Stack
.Set
это не упорядоченная коллекция. Главная особенность множеств - уникальность элементов, то есть один и тот же элемент не может содержаться в множестве дважды. Есть такие имплементации Set
интерфейса: HashSet
, TreeSet
, LinkedHashSet
, EnumSet
. HashSet
хранит элементы в хэш-таблице, что предполагает эффективную реализацию, но не гарантирует порядок итерации элементов. TreeSet
хранит элементы в красно-чёрном дереве и упорядочивает элементы по их значениям, эта коллекция существено медленее чем HashSet
. LinkedHashSet
реализована как хэш-таблица и хранит элементы в связаном списке, в порядке котором они были вставленны.Map
(иногда можно встретить названия: отображения, словарь, ассоциативный массив, карты) отображает ключи в значения и не может иметь дубликаты ключей. Есть три основных имплементации Map
интерфейса HashMap
, TreeMap
и LinkedHashMap
. HashMap
не гарантирует воспроизводимость порядка вставки элементов. TreeMap
хранит элементы в красно-чёрном дереве и упорядычивает элементы по их ключам и медленее чем HashMap
. LinkedHashMap
упорядычивает элементы в порядке их вставки.Iterator
/ListIterator
используются для итерации элементов коллекции. Основное отличие между Iterator
и ListIterator
в том, что первый позволяет итерировать только в одном направлении, а второй в обоих направлениях.Выше сказаное можно резюмировать в такой таблице
Производительность методов каждого класса можно записать через O-нотацию
Метод | Тип | Время |
---|---|---|
get, set | ArrayList | O(1) |
add, remove | ArrayList | O(n) |
contains, indexOf | ArrayList | O(n) |
get, put, remove, containsKey | HashMap | O(1) |
add, remove, contains | HashSet | O(1) |
add, remove, contains | LinkedHashSet | O(1) |
get, set, add, remove (с любого конца) | LinkedList | O(1) |
get, set, add, remove (по индексу) | LinkedList | O(n) |
contains, indexOf | LinkedList | O(n) |
peek | PriorityQueue | O(1) |
add, remove | PriorityQueue | O(log n) |
remove, get, put, containsKey | TreeMap | O(log n) |
add, remove, contains | TreeSet | O(log n) |
List
ArrayList
ArrayList
это массив с изменяемым количесвтом элементов (стандартный array
имеет фиксированый размер), его элементы могут быть доступны непосредственно по индексу. Он реализует все операции списка и позволят вставлять все объекты, включая null
. Контейнер ArrayList
, оптимизированный для произвольного доступа к элементам, но с относительно медленными операциями вставки/удаления элементов в середине списка.
В случае переполнения массива появляется необходимость в новом, имеющем больше места. Размещение и перемещение всех элементов будет занимать O(n) времени. Также, необходимо добавление и удаление элементов для передвижения существующих элементов в массиве. Это, возможно, самое большое неудобство в использовании ArrayList
.
Поиск в ArrayList
проходит за O(1). Удаление первого элемента (худший случай) происходит за O(n), для последнего элемента (лучший случай) за O(1). Вставка происходит за O(n).
Пример
ArrayList<String> lst = new ArrayList<>(); // добавление элементов lst.add("Mercury"); lst.add("Venus"); lst.add("Earth"); lst.add("Saturn"); lst.add("Neptune"); // добавлене несколько элементов сразу lst.addAll(Arrays.asList("PlanetX", "PlanetY", "PlanetZ")); // отображение массива System.out.println(lst); // добавление элемента в определеную позицию lst.add(0, "Jupiter"); lst.add(1, "Uranus"); // получение True если значение есть в массиве, иначе False boolean isExist = lst.contains("Earth") // получение True если все значения есть в массиве, иначе False ArrayList<String> favorite = new ArrayList<>(); favorite.add("Earth"); favorite.add("Saturn"); boolean isContains = planets.containsAll(favorite); // удаление элемента по значению lst.remove("Saturn"); lst.remove("Neptune"); // оставить в списке только указаные элементы ArrayList<String> favorite = new ArrayList<>(); favorite.add("Earth"); favorite.add("Saturn"); planets.retainAll(favorite); // отображение массива System.out.println(lst); // удаление элемента по индексу lst.remove(1); // удалить все элементы в списке ArrayList<String> favorite = new ArrayList<>(); favorite.add("Earth"); favorite.add("Saturn"); planets.removeAll(favorite); // удалить элементы списка, которые соответсвуют условию Predicate class SamplePredicate<T> implements Predicate<T> { T varc1; public boolean test(T varc) { if(varc1.equals(varc)) { return true; } return false; } } SamplePredicate<String> filter = new SamplePredicate<>(); filter.varc1 = "Saturn"; planets.removeIf(filter); // обновление значения по индекску lst.set(1, "Neptune"); // получить индекс элемента по значению, если не найденно то -1 int pos = lst.indexOf("Jupiter"); // получение элемента по индексу String planet = lst.get(3) // размер массива int amount = lst.size() // получить часть массива ArrayList<String> lst2 = new ArrayList<>(lst.subList(1, 3)); // обэдинение массивов lst.addAll(lst2) // удалить все элементы lst.clear() // отсортировать список в обратном порядке List reversedList = Collections.reverse(planets); // заменить значение каждого элемента списка на результат оператор // оператор class MyOperator<T> implements UnaryOperator<T>{ T varc1; public T apply(T varc){ return varc1; } } MyOperator<String> operator = new MyOperator<>(); operator.varc1 = "Earth"; planets.replaceAll(operator); System.out.println(planets); // [Earth, Earth, Earth, Earth] // выполнить действие над каждым элементом списка // действие class MyConsumer<T> implements Consumer<T>{ public void accept(T planet){ System.out.println("We are flying to " + planet); } } MyConsumer<String> action = new MyConsumer<>(); planets.forEach(action);
LinkedList
LinkedList
— это связанный список ссылок на элементы. Таким образом, для доступа к элементу в центре, приходится производить поиск с самого начала и до конца листа. С другой стороны, добавление и удаление элемента в LinkedList
быстрее (чем в ArrayList
) по той причине, что эти операции лишь изменяют сам список.
Контейнер LinkedList
, оптимизированный для последовательного доступа, с быстрыми операциями вставки/удаления в середине списка. Произвольный доступ к элементам LinkedList
выполняется относительно медленно, т.к. требует полного перебора элементов. Класс представляет структуру данных связного списка и реализует интерфейсы List
, Dequeue
, Queue
.
Поиск в LinkedList проходит за O(n). Удаление происходит за O(1). Вставка происходит за O(1).
Пример
LinkedList<String> lst = new LinkedList<>(); // добавление элементов lst.add("Mercury"); lst.add("Earth"); lst.addLast("Saturn"); lst.addFirst("Neptune"); lst.add(1, "Venus"); // вставка в начало lst.push("Kopernik") // отображение списка System.out.println(lst); // добавлене несколько элементов сразу lst.addAll(Arrays.asList("PlanetX", "PlanetY", "PlanetZ")); // изменить элемент списка по индексу String planet = lst.set(1, "PlanetA") // получение True если значение есть в списке, иначе False boolean isExist = lst.contains("Earth") // получение элемента по индексу String planet = lst.get(3) // получение первого элемента String planet = lst.getFirst() // получение последнего элемента String planet = lst.getLast() // получить все элементы списка в виде массива String[] planets = lst.toArray() // удалить все элементы lst.clear() // получить индекс первого элемента с указаным значением, если не найденно то -1 int pos = lst.indexOf("Jupiter"); // получить индекс последнего элемента с указаным значением, если не найденно то -1 int pos = lst.lastIndexOf("Jupiter"); // удаление первого элемента со значением lst.remove("PlanetX"); // удалить первый элемент из списка и вернуть значение String planet = lst.removeFirst(); // удалить первый элемент из списка и вернуть значение String planet = lst.poll(); // удалить первый элемент из списка и вернуть значение String planet = lst.pop(); // удалить последний элемент из списка и вернуть значение String planet = lst.removeLast(); // размер списка int amount = lst.size() // перебор элементов списка for(String str: lst) { System.out.println(str); } // быстрый способ добавить/объединить списки String[] morePlanets = {"Planet1", "Planet2", "Planet3"}; Collections.addAll(lst, moreInts); // конвертирование LinkedList в ArrayList List<String> arr = new ArrayList<>(lst);
Сравнение LinkedList
и ArrayList
по скорости операций:
Метод | Arraylist | LinkedList |
---|---|---|
get(index) | O(1) | O(n) |
add(E) | O(n) | O(1) |
add(E, index) | O(n) | O(n) |
remove(index) | O(n) | O(n) |
Iterator.remove() | O(n) | O(1) |
Iterator.add(E) | O(n) | O(1) |
Сравнеие производительности Arraylist
и LinkedList
Vector
Vector
это динамический массив, похожий на ArrayList
, за исключением двух моментов: Vector
синхронизирован (потоко-безопасен) и Vector
содержит много legacy-методов. По умолчанию, Vector
удваивает свой размер когда заканчивается выделенная под элементы память. ArrayList
же увеличивает свой размер только на половину.
Stack
Стэк является подкласом Vector
и работает по принципу LIFO (last-in-first-out rule) - последним пришел, первым ушел. Обратите внимание, что Stack
и Vector
оба потокобезопасны. Используйте стэк если вы хотите вставлять и удалять элементы только с вершины стэка, что полезно в рекурсивных алгоритмах.
Пример
Stack<String> planets = new Stack<>(); // добавление элементов planets.push("Mercury"); planets.push("Earth"); planets.push("Saturn"); // вывод стэка System.out.println(planets); // пустой стэк? boolean isEmpty = planets.empty() // получить вершину стэка, без удаления String top = planets.peek(); System.out.println(top); // получить вершину стэка, с удалением String saturn = planets.pop(); System.out.println(saturn); // поиск элемента в стэке (вызов метода equals() для каждого элемента) int index = planets.search("Earth"); System.out.println(index);
Set
HashSet
, TreeSet
и LinkedHashSet
относятся к семейству Set
. В множествах Set
каждый элемент хранится только в одном экземпляре, а разные реализации Set
используют разный порядок хранения элементов. В HashSet
порядок элементов определяется по сложному алгоритму и не гарантирует порядок в котором элементы вставлялись. Если порядок хранения для вас важен, используйте контейнер TreeSet
, в котором объекты хранятся отсортированными по возрастанию в порядке сравнения или LinkedHashSet
с хранением элементов в порядке добавления.
Множества часто используются для проверки принадлежности, чтобы вы могли легко проверить, принадлежить ли объект заданному множеству, поэтому на практике обычно выбирается реализация HashSet
, оптимизированная для быстрого поиска.
Сравним времени на операцию add()
для HashSet
, TreeSet
, LinkedHashSet
.
HashSet
HashSet
расширяет AbstractSet
и реализует интерфейс Set
. HashSet
создает коллекцию, которая использует хеш-таблицу для сохранения своих значений. Класс Object
и его наследники имеют метод hashCode()
, который используется классом HashSet
для эффективного размещения объектов, заносимых в коллекцию. Ключ используется для определения уникальности элемента и называется хеш-кодом.
Особености HasSet
:
HashSet
не поддерживает порядок своих элементов, а это значит, что элементы будут возвращены в любом порядже.HashSet
не разрешает хранить дубликаты. Если вы добавите существующий элемент, то старое значение будет переписано.HashSet
разрешает добавить в колекцию null
значение, но только одно значение.HashSet
не синхронизировано.Пример
HashSet<String> planets = new HashSet<>(); // добавление элементов planets.add("Mercury"); planets.add("Earth"); planets.add("Saturn"); planets.add("Neptune"); planets.add("Venus"); // отображение множества, обратите внимание на порядок вывода System.out.println(planets); // получение True если значение есть в множестве, иначе False boolean isExist = planets.contains("Earth") // пустое множество? boolean isEmpty = planets.isEmpty() // удаление элемента по значению planets.remove("Saturn"); // удалить все элементы planets.clear() // размер множества int amount = planets.size() // перебор элементов множества for(String str: planets) { System.out.println(str); } // конвертирование HashSet в ArrayList List<String> arr = new ArrayList<>(planets); // конвертирование List в Set Set<Integer> set = new HashSet<>(list); // конвертирование List в Set, если надо учитывать сравнение элементов Set<Integer> set = new TreeSet<>(aComparator); set.addAll(list);
LinkedHashSet
Класс LinkedHashSet
расширяет класс HashSet
, не добавляя никаких новых методов. Класс поддерживает связный список элементов множества в том порядке, в котором они вставлялись.
Пример
LinkedHashSet<String> planets = new LinkedHashSet<>(); // добавление элементов planets.add("Mercury"); planets.add("Earth"); planets.add("Saturn"); planets.add("Neptune"); // отображение множества, обратите внимание на порядок вывода System.out.println(planets);
TreeSet
TreeSet
реализует интерфейс SortedSet
.
Класс TreeSet
создаёт коллекцию, которая для хранения элементов использует дерево. Объекты сохраняются в отсортированном порядке по возрастанию.
Время доступа к элементам небольшое, что делает TreeSet
отличным выбором для сохранения большого количкства отсортироыанных данных и к которым должен быть обеспечен быстрый доступ.
TreeSet
не поддерживает хранение элементов типа null
.
Пример
TreeSet<String> planets = new TreeSet<>(); // добавление элементов planets.add("Mercury"); planets.add("Earth"); planets.add("Saturn"); planets.add("Neptune"); planets.add("Venus"); // добавлене несколько элементов сразу planets.addAll(Arrays.asList("PlanetX", "PlanetY", "PlanetZ")); // отображение множества, обратите внимание на порядок вывода System.out.println(planets); // получение True если значение есть в множестве, иначе False boolean isExist = planets.contains("Earth") // пустое множество? boolean isEmpty = planets.isEmpty() // получить первый элемент String planet = planets.first(); // получить последний элемент String planet = planets.last(); // получить все элементы перед указаным Set planetsBefore = planets.headSet("Neptune"); // получить все элементы после указаного Set planetsAfter = planets.tailSet("Neptune"); // получить все элементы между двумя указаными Set planetsSub = planets.subSet("Mercury", "Venus"); // удаление элемента по значению planets.remove("Saturn"); // удалить все элементы planets.clear() // размер множества int amount = planets.size() // перебор элементов множества for(String str: planets) { System.out.println(str); } // получить индекс элемента int pos = planets.headSet("Neptune").size() // определим произволный Comparator для TreeSet Setplanets2 = new TreeSet<>(new Comparator<String>() { @Override public int compare(String o1, String o2) { // define comparing logic here return Integer.compare(o1.length() , o2.length()); } }); planets2.add("Earth"); planets2.add("Saturn"); planets2.add("Neptune"); System.out.println(planets2);
NavigableSet
Интерфейс NavigableSet
наследуется от SortedSet
и предоставляет возможность навигации по множеству в обоих направлениях.
Пример
NavigableSet<String> planets = new TreeSet<>(); // добавление элементов planets.add("Mercury"); planets.add("Earth"); planets.add("Saturn"); planets.add("Neptune"); planets.add("Venus"); // печать множества System.out.println(planets); // обратный порядок NavigableSet<String> planetsReverse = planets.descendingSet(); System.out.println(planetsReverse); // получить два последних элемента NavigableSet<String> twoLast = planets.tailSet("Saturn", true); System.out.println(twoLast); // получить элемент, который перед указанным String lower = planets.lower("Saturn"); System.out.println(lower); // получить элемент, который после указаного String higher = planets.higher("Saturn"); System.out.println(higher); // получить первый элемент и удалить его из множества String first = planets.pollFirst(); // получить последний элемент и удалить его из множества String last = planets.pollLast();
Queue
Очереди предствляют собой упорядоченый список элементов, т.к. реализуют интерфейс List
, но есть особености использования. Элементы вставляются в конец очереди, а извлекаются из начала очереди. Обычно, но не обязательно, очереди работают по принципу FIFO — первым пришел, первым ушел.
Используйте очередь если вы хотите обрабатывать поток элементов в том же порядке в котором они поступают. Хорошо для списка заданий и обработки запросов.
Queue
В Java Collections API интерфейс Queue
реализован в
LinkedList
- реализует принцип FIFO.PriorityQueue
- хранит элементы либо в естественном порядке (natural order) либо в соответсвии с Comparator
, переданым в конструктор.Пример
Queue<String> planets = new LinkedList<>(); // добавление элементов planets.add("Mercury"); planets.add("Earth"); planets.add("Saturn"); // добавить элемент, в случаи проблемы - выбросить exception planets.add("Neptune"); // добавить элемент, в случаи проблемы - вернуть false planets.offer("Venus"); // получить последний элемент очереди, без удаления String top = planets.element(); System.out.println(top); // получить последний элемент очереди, с удалением String saturn = planets.remove(); System.out.println(saturn); // итерация элементов for(String planet : planets) { System.out.println(planet); }
Deque
Deque
(Double Ended Queues) это двухсторонняя очередь, которая позволяет вставлять/удалять элементы как с конца очереди, так и с начала. Deque
интерфейс расширяет Queue
интерфейс.
В Java Collections API интерфейс Deque
реализован в
ArrayDeque
- базируется на массиве и используется при реализации стэка (принцип LIFO).LinkedList
- базируется на двух-связном списке и используется при реализации очереди (принцип FIFO).Пример
Deque<String> planets = new LinkedList<>(); planets.addLast("Mercury"); planets.offerLast("Earth"); planets.offerLast("Saturn"); planets.offerLast("Venus"); System.out.println(planets); // пустая очередь? boolean isEmpty = planets.isEmpty() // итерация по очереди и извлечение по одному элементу while (planets.peekFirst() != null) { System.out.println("Первый элемент: " + planets.peekFirst()); planets.removeFirst(); System.out.println("Очередь: " + planets); } // получить первый элемент очереди, без удаления String top = planets.peekFirst(); System.out.println(top); // получить первый элемент очереди, с удалением String saturn = planets.pollFirst(); System.out.println(saturn);
Map
В контейнерах Map
(отображения, словарь, ассоциативный массив, карты) хранятся два объекта: ключ и связанное с ним значение. Map
позволяет искать объекты по ключу. Объект, ассоциированный с ключом, называется значением. И ключи, и значения являются объектами. Ключи могут быть уникальными, а значения могут дублироваться. Некоторые отображения допускают пустые ключи и пустые значения.
Интерфейс Map
соотносит уникальные ключи со значениями. Ключ - это объект, который вы используете для последующего извлечения данных. Задавая ключ и значение, вы можете помещать значения в объект отображения. После того как это значение сохранено, вы можете получить его по ключу.
Основные методы - get()
и put()
, чтобы получить или поместить значения в отображение.
Интерфейс Map
предоставляет три представления (view) хранящихся данных:
Entry
, содержащих в себе и ключ и значениеОтображения не поддерживают реализацию интерфейса Iterable
, поэтому нельзя перебрать карту через цикл for
в форме for-each
. Можно перебрать отдельно ключи или значения или объекти Entry
.
Интерфейс SortedMap
расширяет интерфейс Map
и гарантирует, что элементы размещаются в возрастающем порядке значений ключей.
Интерфейс NavigableMap
расширяет интерфейс SortedMap
и определяет поведение отображения, поддерживающее извлечение элементов на основе ближайшего соответствия заданному ключу или ключам.
Интерфейс Map.Entry
позволяет работать с элементом отображения, в частности используется при переборе элементов. Основные мотеды интерфейса Map.Entry
equals(Object o)
сравнение на равенство двух элементовgetKey()
получить ключ элементаgetValue()
получить значение элементаhashCode()
получить хэш-код элементаsetValue(V value)
замена значения элемента на valueHashMap
HashMap использует хэш-таблицу для реализации Map
интерфейса, что позволяет операциям get()
и put()
выполнятся за константное время даже для больших наборов. HashMap
обеспечивает максимальную скорость выборки, а порядок хранения его элементов не очевиден.
HashMap
подобен Hashtable
с нескольками исключениямия:
HashTable
потокобезопасна, а HashMap
нетHashTable
не может содержать элементы null
, тогда как HashMap
может содержать один ключ null
и любое количество значений null
HashMap
, в отличие от перечислителя HashTable
, работает по принципу fail-fast (выдает исключение при любой несогласованности данных)Пример
HashMap<String, Double> planets = new HashMap<>(); // добавление элементов planets.put("Mercury", new Double(2439.7)); planets.put("Earth", new Double(6371)); planets.put("Saturn", new Double(58232)); planets.put("Neptune", new Double(24622)); planets.put("Venus", new Double(6051.8)); // отображение множества, обратите внимание на порядок вывода System.out.println(planets); // получить значение по ключу Double radius = planets.get("Earth"); // получение True если ключ есть в отображении, иначе False boolean isExist = planets.containsKey("Earth") // получение True если значение есть в отображении, иначе False boolean isExist = planets.containsValue("Earth") // пустое отображение? boolean isEmpty = planets.isEmpty() // удаление элемента по ключу planets.remove("Saturn"); // список ключей Set keys = planets.keySet(); // список значений Collection<Double> values = planets.values(); ArrayList<Double> arr = new ArrayList<>(planets.values()); // множество элементов ввиде объектов интерфейса Map.Entry Set entries = planets.entrySet(); // перебор элементов Entry отображения с помощью for for (Map.Entry me : planets.entrySet()) { System.out.println("Key: "+me.getKey() + " & Value: " + me.getValue()); } // перебор элементов отображения с помощью while Set entries = planets.entrySet(); Iterator i = entries.iterator(); while(i.hasNext()) { Map.Entry me = (Map.Entry)i.next(); System.out.print(me.getKey() + ": "); System.out.println(me.getValue()); } // размер отображения int amount = planets.size() // удалить все элементы planets.clear() // конвертирование Map в ArrayList: список ключей List keyList = new ArrayList(planets.keySet()); // конвертирование Map в ArrayList: список значений List valueList = new ArrayList(planets.valueSet()); // конвертирование Map в ArrayList: список ключ-значения List entryList = new ArrayList(planets.entrySet()); // упорядочивание Map по значениям List list = new ArrayList(planets.entrySet()); Collections.sort(list, new Comparator() { @Override public int compare(Entry e1, Entry e2) { return e1.getValue().compareTo(e2.getValue()); } });
TreeMap
TreeMap
реализует Map
интерфейс с помощью структуры красно-чёрного дерева и хранит ключи отсортированными по возрастанию (естественный порядок, natural order). Переопределить сортировку можно предоставив экземпляр класса Comparator
, метод compare
которого и будет использован для сортировки ключей. Обратите внимание, что все ключи добавленные в словарь должны реализовывать интерфейс Comparable
(это необходимо для сортировки).
TreeMap
предоставляет быстрый доступ к своим элементам.
Для вставки, удаления и поиска элементов в Map
лучше использовать HashMap
. Если же нужно последовательно обходить карты в неком порядке то лучше использовать TreeMap
. Иногда, в зависимости от размера коллекции, лучше добавить элементы в HashMap
, а потом сконвертировать в TreeMap
для упорядоченого обхода элементов.
Пример
TreeMap<String, Double> planets = new TreeMap<>(); // добавление элементов planets.put("Mercury", new Double(2439.7)); planets.put("Earth", new Double(6371)); planets.put("Saturn", new Double(58232)); planets.put("Neptune", new Double(24622)); planets.put("Venus", new Double(6051.8)); // отображение множества, обратите внимание на порядок вывода System.out.println(planets); // получить значение по ключу Double radius = planets.get("Earth"); // получение True если ключ есть в отображении, иначе False boolean isExist = planets.containsKey("Earth") // получение True если значение есть в отображении, иначе False boolean isExist = planets.containsValue("Earth") // пустое отображение? boolean isEmpty = planets.isEmpty() // удаление элемента по ключу planets.remove("Saturn"); // список ключей Set keys = planets.keySet(); // список значений Collection<Double> values = planets.values(); ArrayList<Double> arr = new ArrayList<>(planets.values()); // множество элементов ввиде объектов интерфейса Map.Entry Set entries = planets.entrySet(); // перебор элементов отображения с помощью for for (Map.Entry me : planets.entrySet()) { System.out.println("Key: "+me.getKey() + " & Value: " + me.getValue()); } // перебор элементов отображения с помощью while Set entries = planets.entrySet(); Iterator i = entries.iterator(); while(i.hasNext()) { Map.Entry me = (Map.Entry)i.next(); System.out.print(me.getKey() + ": "); System.out.println(me.getValue()); } // размер отображения int amount = planets.size() // удалить все элементы planets.clear() // сортировка элементов по значению // компаратор public static <K, V extends Comparable<V>> Map<K, V> sortByValues(final Map<K, V> map) { Comparator<K> valueComparator = new Comparator<K>() { public int compare(K k1, K k2) { int compare = map.get(k1).compareTo(map.get(k2)); if (compare == 0) return 1; else return compare; } }; Map<K, V> sortedByValues = new TreeMap<K, V>(valueComparator); sortedByValues.putAll(map); return sortedByValues; } Map sortedMap = sortByValues(planets); for (Map.Entry me : sortedMap.entrySet()) { System.out.println("Key: "+me.getKey() + " & Value: " + me.getValue()); }
LinkedHashMap
LinkedHashMap
реализует связанный список элементов отображения и хранит ключи в порядке вставки. Также позволяет сортировать элементы в порядке последнего доступа. LinkedHashMap
не обеспечивает скорость поиска как HashMap
.
Пример
LinkedHashMap<String, Double> planets = new LinkedHashMap<>(); // добавление элементов planets.put("Mercury", new Double(2439.7)); planets.put("Earth", new Double(6371)); planets.put("Saturn", new Double(58232)); planets.put("Neptune", new Double(24622)); planets.put("Venus", new Double(6051.8)); // отображение множества, обратите внимание на порядок вывода System.out.println(planets); // получить значение по ключу Double radius = planets.get("Earth"); // получение True если ключ есть в отображении, иначе False boolean isExist = planets.containsKey("Earth") // получение True если значение есть в отображении, иначе False boolean isExist = planets.containsValue("Earth") // перебор элементов отображения с помощью for for (Map.Entry me : planets.entrySet()) { System.out.println("Key: "+me.getKey() + " & Value: " + me.getValue()); } // еще один вариант перебора элементов отображения с помощью for for (Map.Entryme : planets.entrySet()) { String key = me.getKey(); Double value = me.getValue(); System.out.println("Key: " + key + " & Value: " + value); }
Различия между Iterator и ListIterator?
Set
, List
и Map
. В отличие от него, ListIterator
может быть использован только для перебора элементов коллекции List
.Iterator
позволяет перебирать элементы только в одном направлении, при помощи метода next()
. Тогда как ListIterator
позволяет перебирать список в обоих направлениях, при помощи методов next()
и previous()
.ListIterator
вы можете модифицировать список, добавляя/удаляя элементы с помощью методов add()
и remove()
. Iterator
не поддерживает данного функционала.