Платформа коллекции - это среда для работы с коллекцией данных в Java.

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

Каркас коллекции - это набор интерфейсов и конкретных классов. Мы можем использовать его для хранения и управления группой объектов. Он поддерживает встроенные алгоритмы сортировки и поиска. Можно сказать, что фреймворк сбора APIS готов для различных структур данных. Фреймворк коллекции находится в основных библиотеках Java. Нам просто нужно импортировать их из пакета java.util.

Прежде чем мы начнем обсуждать каждую коллекцию отдельно, вам необходимо знать несколько общих функций:

  • Коллекции могут работать (удерживать) только Объекты, примитивы не допускаются.
  • Фреймворк коллекций широко использует концепцию дженериков. Например, если вы хотите создать ArrayList, который может содержать коллекцию строк, мы можем сделать это следующим образом: ArrayList ‹String› list = new ArrayList ‹› ();
    Если вы не указывайте тип, который он примет как набор объектов.
  • Обычно используется полиморфный способ создания экземпляров из коллекций. пример: List ‹String› list = new ArrayList ‹› ();

Интерфейс списка

Как вы можете видеть на схеме выше, List - это интерфейс с тремя конкретными классами. Список представляет собой упорядоченную структуру данных динамического размера. Это позволяет дублировать значения.

По сути, коллекции позволяют нам работать с группой данных. Так же, как и массив. Давайте посмотрим на различия в создании массива и списка.

// import statements and valid code above
int[] numberArray = new int[3];
numberArray[0] = 1;
numberArray[1] = 3;
numberArray[2] = 7;
System.out.println(Arrays.toString(numberArray)); // [1, 3, 7]
List<Integer> colorsList = new ArrayList<>();
colorsList.add(1);
colorsList.add(3);
colorsList.add(4);
System.out.println(colorsList); // [1, 3, 7]

В приведенном выше примере мы создали массив int со значениями [1, 2, 3] и создали List of Integer со значениями [1, 2, 3].

  1. Когда мы создали массив int, мы указываем размер, потому что массив представляет собой структуру данных фиксированного размера, однако мы не указываем размер в коллекциях. Мы можем думать, что коллекции имеют динамический размер.
  2. Как вы можете видеть в примере со списком, чтобы указать тип данных, нам нужно использовать оператор ‹›. Он использует дженерики в java.
  3. Массив может быть создан как примитивный тип данных, но Коллекции не допускают примитивов, они могут содержать только объекты.

Список - это интерфейс, поэтому в нем много абстрактных методов, а в списке есть три конкретных класса, которые его реализуют. Зачем нам нужны три разных реализации List? Поскольку способы их реализации различаются, каждая реализация может быть подходящей для определенного сценария. В частности, реализации ArrayList и LinkedList.

ArrayList - реализация списка. Он основан на внутреннем массиве и может динамически увеличиваться и уменьшаться - реализация массива с изменяемым размером. ArrayList не синхронизирован (небезопасен для многопоточности). Если несколько потоков будут работать с одним и тем же экземпляром ArrayList, java не гарантирует, что он будет вести себя так, как ожидалось. Его удобно использовать, когда вам не нужно существенно изменять (добавлять и удалять) количество элементов внутри, и он удобен для доступа к элементам по индексу. Почему? Потому что он внутренне основан на массиве. Прочтите статью Структуры данных для получения дополнительной информации.

Реализация LinkedList основана на двусвязном списке. Поскольку он основан на внутреннем связном списке, он имеет динамический размер по характеру структуры данных. Это не синхронизировано. Его удобно использовать, когда вы не знаете заранее точное количество элементов и не часто получаете доступ к различным элементам по индексу. Почему? Потому что это внутренний двусвязный список.

Вектор. Этот класс примерно эквивалентен ArrayList, за исключением того, что он синхронизирован.

Итак, мы обсудили три основных реализации интерфейса списка. Теперь вам просто нужно изучить методы (API) List, и все готово.

import java.util.List;
import java.util.ArrayList; 
public class Main {
   public static void main(String[] args) {
      // create list of String
      List<String> cars = new ArrayList<>();
      // add elements to back of the list
      cars.add("bmw");
      cars.add("audi");
      cars.add("honda");
      System.out.println(cars); // ["bmw", "audi", "honda"]
      
      // insert element at specified position
      cars.add(1, "tesla");
      System.out.println(cars); // ["bmw", "tesla", "audi", "honda"]
      // get specific element by index(index starts from 0)
      String str = cars.get(2);
      System.out.println(str); // audi
      // find out number of elements in the list      
      int size = cars.size(); 
      System.out.println("Size: " + size); // 4
      // remove by index
      cars.remove(0);
      System.out.println(cars); // ["tesla", "audi", "honda"]
      // remove by value
      cars.remove("honda");
      System.out.println(cars); // ["tesla", "audi"]
      // find index of specific element
      int index = cars.indexOf("audi");
      System.out.println(index); // 1
      // check if list contains specified element
      boolean isThere = cars.contains("bmw");
      System.out.println(isThere); //false
   }
}

В приведенном выше примере я использовал реализацию ArrayList. То же самое для всех остальных реализаций.

Установить интерфейс

Set не допускает повторяющихся значений. В интерфейсе Set нет метода get (index). В целом производительность классов реализации Set очень высока. Он имеет три основных реализации: HashSet, LinkedHashSet, TreeSet.

HashSet - это реализация интерфейса Set. Он основан на структуре данных таблицы hast. Это не гарантирует порядок вставки или итерации. Допускается одно нулевое значение. HashSet имеет постоянную производительность. Неважно, насколько велика коллекция, для выполнения основных операций, таких как добавление, удаление, содержание и изменение размера, потребуется постоянное время. Это невероятно! HashSet хорош, когда вам не нужно упорядочивать или сортировать данные и если вам не нужно читать по индексу.

LinkedHashSet полностью аналогичен HashSet, за исключением того, что он поддерживает порядок вставки. LinkedHashSet также гарантирует постоянную производительность. Производительность, вероятно, будет немного ниже, чем у HashSet, из-за дополнительных расходов на поддержание связанного списка.

TreeSet - реализация упорядоченного набора. Это следует за естественным порядком. Что такое естественный порядок? Давайте сначала обсудим сам заказ. Данные можно упорядочить по-разному. Например, его можно расположить в алфавитном порядке, если это набор строк, или в порядке возрастания, если это набор чисел. И так далее. Если это набор нестандартных объектов, как его следует упорядочить? Итак, чтобы решить эту проблему Как заказать вещи? Java имеет интерфейс Comparable, в котором есть только один метод compareTo. Каждый объект, который необходимо упорядочить, может реализовать этот интерфейс, и все другие механизмы упорядочения в Java смогут упорядочивать ваши данные. Тот же шаблон для нашего TreeSet - он упорядочивает данные на основе метода compareTo для заданного типа данных.

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Set<String> cars = new HashSet<>();
        cars.add("honda");
        cars.add("audi");
        cars.add("bmw");
        cars.add("tesla");
        cars.add("bmw");

        // 1. We can see that there is no order
        // 2. No duplicates
        System.out.println(cars); // [audi, tesla, honda, bmw]


        // find out number of elements in the set
        System.out.println("Size: " + cars.size()); // Size: 4

        // check if specific element is the set
        System.out.println(cars.contains("honda")); // true

        // check if set is empty
        System.out.println(cars.isEmpty()); // false

        // remove element from set if exist
        // if it's removed return true otherwise false
        System.out.println(cars.remove("honda")); // true

        // there is no get(index) method in the Set
        // We can iterate over the set with for each loop or   Iterator<E>
        for (String car : cars) {
            // audi tesla bmw
            System.out.print(car + " ");
        }

        System.out.println();
        // Iterate over set with Iterator<E>
        Iterator<String> iterator = cars.iterator();
        while(iterator.hasNext()) {
            // audi tesla bmw
            System.out.print(iterator.next() + " ");
        }
        System.out.println();


        // LinkedHashSet
        Set<String> cars2 = new LinkedHashSet<>();
        cars2.add("honda");
        cars2.add("audi");
        cars2.add("bmw");
        cars2.add("tesla");
        cars2.add("bmw");

        // 1. LinkedHashSet implementation will keep insertion order
        // 2. There is no duplicates allowed in set
        System.out.println(cars2); // [honda, audi, bmw, tesla]


        // TreeSet
        Set<String> cars3 = new TreeSet<>();
        cars3.add("honda");
        cars3.add("audi");
        cars3.add("bmw");
        cars3.add("tesla");
        cars3.add("bmw");

        // 1. Data is ordered in natural order - for String is alphabetical order
        // 2. There is no duplicates allowed in set
        System.out.println(cars3); // [audi, bmw, honda, tesla]
    }
}

Очередь, стек и удаление из очереди

Эти коллекции предназначены для хранения элементов перед обработкой.

Очередь - это структура данных в порядке очереди. Чтобы понять структуру данных очереди, вы всегда можете подумать о людях, ожидающих в очереди в кафе. Кто придет первым, будет обслужен первым и первым выйдет из очереди.

Есть три основных метода работы с интерфейсом очереди:

  1. offer (e) добавляет новый элемент в конец очереди, если это возможно, в противном случае. он вернет false.
  2. Метод poll () удалит элемент из головы и вернет его.
  3. peek () возвращает, но не удаляет заголовок очереди.

Стек - это структура данных "последний вошел - первым ушел". В Java нет интерфейса Stack, есть класс Stack. Большую часть времени структура данных стека (LIFO) реализуется с помощью Dequeue.

Представьте себе стопку тарелок. Мы всегда ставим тарелку сверху стопки, а когда нам нужно, то и снимаем ее сверху.

Есть три основных метода работы со стеком:

  1. push (e) Помещает элемент в верхнюю часть этой стопки.
  2. pop () Удаляет объект наверху этого стека и возвращает этот объект как значение этой функции.
  3. peek () возвращает объект сверху, но не удаляет его.

Dequeue - это интерфейс, который может вести себя как очередь, а также как структура данных стека.

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

public class Main {
    public static void main(String[] args) {
        // Queue - FIFO (First In, First Out)
        // LinkedList is one of the Queue implementations as well
        Queue<String> queueInStore = new LinkedList<>();
        queueInStore.add("Alex");
        queueInStore.add("Misha");
        queueInStore.add("Boris");
        queueInStore.add("John");

        // [Alex, Misha, Boris, John]
        System.out.println(queueInStore);

        // poll() method get element and remove it from queue
        String currentCustomer = queueInStore.poll();

        // Working with cutomer: Alex
        System.out.println("Working with cutomer: " + currentCustomer);

        // Alex is no longer in the queue
        // Customers in line: [Misha, Boris, John]
        System.out.println("Customers in line: " + queueInStore);
        System.out.println("-------------");

        currentCustomer = queueInStore.poll();
        // Working with customer: Misha
        System.out.println("Working with customer: " + currentCustomer);

        // Customers in line: [Boris, John]
        System.out.println("Customers in line: " + queueInStore);
        System.out.println("==============");


        // Stack
        // LIFO - Last In First Out
        Stack<String> messages = new Stack<>();
        // push() will add element to the stack
        // it will push an item onto the top of this stack
        messages.push("Message from John");
        messages.push("Message from Alex");
        messages.push("Message from Smith");

        //[Message from John, Message from Alex, Message from Smith]
        System.out.println(messages);

        //pop() will get elements from the top(last added) 
        // it will remove this element
        String msg = messages.pop();

        // Reading Message from Smith
        System.out.println("Reading " + msg);
        System.out.println("------");

        msg = messages.pop();
        // Reading Message from Alex
        System.out.println("Reading " + msg);
        System.out.println("------");
    }
}

Интерфейс карты

Карта - это структура данных, основанная на ключевом значении. В некоторых языках программирования он известен как словарь. Ключи уникальны на карте. Карта является частью структуры коллекции (она не расширяет Collection или Iterable).

Класс HashMap представляет собой реализацию Map на основе хэш-таблицы:
1. Не поддерживает никакого порядка.
2. Позволяет использовать один ноль в качестве ключа и любое количество нулей. как значение.
3. Несинхронизировано.

Хеш-таблица. Этот класс реализует хеш-таблицу, которая сопоставляет ключи значениям. Любой объект, отличный от null, может использоваться как ключ или как значение:
1. Не поддерживает никакого порядка.
2. Не допускает null как ключ и значение.
3. Синхронизировано.

Класс LinkedHashMap почти такой же, как HashMap, за исключением того, что он поддерживает порядок вставки.

Класс TreeMap - NavigableMap реализация на основе красно-черного дерева. Карта сортируется в соответствии с естественным порядком ее ключей или Comparator, предоставленным во время создания карты, в зависимости от того, какой конструктор используется.

import java.util.*;

public class Main {
    public static void main(String[] args) {
        //    K   ,  V
        Map<String, Double> fruit = new HashMap<>();
        fruit.put("Orange", 1.05);
        fruit.put("Mango", 0.50);
        fruit.put("Apple", 0.76);
        fruit.put("Lemon", 1.47);
        fruit.put("Banana", 1.39);
        System.out.println(fruit);
        // there is no indexes in the map
        Double applePrice = fruit.get("Apple");
        System.out.println("Apple price is " + applePrice);

        System.out.println(fruit.get("Mango")); // 0.50
        Double lemonPrice = fruit.get("abc");

        // if key is not part of the map, it will return null
        System.out.println(lemonPrice);

        // Get sum of prices of Mango, Banana and Orange
        Double sumPrice = fruit.get("Mango") + fruit.get("Banana") + fruit.get("Orange");
        System.out.println("Price sum: " + sumPrice);

        // put(K, V) - will put element into map
        // get(K) - it will return V based on the key, if key is not in the map, it will return null
        // containsKey(K) - returns true if key in the map otherwise false

        boolean isThere = fruit.containsKey("Kiwi");
        System.out.println("Kiwi is in the map: " + isThere);

        String strKey = "Orange";
        if (fruit.containsKey(strKey)) {
            System.out.println("Price: " + fruit.get(strKey));
        } else {
            System.out.println("Key is not in the map: " + strKey);
        }

        // containsValue(V) true if value is there
        System.out.println(fruit.containsValue(0.50));
        System.out.println("-------");

        // remove(K); - will remove entity from the map (K , V)
        System.out.println(fruit);

        // if key is not there nothing will happen
        fruit.remove("Orange");
        System.out.println(fruit);

        // HashMap impl of Map does not maintain insertion order

        // keySet() -> return all the keys of the as Set<K>
        System.out.println("--- KEYS ---");
        Set<String> keys = fruit.keySet();
        System.out.println(keys);

        // Mango=0.5
        fruit.put("Mango", 1.50);
        System.out.println(fruit);
    }
}

Это все для платформы Collection в Java. Все ссылки и ссылки взяты из Java 8.

This article is part of the series of articles to learn Java programming language from Tech Lead Academy:
1. Introduction to programming 
2. OS, File, and File System
3. Working with terminal 
4. Welcome to Java Programming Language
5. Variables and Primitives in Java
6. Methods with Java
7. Java Math Operators and special operators
8. Conditional branching in Java
9. Switch statement in Java
10. Ternary operator in Java
11. Enum in Java
12. String class and its methods in Java
13. Loops in Java
14. Access modifiers in Java
15. Static keyword in Java
16. The final keyword in Java
17. Class and Object in Java
18. Object Oriented Programming in Java
19. OOP: Encapsulation in Java
20. Inheritance in Java
21. Abstraction in Java
22. Polymorphism in Java
23. Overriding vs Overloading in Java
24. OOP Design Principles in Java
25. Array in Java
26. Data Structures with Java
27. Collection framework in Java
28. ArrayList in Java
29. Set in Java
30. Map in Java
31. LocalDate in Java
32. Exception in Java
33. IO in Java
34. Design Patterns
35. Generics in Java
36. Multithreading in java
37. JUnit
38. Big O Notation for coding interviews
39. Top 17 Java coding interview questions for SDET