Data Structures in Java


All programming languages ​​have some way of representing groups of data in common. The most popular of all languages ​​are arrays or vectors. Thus, many programmers tend to summarize their arsenal to just a single piece of data or an array. However, there are several other options for "structuring" this data. That's what we're going to talk about in this article, using the Java language as the technology for demonstration. Data Structures is one of the most special topics of any training in computing courses. From my graduation, I consider that it was as important as Algorithms, Operating Systems and Networks. These four disciplines form the foundation for every good systems developer. The Data Structures

In Java, data structures are represented in the language in the Java Collections Framework, and you can access all the details about it in the official tutorial ( link ). According to the Java Tutorial.

"A collection — sometimes called a container — is simply an object that groups multiple elements into a single unit. Collections are used to store, retrieve, manipulate, and communicate aggregate data. Typically, they represent data items that form a natural group, such as as a poker hand (a collection of cards), a mail folder (a collection of letters), or a telephone directory (a mapping of names to phone numbers)." Next, we will give a brief description of the concept, purpose and operations of each structure, followed by an example of its implementation in Java. array

It is a linear structure where homogeneous data is stored in continuous memory spaces. Access to each element is done through an index. As part of the modernization that Java has been going through, the language organizers have added utility classes to the Collections Framework that follow the naming scheme: Array -> Arrays, Collection -> Collections, File -> Files (ok, here we're not talking about files, but you got the idea, right?). Code example:

                    1class ArrayDemo {
                        2	public static void main(String[] args) {
                        3		int[] arrayInteiros = new int[5];//declara um array de 5 posições, vazio
                        4		int[] numeros = {2,3,1,5,4};//um array com os elementos já preenchidos
                        5		System.out.println(numeros.length);//informa o tamanho do array, ou seja, 5
                        6		System.out.println(numeros[0]);//vai imprimir "2"
                        7		Arrays.sort(numeros);//ordena o array 
                        8		System.out.println(Arrays.toString(numeros));//imprime cada um dos elementos
                        9	}

Linked List There is a "root" element, so each element is linked to another. The size is dynamic and the list can be "spread" across memory. This structure is often overlooked because of its similarities to ArrayList (the Java interface java.util.List implemented as an array). However, the main advantage lies in dynamically sized lists that tend to grow as needed. While in the best case of the addition operation, both have O(1) cost (in Big O notation - ), if it is necessary to resize the array, the cost will be O (log(n)) .

                        1class LinkedListDemo {
                            2	public static void main(String[] args) {
                            3		LinkedList linkedList = new LinkedList<>(List.of("maçã", "uva", "banana"));//cria uma nova lista encadeada 
                            4		linkedList.push("laranja");//adiciona ao início
                            5		String headElement = linkedList.poll();//remove o elemento da frente
                            6		System.out.println("Removido: " + headElement);//imprime "Removido: laranja"
                            7		String collect =", "));//ordena e junta numa string separada por vírgula
                            8		System.out.println(collect);//imprime "banana, maçã, uva"
                            9	}

stack Represents a stack (like a deck of cards or stacked books), following the LIFO algorithm. The four main operations are: push(e) - inserts an element on top; pop() - removes the element from the top; isEmpty() - tells true/false if the stack is empty; peek() - accesses the top element (without removing). This structure is often used for representations of state or navigation history, where the most recent is always on top.

                        1class StackDemo {
                            2	public static void main(String[] args) {
                            3		Stack history = new Stack<>();
                            4		history.push("Algoritmos");
                            5		history.push("Estruturas de Dados");  
                            6		history.push("Java");  
                            7		System.out.println("Topo: " + history.peek());  
                            8		String collect = String.join(", ", history);  
                            9		System.out.println("Todos: "+ collect);
                            10	}

set Represents a group of unique, non-repeating homogeneous data. Therefore, there must be a way to compare the elements in order to decide if they are the same or not. In Java, this comparison is done by the equals and hashcode methods . The main classes that implement the Set interface are: HashSet , TreeSet and LinkedHashSet .

1class SetDemo {
2	public static void main(String[] args) {
3		Set setFrutas = new HashSet<>(List.of("maçã", "uva", "banana"));  
4		setFrutas.add("abacaxi");  
5		setFrutas.add("abacaxi"); //não adiciona o elemento repetido
6		String collect = String.join(", ", setFrutas); 
7		System.out.println("Todos: "+ collect);//Todos: banana, uva, maçã, abacaxi
8	}

HashMap Use hash functions to determine the position of each element. A hash function is an algorithm that maps variable-length input data to fixed-length data. Thus, each element to be inserted in the structure has its address calculated. This avoids "collisions" and speeds up read operations. In the following code, we will count the occurrence of each character in the phrase "Java data structures", disregarding the blanks. The key of our map, key , will be the character and the value, value , will be the counter. As expected, the output of the program will be "a: 4, r: 2, s: 3, t: 2, d: 3, e: 2, u: 2, v: 1, j: 1, o: 1".

1class HashMapDemo {
2	public static void main(String[] args) {
3		HashMap charCountMap = new HashMap<>();  
4		String demo = "estruturas de dados java";  
5		for (char c : demo.toCharArray()) {  
6		    if (charCountMap.containsKey(c)) {  
7		        charCountMap.put(c, charCountMap.get(c) + 1);  
8		  } else {  
9		        charCountMap.put(c, 1);  
10		  }  
11		}  
12		String collect = charCountMap.entrySet().stream()  
13		    .filter(Predicate.not(entry -> entry.getKey().equals(' ')))
14		    .map(entry -> entry.getKey() + ": " + entry.getValue())  
15		    .collect(Collectors.joining(", "));  
16		System.out.println(collect);
17	}

In software development we need to represent sets of data. The discipline of Computer Science studies the best way to structure this information is called Data Structure. They are defined according to the nature of the data and the most common operations intended. In Java, data structures are available in the Java Collection Framework. In this article we discuss what should be in the repertoire of a good Java programmer: Array, Linked List, Set, Stack and HashMap. If you are interested in Data Structure, check out our courses and follow our blog for more Java tips!