Java Collections: ArrayList and HashMap
ProgrammingLesson 6 of 65 min read
What you'll learn
- Use ArrayList to store and manipulate ordered lists of objects
- Use HashMap to look up values by key, including counting patterns
- Explain generics and why
List<int>is not allowed - Choose the right collection for a task and avoid common runtime exceptions
On this page
Arrays have a fixed size, which makes them awkward for real data like a shopping cart that grows and shrinks. Java's collections framework provides resizable, feature-rich containers, and two of them, ArrayList and HashMap, cover a large share of everyday code and coding-interview solutions. This lesson shows how to use both and how to decide between them.
Generics: telling a collection what it holds
Collections are generic. The angle brackets state the element type: List<String> is a list of strings. The compiler then rejects anything else, and you never need to cast when reading values back. Generics work only with objects, so for numbers you use wrapper classes: List<Integer>, List<Double>, List<Boolean>. Writing List<int> is a compile error. Java automatically converts between int and Integer, which is called boxing and unboxing.
ArrayList: an ordered, resizable list
An ArrayList keeps items in insertion order, allows duplicates and gives fast access by index. By convention you declare the variable with the interface type List and create an ArrayList: this keeps your code flexible if you later swap implementations. Import it from java.util.
import java.util.ArrayList;
import java.util.List;
public class ListDemo {
public static void main(String[] args) {
List<String> cart = new ArrayList<>();
cart.add("Keyboard");
cart.add("Mouse");
cart.add("Monitor");
cart.add(1, "USB Hub");
System.out.println(cart);
System.out.println(cart.size());
System.out.println(cart.get(0));
System.out.println(cart.contains("Mouse"));
System.out.println(cart.indexOf("Monitor"));
cart.set(0, "Mechanical Keyboard");
cart.remove("Mouse");
cart.remove(0);
System.out.println(cart);
for (String item : cart) {
System.out.println("- " + item);
}
List<Integer> scores = new ArrayList<>(List.of(55, 80, 92, 38));
scores.removeIf(s -> s < 40);
int total = 0;
for (int s : scores) {
total += s;
}
System.out.println(scores + " total=" + total);
}
}Output
[Keyboard, USB Hub, Mouse, Monitor] 4 Keyboard true 3 [USB Hub, Monitor] - USB Hub - Monitor [55, 80, 92] total=227
Follow the cart. After the inserts it is [Keyboard, USB Hub, Mouse, Monitor]. set(0, ...) replaces the first item, remove("Mouse") removes by value, and then remove(0) removes by index, which deletes the renamed keyboard, leaving [USB Hub, Monitor]. Note that scores.removeIf(...) takes a lambda (s -> s < 40), a short inline function, and removes every matching element safely.
HashMap: look things up by key
A HashMap<K, V> stores key-value pairs and finds a value from its key in constant time on average, no matter how many entries it holds. Keys are unique: putting an existing key replaces the old value. A missing key returns null, so getOrDefault is often safer. A HashMap makes no promise about iteration order. Use LinkedHashMap to keep insertion order or TreeMap to keep keys sorted.
import java.util.HashMap;
import java.util.Map;
public class MapDemo {
public static void main(String[] args) {
Map<String, Integer> stock = new HashMap<>();
stock.put("apple", 50);
stock.put("banana", 30);
stock.put("apple", 45);
System.out.println(stock.get("apple"));
System.out.println(stock.get("mango"));
System.out.println(stock.getOrDefault("mango", 0));
System.out.println(stock.containsKey("banana"));
System.out.println(stock.size());
stock.put("cherry", 10);
stock.remove("banana");
for (Map.Entry<String, Integer> e : stock.entrySet()) {
if (e.getKey().equals("apple")) {
System.out.println(e.getKey() + " -> " + e.getValue());
}
}
int units = 0;
for (int v : stock.values()) {
units += v;
}
System.out.println("Units: " + units);
}
}Output
45 null 0 true 2 apple -> 45 Units: 55
The second put("apple", 45) overwrote 50, which is why the first line prints 45 and the map has only 2 entries. We filtered the entry loop to apple on purpose. Because HashMap order is unspecified, printing every entry could appear in a different order on a different Java version, and your code should never depend on it.
ArrayList or HashMap: which one?
| Need | Use | Why |
|---|---|---|
| Ordered items, access by position | ArrayList | Fast get(index) and iteration in insertion order |
| Look up by an id, name or other key | HashMap | Average constant-time get and containsKey |
| Count occurrences of things | HashMap<T, Integer> | Key is the item, value is the count |
| Check whether an item was already seen | HashSet or HashMap | Fast membership tests, unlike list.contains which scans |
| Keys must stay sorted | TreeMap | Keeps keys in order, with slower operations than HashMap |
Interview-style patterns
Three patterns appear again and again: counting frequencies, finding a pair that adds to a target, and removing duplicates while keeping order. All three are a loop plus a HashMap. The program below uses a TreeMap for the word count only so that the printed order is predictable.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
public class Interview {
static Map<String, Integer> wordCount(String text) {
Map<String, Integer> counts = new TreeMap<>();
for (String word : text.toLowerCase().split("\\s+")) {
counts.put(word, counts.getOrDefault(word, 0) + 1);
}
return counts;
}
static int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> seen = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int need = target - nums[i];
if (seen.containsKey(need)) {
return new int[]{seen.get(need), i};
}
seen.put(nums[i], i);
}
return new int[]{};
}
static List<Integer> removeDuplicates(int[] nums) {
List<Integer> unique = new ArrayList<>();
Map<Integer, Boolean> seen = new HashMap<>();
for (int n : nums) {
if (seen.putIfAbsent(n, true) == null) {
unique.add(n);
}
}
return unique;
}
public static void main(String[] args) {
System.out.println(wordCount("the cat and the hat and the bat"));
System.out.println(Arrays.toString(twoSum(new int[]{2, 7, 11, 15}, 9)));
System.out.println(removeDuplicates(new int[]{4, 2, 4, 9, 2}));
}
}Output
{and=2, bat=1, cat=1, hat=1, the=3}
[0, 1]
[4, 2, 9]twoSum is the key idea: instead of checking every pair (slow), remember each number you have seen with its index, and for each new number ask "have I already seen the value I need?". One pass, one map. That trade of extra memory for speed is the core of many interview solutions. For a plan on practising these, read coding interview prep for self-taught developers.
Common mistakes
- Primitive type in generics.
List<int> numsfails witherror: unexpected type; required: reference, found: int. UseList<Integer>. - Reading past the end.
cart.get(5)on a four-item list throwsjava.lang.IndexOutOfBoundsException: Index 5 out of bounds for length 4. - Removing while iterating. Calling
list.remove(...)inside an enhanced for loop throwsjava.util.ConcurrentModificationException. UseremoveIfor anIterator. - Unboxing a missing key.
int n = map.get("mango");where the key is absent throwsNullPointerException, becausenullcannot become anint. UsegetOrDefault. - Immutable lists.
List.of(1, 2, 3).add(4)throwsUnsupportedOperationException. Wrap it innew ArrayList<>(...)if you need to modify it. - Using mutable objects as keys. Changing a key object after inserting it can make the entry impossible to find again. Prefer immutable keys such as
StringorInteger.
How this shows up in interviews and real projects
Many array and string problems in screening rounds are solved cleanly with a HashMap, and interviewers often ask follow-ups such as "what is the time complexity of get?" or "what happens when two keys collide?". In production code, lists hold query results and request payloads, and maps serve as in-memory caches and lookup tables. When you are ready, put your skills to the test with real Java roles on our jobs board.
Try it yourself
Build an inventory tracker. Use a Map<String, Integer> to store product names and quantities. Write methods addStock(name, qty), sell(name, qty) (return false if there is not enough stock) and lowStock(threshold) that returns a List<String> of products below the threshold. Test them from main.
Show a hint
Use getOrDefault(name, 0) in addStock and sell, and loop over entrySet() in lowStock, adding matching keys to a new ArrayList.
Key takeaways
- Collections are generic: write
List<String>orMap<String, Integer>, and use wrapper types likeIntegerinstead of primitives. ArrayListis for ordered data accessed by index;HashMapis for fast lookups by key.- HashMap order is not guaranteed; use
LinkedHashMaporTreeMapwhen order matters. - Use
getOrDefault,removeIfandputIfAbsentto avoid null checks and modification errors. - Counting and "have I seen this before?" problems are usually a loop plus a HashMap.
Test yourself
A trick from this lesson's ride: Angle brackets take objects only: int becomes Integer, double becomes Double. Four more tricks like it wait along the route, each followed by a question.
Frequently asked questions
What is the difference between ArrayList and HashMap in Java?
An ArrayList stores elements in order and accesses them by numeric index, while a HashMap stores key-value pairs and retrieves a value by its key. Use a list for ordered sequences and a map when you need fast lookup by an identifier.
Why can't I use int in an ArrayList in Java?
Generics work only with reference types, so ArrayList<int> is a compile error. Use the wrapper class Integer instead. Java automatically converts between int and Integer, so list.add(5) and int x = list.get(0) still work.
How does a HashMap work internally in Java?
A HashMap computes a hash code from the key and uses it to choose a bucket in an internal array, then compares keys with equals() to find the entry. This gives average constant-time get and put. Keys that land in the same bucket are chained, and heavily loaded buckets are converted to trees in modern Java versions.