#
Collections in Java
#
Collections in Java - Theory
This tutorial explains to you when to use and how to use Collections in Java.
A collection groups objects of the same structure together.
Info
- The Collections are not storing
key/value
pairs, so the collections are not maps. - The arrays have fixed length, the collections have variable length.
- The Collections could be : Lists, Queues, Sets (have no duplicates).
- Interfaces: Collection, List, Set, Queue
- Classes: Collections, ArrayList, LinkedList, etc.
The most used collection classes are:
ArrayList
: not synchronized, better usage: storing and accessing dataLinkedList
: not synchronized, better usage: manipulating dataVector
: synchronized, like ArrayListHashSet
: not synchronized, the insert order is not kept, accept 1 null value.LinkedHashSet
: not synchronized, the insert order is kept, accept 1 null value, use more memory than HashSets.TreeSet
: not synchronized, the values are ordered => insert/remove operations are slow, but the read is fast, there are no null values.PriorityQueue
: you can read the elements from this type of queue in a default or custom order defined by a Comparator (the priority is defined by the natural or custom order). The PriorityQueue class in Java is not thread-safe.ArrayBlockingQueue
: based on FIFO, fixed size Blocking Queue (implements BlockingQueue interface).LinkedBlockingQueue
: based on FIFO, variable size Blocking Queue (max size = Integer.MAX_VALUE), (implements BlockingQueue interface).PriorityBlockingQueue
: Blocking Queue which is a PriorityQueue in the same timeArrayDeque
: is used for inserting and removing elements from both ends of the queue (are not thread safe).
Info
Blocking Queues are thread safe and can block a producer until the queue has room or can block a consumer until the queue has elements available.
For more information on collection concurrency take a look at the Synchronized vs Concurrent Collection article.
#
Lists in Java - Example
Here you can see a standard usage of the ArrayList class:
package com.exampe.java;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.util.ArrayList;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) throws InterruptedException {
SpringApplication.run(DemoApplication.class, args);
System.out.println("--------------------------------------------");
ArrayList<String> carList = new ArrayList<>();
// safe to use with multiple threads
carList.add("Audi");
carList.add("Renault");
carList.add("Peugeot");
carList.add("Dacia");
carList.remove("Dacia");
carList.forEach( x-> {
System.out.println("forEach/ car= " + x);
});
for (String c : carList) {
System.out.println("car= " + c);
}
System.out.println("--------------------------------------------");
}
}
The result of this code is :
--------------------------------------------
forEach/ car= Audi
forEach/ car= Renault
forEach/ car= Peugeot
car= Audi
car= Renault
car= Peugeot
--------------------------------------------
#
PriorityQueue in Java - Example
Here you can see the usage of the PriorityQueue class.
First we need to define the Employee class.
package com.example.demo;
public class Employee {
String name;
Integer salary;
public Employee(String name, Integer salary) {
this.name = name;
this.salary = salary;
}
}
We can define a Comparator (if not created a natural order (ASC/DESC) will be used for objects like String or Integer):
package com.example.demo;
import java.util.Comparator;
public class MyEmployeeSalaryComparator implements Comparator<Employee> {
@Override
public int compare(Employee emp1, Employee emp2) {
// descending order
return emp1.salary < emp2.salary ? 1 : -1;
}
}
and here we have the main class:
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.util.PriorityQueue;
@SpringBootApplication
public class Demo1Application {
public static void main(String[] args) {
SpringApplication.run(Demo1Application.class, args);
// PriorityQueue
PriorityQueue<Employee> salPriorityQueue = new PriorityQueue<>(new MyEmployeeSalaryComparator());
// add an element to the queue
salPriorityQueue.add(new Employee("John", 2100));
salPriorityQueue.add(new Employee("Elena", 2200));
salPriorityQueue.add(new Employee("Dan", 2300));
salPriorityQueue.add(new Employee("Dana", 2000));
while (!salPriorityQueue.isEmpty()) {
// find and remove the head of the queue
Employee tempEmp = salPriorityQueue.poll();
System.out.println("tempEmp= "+tempEmp.salary + " >> "+ tempEmp.name);
}
}
}
The result of this code is :
tempEmp= 2300 >> Dan
tempEmp= 2200 >> Elena
tempEmp= 2100 >> John
tempEmp= 2000 >> Dana
#
Sets in Java - Example
Sets are storing unique values in a collection.
Here we have some example of using HashSet, LinkedHashSet and TreeSet classes:
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.util.*;
@SpringBootApplication
public class Demo1Application {
public static void main(String[] args) {
SpringApplication.run(Demo1Application.class, args);
// HashSet
HashSet hs = new HashSet();
hs.add(10);
hs.add(20);
hs.add(5);
System.out.println("HashSet - unordered");
hs.stream().forEach(System.out::println);
// LinkedHashSet
System.out.println("-----------------------");
LinkedHashSet lhs = new LinkedHashSet();
lhs.add(10);
lhs.add(20);
lhs.add(5);
System.out.println("LinkedHashSet - order of insertion");
lhs.stream().forEach(System.out::println);
// TreeSet
System.out.println("-----------------------");
TreeSet ts = new TreeSet();
ts.add(10);
ts.add(20);
ts.add(5);
System.out.println("TreeSet - natural order if no Comparator is defined");
ts.stream().forEach(System.out::println);
}
}
When we run this code we get the following:
HashSet - unordered
20
5
10
-----------------------
LinkedHashSet - order of insertion
10
20
5
-----------------------
TreeSet - natural order if no Comparator is defined
5
10
20