Про Java Collections Framework: почти все и сразу Java 10.04.2017

Java Collections Framework это коллекция интерфейсов и классов, которые используются для сохранения и обработки данных.

java_collection.png

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 в том, что первый позволяет итерировать только в одном направлении, а второй в обоих направлениях.

Выше сказаное можно резюмировать в такой таблице

java_collection_summary.png

Производительность методов каждого класса можно записать через 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

java_arraylist_vs_linkedlist.png

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.

java_hashset_treeset_linkedhashset.png

HashSet

HashSet расширяет AbstractSet и реализует интерфейс Set. HashSet создает коллекцию, которая использует хеш-таблицу для сохранения своих значений. Класс Object и его наследники имеют метод hashCode(), который используется классом HashSet для эффективного размещения объектов, заносимых в коллекцию. Ключ используется для определения уникальности элемента и называется хеш-кодом.

Особености HasSet:

  1. HashSet не поддерживает порядок своих элементов, а это значит, что элементы будут возвращены в любом порядже.
  2. HashSet не разрешает хранить дубликаты. Если вы добавите существующий элемент, то старое значение будет переписано.
  3. HashSet разрешает добавить в колекцию null значение, но только одно значение.
  4. 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
Set planets2 = 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) замена значения элемента на value

HashMap

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.Entry me : planets.entrySet()) {
    String key = me.getKey();
    Double value = me.getValue();
    System.out.println("Key: " + key + " & Value: " + value);
}

Различия между Iterator и ListIterator?

  • Iterator может использоваться для перебора элементов Set, List и Map. В отличие от него, ListIterator может быть использован только для перебора элементов коллекции List.
  • Iterator позволяет перебирать элементы только в одном направлении, при помощи метода next(). Тогда как ListIterator позволяет перебирать список в обоих направлениях, при помощи методов next() и previous().
  • При помощи ListIterator вы можете модифицировать список, добавляя/удаляя элементы с помощью методов add() и remove(). Iterator не поддерживает данного функционала.
Цитата
Только одно делает исполнение мечты невозможным - это страх неудачи.
Пауло Коэльо
Категории
Архив