Collections ·
‹ Previous Next ›
⏱ 5 min read Modified: 2026-10-22

Data Structures in Java: List, Stack, Queue and Set

Push 1, 2 and 3 onto a java.util.Stack and print it: you get [1, 2, 3]. Do the same with an ArrayDeque and you get [3, 2, 1]. Both are used as stacks, yet the output is reversed. To avoid this kind of confusion, learn the data structures themselves first, and only then the Java classes that implement them.

A data structure is a way to organize a group of elements together with rules for accessing them: by index, only the most recently added element, only the oldest one, or without duplicates. The basic data structures in Java fall into four kinds: the list, the stack, the queue and the set. The map (dictionary) for key–value pairs stands apart. All of them are implemented in the Collections Framework, whose interfaces and classes are covered in the lesson Java Collections Framework.

List

A list is an ordered sequence of elements in which every element has an index (its position, starting from 0) and the same value may appear more than once. You can read any element by its index, insert a new element at any position, or remove one.

A list is also called a sequence. The abstract list says nothing about how elements are stored. Java has two main implementations: ArrayList keeps elements in an internal array, while LinkedList keeps them in nodes, each referring to the next and the previous element. That difference makes get(i) fast in one and slow in the other — see the performance table in Choosing an implementation.

In the diagram below, the letters A, B, C, A, A are added to a list. The letter A appears three times, which a list allows. Each letter is marked with its index.

List data structure diagram: elements A, B, C, A, A with indexes 0 to 4

Stack (LIFO)

A stack is a data structure that removes elements in Last-In-First-Out (LIFO) order: the element added last comes out first. Only the top element is accessible, and both adding (push) and removing (pop) happen at the same end. A stack allows duplicate elements.

Think of a stack of plates. The top plate was put on last (Last-In), but it is the first one you can take (First-Out). The bottom plate went in first and comes out only after all the plates above it are removed. You cannot pull a plate out of the middle without lifting the ones on top.

The JVM call stack works the same way: the method called last finishes first. Typical uses of a stack are undo history, checking that brackets are balanced, and depth-first search.

Stack data structure diagram: elements are pushed onto and popped from the top (LIFO)

In Java, a stack is a Deque, not Stack

The java.util.Stack class dates back to Java 1.0 and extends Vector: all its methods are synchronized, and the inherited get(i) and add(i, e) let you reach into the middle of the stack, which breaks the LIFO rule itself. That is also why it prints from bottom to top, like a list. The Javadoc of Stack recommends the Deque interface instead: Deque<Integer> stack = new ArrayDeque<>();. An ArrayDeque pushes to its head, so it prints from top to bottom.

Queue (FIFO)

A queue is a data structure that removes elements in First-In-First-Out (FIFO) order: elements are added at the tail (enqueue) and taken from the head (dequeue). As a result, elements leave the queue in the same order in which they were added.

Like a stack, a queue gives no access to an arbitrary element — only to its ends. The difference is which ends: a stack adds and removes at the same end, a queue at opposite ends, just like a line at a checkout or items on a conveyor belt. A queue allows duplicates. Queues are used for work processed in arrival order: print jobs, incoming requests, breadth-first search.

Queue data structure diagram: elements are added at the tail and removed from the head (FIFO)

In Java, a queue is described by the Queue interface, and a double-ended queue, which can also work as a stack, by Deque. Its usual implementations are ArrayDeque and LinkedList. A special kind of queue, where the element that comes out first is the one with the highest priority rather than the oldest one, is PriorityQueue.

Set

A set is a collection of elements without duplicates: each element occurs in it at most once, and elements have no indexes. The main operation of a set is a fast check whether it contains an element; adding an element that is already there changes nothing.

A good example of a set is the cars in a parking lot: every car has a unique licence plate, two cars with the same plate cannot be there at once, and the order in which they are parked does not matter.

Set data structure diagram: unique elements without indexes

The abstract set is unordered, but Java also has implementations with an order: HashSet does not guarantee any order, LinkedHashSet keeps insertion order, and TreeSet keeps its elements sorted. How a HashSet decides that two objects are equal depends on equals() and hashCode().

Map (dictionary)

A map (also called a dictionary or associative array) is a data structure that stores key–value pairs: keys are unique, like the elements of a set, and a value is found by its key rather than by an index. A phone book is a map: you look up a number by a name.

In Java, a map is described by the Map interface with the HashMap, LinkedHashMap and TreeMap implementations. Map is a separate branch of the collection hierarchy and does not extend Collection.

Java data structures compared

Java data structures differ in three properties: which elements you can access, whether duplicates are allowed, and whether elements have indexes. These properties tell you which Java interface and class fit a task.

Structure Access rule Duplicates Indexes Java interface Main classes
List Any element by index Yes Yes List ArrayList, LinkedList
Stack Only the most recently added (LIFO) Yes No Deque ArrayDeque
Queue Only the oldest element (FIFO) Yes No Queue, Deque ArrayDeque, LinkedList, PriorityQueue
Set Membership check No No Set HashSet, LinkedHashSet, TreeSet
Map Value by key Keys: no; values: yes No (a key instead of an index) Map HashMap, LinkedHashMap, TreeMap

Which implementation to use by default and how fast each class performs its operations in Big O notation is shown in the table Choosing an implementation.

The same data in four structures

Add the same letters A, B, C, A, D to a list, a stack, a queue and a set, and each structure gives the data back in its own way: the list by index, the stack from the end, the queue from the beginning, and the set simply rejects the duplicate. What does this code print?

import java.util.*;

public class DataStructuresDemo {
    public static void main(String[] args) {
        String[] letters = {"A", "B", "C", "A", "D"};

        List<String> list = new ArrayList<>();
        Deque<String> stack = new ArrayDeque<>();
        Queue<String> queue = new ArrayDeque<>();
        Set<String> set = new HashSet<>();

        for (String s : letters) {
            list.add(s);     // to the end of the list
            stack.push(s);   // onto the top of the stack
            queue.offer(s);  // to the tail of the queue
            set.add(s);      // the second "A" is ignored
        }

        System.out.println("List: " + list + ", get(3) = " + list.get(3));
        System.out.println("Stack: pop() = " + stack.pop() + ", then " + stack.pop());
        System.out.println("Queue: poll() = " + queue.poll() + ", then " + queue.poll());
        System.out.println("Set: size() = " + set.size() + ", add(\"A\") = " + set.add("A"));
    }
}

Output:

List: [A, B, C, A, D], get(3) = A
Stack: pop() = D, then C
Queue: poll() = A, then B
Set: size() = 4, add("A") = false

The list keeps all five letters, including the duplicate. The stack returns the last added D and C, the queue returns the first added A and B. The set holds four elements: the second A was never added, and another add("A") returns false. On an empty stack or queue, pop() throws NoSuchElementException, while poll() returns null.

Frequently Asked Questions

What is the difference between a list and an array in Java?

An array gets its size when it is created and never changes it, while a list grows and shrinks as you add and remove elements. An array can hold primitives (int[]), but a Java list holds only objects, so you write List<Integer> with a wrapper class. Inside an ArrayList there is a plain array that is replaced by a larger one when it fills up.

What other data structures are there besides list, stack, queue and set?

Common ones are the hash table (behind HashSet and HashMap), the tree (a red-black tree inside TreeSet and TreeMap), the binary heap (PriorityQueue) and the graph. The Java standard library has no ready-made graph class: a graph is usually built as a Map from each vertex to a list of its neighbours.

How can one collection be both a stack and a queue?

A double-ended queue (deque) lets you add and remove elements at both ends. Use only one end (push()/pop()) and you get a stack; add at the tail and take from the head (offer()/poll()) and you get a queue. That is why ArrayDeque replaces both the Stack class and a plain queue. See the example in The same data in four structures.

Which data structure should I use for my task?

Undo history — a stack; jobs processed in arrival order — a queue; only unique values (for example, site visitors) — a set; access by position or keeping duplicates — a list; lookup by key (login → user) — a map. The properties are summarized in Java data structures compared.

Comments

Please log in or register to have a possibility to add comment.