These ten questions explain collection ordering, element uniqueness, and the tradeoffs among common Java SE 25 collection implementations.
Answer: A class defines its natural ordering by implementing Comparable<T> and its compareTo method. The result is negative, zero, or positive when the receiver is less than, equivalent to, or greater than the other value in that ordering. It need not be exactly -1 or 1.
For example, Integer uses numerical ordering. String compares lexicographically using UTF-16 code units; this is case-sensitive and is not necessarily a language's dictionary order. Use a Comparator for a different ordering, or a suitably configured Collator for linguistic comparisons. Avoid implementing numerical comparisons by subtraction, which can overflow.
Answer: There is no fixed number. The JDK provides several implementations, and applications and libraries can provide more. Common choices include ArrayList, LinkedList, and java.util.concurrent.CopyOnWriteArrayList. Legacy Vector and Stack also implement List; new stack-style code usually uses a Deque.
Factory methods introduce important behavioral differences: List.of(...) creates an unmodifiable list and rejects null elements. Arrays.asList(array) returns a fixed-size list backed by the array: elements can be replaced, but not added or removed. Choose by the required operations, mutability, and concurrency behavior rather than memorizing an implementation count.
Answer: ArrayList uses a resizable array. Indexed reads are constant time, and appending is amortized constant time. Inserting or removing near the beginning usually shifts subsequent elements. LinkedList is doubly linked; finding an indexed position takes linear time, although insertion or removal through an iterator already at that position can update links in constant time.
Thus, âLinkedList is faster for insertionâ is incomplete: locating the position may dominate the work. Node allocation also increases memory overhead. ArrayList is often a useful default for ordinary lists; measure the actual workload. For a queue or stack that does not require indexed access, consider ArrayDeque. Neither ArrayList nor LinkedList supplies general thread safety.
Answer: The general Set contract defines duplicates using equality: a set contains no pair of distinct elements for which equals returns true. Hash-based sets use hashCode to locate candidates and equals to distinguish them. Equal objects must have equal hash codes; a matching hash code alone does not establish equality.
Sorted sets determine equivalence through their ordering: a comparison result of zero prevents a second element from being added. Keep that ordering consistent with equals to satisfy the general Set contract. Do not mutate fields involved in equality, hashing, or ordering while an element is stored in a set; remove it, change it, and add it again.
Answer: HashSet prevents duplicate elements using hashing and equality, but guarantees no iteration order. Apparent insertion or numerical order in a small example is accidental and must not become an application dependency. Basic add, remove, and contains operations have expected constant-time performance when hashes are well distributed.
A HashSet permits one null element. It is not synchronized. Use LinkedHashSet when encounter order matters, TreeSet when sorted order matters, or an appropriate concurrent set when threads modify shared contents. Fail-fast iteration is a best-effort bug detector, not a thread-safety mechanism.
Answer: LinkedHashSet combines hash-based membership with a linked encounter order. Ordinary add appends a new element; adding an element already present does not move it. Removing an element and adding it again places it at the end.
In Java SE 25 it also implements SequencedSet. Operations such as addFirst and addLast explicitly position elements, including repositioning existing ones. reversed() provides a reverse-order view, not an independent copy. Its ordering is therefore predictable but is not an automatic sort.
Answer: TreeSet implements NavigableSet, which extends SortedSet. It uses either the elements' natural ordering or the Comparator supplied to its constructor. Basic add, remove, and contains operations take logarithmic time. Navigation methods such as floor and ceiling find nearby values in that ordering.
A comparison result of zero means the set considers the elements equivalent, even if equals disagrees. For example, a case-insensitive string comparator treats "Java" and "JAVA" as one element. Natural ordering rejects null; a custom comparator can support it explicitly.
import java.util.LinkedHashSet;
import java.util.List;
import java.util.TreeSet;
public class SetOrders {
public static void main(String[] args) {
var insertionOrder = new LinkedHashSet<String>();
insertionOrder.addAll(List.of("beta", "alpha", "beta"));
System.out.println(insertionOrder);
var sorted = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
sorted.addAll(List.of("Java", "JAVA", "Kotlin"));
System.out.println(sorted);
}
}
The output is [beta, alpha], followed by [Java, Kotlin]. Each set retains only two elements, for different ordering reasons.
Answer: It depends on the implementation. HashMap uses hashing and equals. TreeMap uses its ordering: keys comparing as zero identify the same mapping, so an ordering consistent with equals is important. IdentityHashMap deliberately uses reference identity, ==, instead of logical equality and is intended for specialized use.
With an ordinary HashMap, replacing a value using an equal key updates the existing mapping rather than adding another key. Different keys may map to equal values. Keys should retain stable equality and hash codes while stored; an immutable key such as String avoids many accidental lookup failures.
Answer: HashMap is an unsynchronized hash-table implementation of Map. It permits one null key and null values, guarantees no iteration order, and normally provides constant-time get and put operations when hashes are well distributed. Resizing and poor hash distribution affect performance; constant time is not an unconditional guarantee for every call.
Because get can return null for either an absent mapping or a mapped null value, use containsKey when that distinction matters. For shared mutable access, choose a suitable synchronization strategy or ConcurrentHashMap. The latter rejects null keys and values and offers atomic per-key operations such as compute and merge.
Answer: HashMap permits nulls and does not synchronize its operations. Hashtable rejects null keys and values and synchronizes its ordinary operations. Hashtable predates the collections framework but was retrofitted to implement Map and is part of that framework today.
Synchronization of individual methods does not automatically make a sequence such as âcheck, then putâ atomic. For new concurrent code, ConcurrentHashMap often provides more suitable concurrency and compound operations. For a map used by one thread or protected by an external lock, HashMap is usually sufficient. Neither implementation promises iteration order.
References: Java SE 25 collection APIs, LinkedHashSet, and Hashtable.