This collection of 30 Java ArrayList exercises covers the full lifecycle of working with a list: creating and iterating, inserting and removing, searching and sorting, and combining or splitting lists.
- Early exercises cover the three main iteration styles, indexed insertion and removal, safe retrieval with exception handling, and sorting in both ascending and descending order.
- The middle set covers copying, shuffling, manual reversal, sublists, array conversion in both directions.
- The final exercises tackle more advanced problems: deduplication with and without a
Set, finding common elements, a frequency counter, splitting a list by condition, merging two sorted lists, the sliding window technique, and sorting custom objects with aComparator.
Each exercise includes a Problem Statement, Purpose, Hint, and a Solution with Explanation, with an alternative approach noted wherever a more modern or concise option exists.
- Also, See: Java Exercises with over 20+ topic-wise sets and 575+ coding questions to practice.
- Practice questions using our Online Java Compiler
+ Table of Contents (30 Exercises)
Table of contents
- Exercise 1: Creation and Initialization
- Exercise 2: Iterating Elements
- Exercise 3: Insert at First Position
- Exercise 4: Retrieve an Element
- Exercise 5: Update an Element
- Exercise 6: Remove an Element
- Exercise 7: Search for an Element
- Exercise 8: Check for Empty List
- Exercise 9: Sort Elements
- Exercise 10: Copy an ArrayList
- Exercise 11: Shuffle a List
- Exercise 12: Reverse Elements Manually
- Exercise 13: Extract a Sublist
- Exercise 14: Swap Two Elements
- Exercise 15: Join Two Lists
- Exercise 16: Clone an ArrayList
- Exercise 17: Array to ArrayList Conversion
- Exercise 18: ArrayList to Array Conversion
- Exercise 19: Replace Elements Conditionally
- Exercise 20: Filter Even Numbers
- Exercise 21: Trim Capacity
- Exercise 22: Compare Two Lists
- Exercise 23: Remove Duplicates (With Set)
- Exercise 24: Remove Duplicates (Without Set)
- Exercise 25: Find Common Elements
- Exercise 26: Frequency Counter
- Exercise 27: Split an ArrayList
- Exercise 28: Merge Sorted Lists
- Exercise 29: Find Continuous Sublist Sum
- Exercise 30: Custom Object Sorting
Exercise 1: Creation and Initialization
Problem Statement: Create an ArrayList of Strings, add five names of your favorite programming languages, and print the entire list to the console.
Purpose: This exercise helps you practice basic ArrayList creation and the add() method, foundational for working with dynamic, resizable collections in Java.
Given Input: Add “Java”, “Python”, “JavaScript”, “C++”, and “Go” to a new ArrayList<String>.
Expected Output: Languages = [Java, Python, JavaScript, C++, Go]
▼ Hint
- Import
java.util.ArrayListbefore using the class. - Declare the list using
ArrayList<String>and instantiate it withnew ArrayList<>(). - Use the
add()method to append each language one at a time. - Print the entire list directly; Java’s
ArrayListalready provides a readabletoString()format.
▼ Solution & Explanation
Explanation:
new ArrayList<>(): Creates an empty, resizable list that can grow as elements are added, unlike a fixed-size array.languages.add("Java"): Appends each element to the end of the list, one call per language.System.out.println("Languages = " + languages): Relies onArrayList‘s built-intoString()method, which automatically formats the list as comma-separated values inside square brackets.- Alternative: You could use
List.of("Java", "Python", ...)combined withnew ArrayList<>(...)to initialize the list in a single line, though it creates an intermediate immutable list first.
Exercise 2: Iterating Elements
Problem Statement: Write a program to iterate through all elements in an ArrayList using three different methods: a standard for loop, an enhanced for-each loop, and an Iterator.
Purpose: This exercise helps you practice the three most common iteration patterns in Java, and understand when each one is useful.
Given Input: fruits = {"Apple", "Banana", "Cherry"}
Expected Output:
Standard for: Apple Banana Cherry For-each: Apple Banana Cherry Iterator: Apple Banana Cherry
▼ Hint
- For the standard for loop, use
get(i)alongsidesize()to access elements by index. - For the for-each loop, iterate directly over the list without needing an index variable.
- For the Iterator, call
iterator()on the list, then usehasNext()andnext()inside a while loop. - Print each element as you go so you can compare the output of all three approaches.
▼ Solution & Explanation
Explanation:
for (int i = 0; i < fruits.size(); i++): Uses an index to access elements directly withget(i), giving full control over the position being read.for (String fruit : fruits): Iterates over each element automatically without managing an index, making the code more concise for simple traversal.Iterator<String> it = fruits.iterator(): Creates an explicit iterator object, useful when you need to remove elements safely during iteration withit.remove().- Alternative: You could use
fruits.forEach(fruit -> System.out.print(fruit + " "))with a lambda expression for a fourth, more modern iteration style.
Exercise 3: Insert at First Position
Problem Statement: Create an ArrayList of integers, add a few elements, and then insert a new integer at the first position (index 0).
Purpose: This exercise helps you practice the indexed add() overload for inserting elements at a specific position rather than appending to the end.
Given Input: numbers = {20, 30, 40}, then insert 10 at index 0.
Expected Output: Numbers = [10, 20, 30, 40]
▼ Hint
- Start by adding a few integers to the list using the regular
add()method, which appends to the end. - Use the overloaded
add(index, element)method to insert at a specific position instead of the end. - Passing index 0 shifts every existing element one position to the right to make room.
- Print the list afterward to confirm the new element is now first.
▼ Solution & Explanation
Explanation:
numbers.add(20): Appends elements to the end of the list in the order they are added.numbers.add(0, 10): Uses the two-argument overload ofadd()to insert10at index 0, pushing all other elements one position later.- Automatic resizing: The
ArrayListinternally shifts elements and grows its backing array as needed, so you don't have to manage array indices manually. - Alternative: You could rebuild the list with the new element first by creating a new
ArrayListand adding elements in the desired order, though the indexedadd()is far simpler for a single insertion.
Exercise 4: Retrieve an Element
Problem Statement: Retrieve and print the element at a specific index (e.g., index 3) from an existing ArrayList. Handle cases where the index might be out of bounds.
Purpose: This exercise helps you practice safe element retrieval using try-catch, since accessing an invalid index throws an exception rather than returning null.
Given Input: colors = {"Red", "Green", "Blue"}, retrieve index 3
Expected Output: Index 3 is out of bounds for this list.
▼ Hint
- Use
get(index)to retrieve an element from the list at the specified position. - Wrap the retrieval in a try-catch block to handle an invalid index gracefully.
- Catch
IndexOutOfBoundsException, which is the exceptionArrayListthrows for invalid indices. - Print a friendly error message inside the catch block instead of letting the program crash.
▼ Solution & Explanation
Explanation:
colors.get(index): Attempts to retrieve the element at the given position, throwing an exception if the index is invalid.catch (IndexOutOfBoundsException e): Catches the specific exceptionArrayListthrows when an index is negative or greater than or equal to the list's size.- Graceful error handling: Prevents the program from terminating abruptly, instead giving the user a clear explanation of what went wrong.
- Alternative: You could check
index >= 0 && index < colors.size()before callingget(), avoiding the exception entirely, though try-catch is useful when the check itself is easy to forget.
Exercise 5: Update an Element
Problem Statement: Update a specific element in a list of colors (e.g., change "Red" to "Crimson") and display the updated list.
Purpose: This exercise helps you practice the set() method for replacing an element at a known position without removing and re-adding it.
Given Input: colors = {"Red", "Green", "Blue"}, update "Red" to "Crimson"
Expected Output: Updated Colors = [Crimson, Green, Blue]
▼ Hint
- Locate the index of the element you want to change, either by knowing it in advance or using
indexOf(). - Use the
set(index, element)method to replace the element at that position. - Unlike
add(),set()overwrites the existing element rather than shifting others. - Print the list afterward to confirm the update took effect.
▼ Solution & Explanation
Explanation:
colors.indexOf("Red"): Locates the position of the element to replace without hardcoding an index number.colors.set(index, "Crimson"): Replaces the element at the found index with the new value, leaving the size of the list unchanged.set()versusadd():set()overwrites an existing position, whileadd(index, element)would instead insert a new element and shift everything else.- Alternative: You could loop through the list checking each element with
equals()and replace it manually, butset()combined withindexOf()is more direct.
Exercise 6: Remove an Element
Problem Statement: Remove the third element (index 2) from an ArrayList of doubles and print the list to confirm the removal.
Purpose: This exercise helps you practice the indexed remove() method, and understand the difference between removing by index versus by value.
Given Input: values = {1.5, 2.5, 3.5, 4.5}, remove index 2
Expected Output: Values = [1.5, 2.5, 4.5]
▼ Hint
- Use the
remove(int index)overload to remove an element by its position rather than its value. - Be careful with
Integerwrapper types, sinceremove(Integer)would instead try to remove a matching value. - After removal, all later elements shift one position earlier to fill the gap.
- Print the list afterward to confirm the correct element was removed.
▼ Solution & Explanation
Explanation:
values.remove(2): Uses theintoverload ofremove(), which removes the element at index 2 (the third element) rather than searching for a matching value.- Element shifting: After removal, elements that came after index 2 move one position earlier, keeping the list contiguous.
intversusIntegeroverload:remove(int index)removes by position, whileremove(Object o)removes by matching value, which is an easy source of bugs withIntegerlists specifically.- Alternative: You could use
values.remove(Double.valueOf(3.5))to remove by value instead of position, though it requires knowing the exact value in advance.
Exercise 7: Search for an Element
Problem Statement: Search for a user-specified string within an ArrayList. If it exists, return its index; otherwise, print a "Not Found" message.
Purpose: This exercise helps you practice the contains() and indexOf() methods for locating elements within a list.
Given Input: items = {"Pen", "Notebook", "Eraser"}, search for "Notebook"
Expected Output: Found "Notebook" at index 1.
▼ Hint
- Use
contains()to first check whether the target element exists in the list at all. - If it exists, use
indexOf()to retrieve its position. - If
contains()returns false, skip the lookup and print a "Not Found" message instead. - Remember that both methods rely on
equals()to compare elements, which works well for Strings.
▼ Solution & Explanation
Explanation:
items.contains(target): Checks whether the target string exists anywhere in the list, returning a simple boolean.items.indexOf(target): Returns the position of the first matching element, only called after confirming the element exists.- String comparison: Both methods use
equals()internally, correctly comparing the contents of Strings rather than their memory references. - Alternative: You could skip the
contains()check and rely solely onindexOf(), treating a return value of -1 as "not found," which avoids scanning the list twice.
Exercise 8: Check for Empty List
Problem Statement: Create an ArrayList, add a few items, clear the list completely using a built-in method, and verify whether the list is empty.
Purpose: This exercise helps you practice the clear() and isEmpty() methods for resetting and checking a list's state.
Given Input: numbers = {1, 2, 3}, then call clear()
Expected Output:
Before clear: Is Empty = false After clear: Is Empty = true
▼ Hint
- Add a few elements to the list first so it starts out non-empty.
- Check and print the result of
isEmpty()before clearing, to establish a baseline. - Call
clear()to remove all elements from the list at once. - Check and print
isEmpty()again afterward to confirm the list is now empty.
▼ Solution & Explanation
Explanation:
numbers.isEmpty(): Returns true only when the list contains zero elements, providing a cleaner check than comparingsize()to 0.numbers.clear(): Removes every element from the list in a single call, resetting its size to zero without creating a new list object.- Before and after comparison: Demonstrates that
clear()actually empties the existing list rather than just reassigning the variable to a new empty list. - Alternative: You could reassign
numbers = new ArrayList<>()to achieve a similarly empty list, but that creates a new object instead of clearing the existing one, which matters if other references point to the original list.
Exercise 9: Sort Elements
Problem Statement: Write a program to sort a given ArrayList of integers in ascending order, and then in descending order.
Purpose: This exercise helps you practice Collections.sort() and using a custom Comparator for reverse order.
Given Input: numbers = {5, 3, 8, 1, 9}
Expected Output:
Ascending = [1, 3, 5, 8, 9] Descending = [9, 8, 5, 3, 1]
▼ Hint
- Use
Collections.sort(list)to sort the list in its natural ascending order. - Print the list after this first sort to confirm the ascending order.
- Use
Collections.sort(list, Collections.reverseOrder())to sort the same list in descending order. - Print the list again to confirm the order has been reversed.
▼ Solution & Explanation
Explanation:
Collections.sort(numbers): Sorts the list in place using the natural ordering ofIntegervalues, which is ascending numerical order.Collections.reverseOrder(): Provides aComparatorthat reverses the natural ordering, whichCollections.sort()then uses to sort in descending order.- In-place sorting: Both calls modify the same list object directly rather than returning a new sorted list.
- Alternative: You could use
numbers.sort(Comparator.reverseOrder())directly on the list instance instead of passing it throughCollections.sort(), sinceListgained asort()method in Java 8.
Exercise 10: Copy an ArrayList
Problem Statement: Create an ArrayList of strings, populate it, and copy all its elements into another freshly created ArrayList.
Purpose: This exercise helps you practice creating an independent copy of a list using a copy constructor, avoiding shared references between two lists.
Given Input: original = {"A", "B", "C"}
Expected Output: Copy = [A, B, C]
▼ Hint
- Create and populate the original
ArrayListfirst with a few elements. - Create a second
ArrayListby passing the original list into the constructor of the new one. - This constructor copies all elements into the new list, rather than making the new list reference the same underlying data.
- Print the new list to confirm it contains the same elements as the original.
▼ Solution & Explanation
Explanation:
new ArrayList<>(original): Uses the copy constructor, which creates a new list containing all the same elements as the original at the time of copying.- Independent lists: Since the constructor copies element references into a new backing array, modifying
copyafterward (like adding or removing elements) does not affectoriginal, and vice versa. - Shallow copy note: While the list itself is independent, if the elements were mutable objects rather than immutable Strings, both lists would still reference the same underlying objects.
- Alternative: You could use
copy.addAll(original)on an already-created empty list to achieve the same result, which is useful when the destination list already exists.
Exercise 11: Shuffle a List
Problem Statement: Randomly shuffle the elements in an ArrayList of integers so that they appear in a random order every time the program runs.
Purpose: This exercise helps you practice using Collections.shuffle() to randomize the order of a list in place.
Given Input: numbers = {1, 2, 3, 4, 5}
Expected Output:
Before = [1, 2, 3, 4, 5] Shuffled = [3, 1, 5, 2, 4] (order will vary on each run)
▼ Hint
- Import
java.util.Collectionsto access theshuffle()method. - Populate the
ArrayListfirst with the integers in a fixed order. - Call
Collections.shuffle(list)to randomize the element order in place. - Print the list before and after shuffling to observe the change; the exact result will differ each time you run the program.
▼ Solution & Explanation
Explanation:
Collections.shuffle(numbers): Randomly permutes the elements of the list in place using a default source of randomness.- Non-deterministic output: Since
shuffle()uses an internalRandominstance seeded by the current time by default, the resulting order differs on each program run. - In-place modification: The original list object is reordered directly rather than a new shuffled list being created.
- Alternative: You could pass a seeded
Randomobject, likeCollections.shuffle(numbers, new Random(42)), to get a reproducible shuffle order, which is useful for testing.
Exercise 12: Reverse Elements Manually
Problem Statement: Reverse the elements of an ArrayList without using the built-in Collections.reverse() method.
Purpose: This exercise helps you practice the two-pointer swap technique using get() and set(), a pattern also useful outside of lists.
Given Input: numbers = {1, 2, 3, 4, 5}
Expected Output: Reversed = [5, 4, 3, 2, 1]
▼ Hint
- Use two pointers, one starting at the beginning of the list and one at the end.
- Swap the elements at these two positions using the
set()method. - Move the pointers toward the center after each swap.
- Stop once the pointers meet or cross, since further swapping would just undo the work.
▼ Solution & Explanation
Explanation:
leftandright: Two pointers that start at opposite ends of the list and move toward each other.numbers.set(left, numbers.get(right)): Usesget()andset()together to swap the values at the two pointer positions without a built-in swap method.left++/right--: Advances both pointers toward the middle after each swap, ensuring the loop eventually terminates.- Alternative: You could build a brand new
ArrayListby iterating through the original from last to first and adding each element, though the two-pointer swap avoids creating extra objects.
Exercise 13: Extract a Sublist
Problem Statement: Extract a portion of an ArrayList (e.g., elements from index 2 to index 6) into a new sublist and print it.
Purpose: This exercise helps you practice the subList() method, and understand its inclusive-start, exclusive-end index convention.
Given Input: numbers = {10, 20, 30, 40, 50, 60, 70, 80}, extract indices 2 through 6
Expected Output: Sublist = [30, 40, 50, 60, 70]
▼ Hint
- Use the
subList(fromIndex, toIndex)method to extract a range of elements from the original list. - Remember that
fromIndexis inclusive whiletoIndexis exclusive, so pass one index higher than the last element you want. - Wrap the result in a
new ArrayList<>(...)constructor to get an independent copy rather than a live view of the original list. - Print the sublist to confirm it contains the intended elements.
▼ Solution & Explanation
Explanation:
numbers.subList(2, 7): Extracts elements from index 2 up to, but not including, index 7, capturing indices 2 through 6.new ArrayList<>(...): Wraps the returned view in a new list so the sublist is independent, sincesubList()by itself returns a live view backed by the original list.- Live view caveat: Without the copy constructor, structural changes to the original list (like adding or removing elements) could throw a
ConcurrentModificationExceptionon the view. - Alternative: You could manually loop from index 2 to 6 and add each element to a new
ArrayList, which avoids the live-view behavior entirely but requires more code.
Exercise 14: Swap Two Elements
Problem Statement: Write a Java program to swap two elements at specified positions in an ArrayList.
Purpose: This exercise helps you practice using Collections.swap(), a convenient built-in method for exchanging two elements by index.
Given Input: items = {"A", "B", "C", "D"}, swap indices 1 and 3
Expected Output: Swapped = [A, D, C, B]
▼ Hint
- Use
Collections.swap(list, i, j)to swap two elements by their positions in a single call. - This built-in method handles the temporary variable logic internally.
- Make sure both indices are valid positions within the list's current size.
- Print the list afterward to confirm the two elements traded places.
▼ Solution & Explanation
Explanation:
Collections.swap(items, 1, 3): Swaps the elements currently at index 1 and index 3, handling the exchange internally without needing a manual temporary variable.- In-place operation: The same list object is modified directly, with no new list created.
- Index validity: Both indices must fall within the current bounds of the list, or an
IndexOutOfBoundsExceptionwill be thrown. - Alternative: You could implement the swap manually using
get()andset()with a temporary variable, which is exactly whatCollections.swap()does internally.
Exercise 15: Join Two Lists
Problem Statement: Create two separate ArrayLists of strings and join/concatenate them into a single, combined ArrayList.
Purpose: This exercise helps you practice the addAll() method for merging the contents of multiple lists into one.
Given Input: listA = {"Apple", "Banana"}, listB = {"Cherry", "Date"}
Expected Output: Combined = [Apple, Banana, Cherry, Date]
▼ Hint
- Create and populate two separate
ArrayListsindependently. - Create a brand new destination list to hold the combined result.
- Use the
addAll()method twice, once for each source list, to append all their elements into the destination. - Print the combined list to confirm all elements are present in order.
▼ Solution & Explanation
Explanation:
combined.addAll(listA): Appends every element fromlistAto the end ofcombined, preserving their original order.combined.addAll(listB): Appends every element fromlistBimmediately afterlistA's elements.- New destination list: Using a separate
combinedlist keeps bothlistAandlistBunmodified, unlike callinglistA.addAll(listB)directly. - Alternative: You could use
Stream.concat(listA.stream(), listB.stream()).collect(Collectors.toList())for a more functional-style approach to merging.
Exercise 16: Clone an ArrayList
Problem Statement: Perform a shallow copy of an ArrayList to another ArrayList using the clone() method.
Purpose: This exercise helps you practice using clone() and understand what "shallow copy" means for a list of objects.
Given Input: original = {"X", "Y", "Z"}
Expected Output: Clone = [X, Y, Z]
▼ Hint
- Call the
clone()method directly on the originalArrayListinstance. - Since
clone()returns a plainObject, cast the result back to the appropriate generic type before using it. - Remember that this creates a shallow copy: the new list is a separate object, but if elements were mutable, both lists would still reference the same underlying element objects.
- Print the cloned list to confirm it contains the same elements as the original.
▼ Solution & Explanation
Explanation:
original.clone(): Creates a shallow copy of theArrayList, meaning a new list object is created but its elements are not individually duplicated.(ArrayList<String>) original.clone(): Casts the returnedObjectback to the expected generic type, sinceclone()has an untyped return signature.@SuppressWarnings("unchecked"): Suppresses the compiler warning that results from this necessary but inherently unchecked cast.- Alternative: You could use the copy constructor
new ArrayList<>(original)instead ofclone(), which is generally preferred in modern Java code since it avoids the unchecked cast entirely.
Exercise 17: Array to ArrayList Conversion
Problem Statement: Convert a standard fixed-size Java array (String[]) into a dynamic ArrayList.
Purpose: This exercise helps you practice bridging arrays and collections using Arrays.asList().
Given Input: String[] array = {"Red", "Green", "Blue"}
Expected Output: List = [Red, Green, Blue]
▼ Hint
- Use
Arrays.asList(array)to wrap the array in a fixed-sizeListview. - Pass that view into the
ArrayListconstructor to create a fully resizable, independent list. - Skipping the
ArrayListconstructor and usingArrays.asList()alone would limit you to a fixed-size list that doesn't supportadd()orremove(). - Print the resulting
ArrayListto confirm it contains the same elements as the original array.
▼ Solution & Explanation
Explanation:
Arrays.asList(array): Wraps the existing array in aListview backed directly by the array, without copying its elements.new ArrayList<>(...): Copies the elements from that fixed-size view into a brand new, fully resizableArrayList.- Fixed-size limitation: Calling
add()orremove()directly on the result ofArrays.asList()throws anUnsupportedOperationException, which is why wrapping it in anArrayListconstructor matters. - Alternative: You could loop through the array manually and call
add()for each element, thoughArrays.asList()combined with the constructor is far more concise.
Exercise 18: ArrayList to Array Conversion
Problem Statement: Convert an ArrayList of integers back into a standard wrapper array (Integer[]).
Purpose: This exercise helps you practice the toArray() method for converting a list back into an array of a specific type.
Given Input: numbers = {1, 2, 3, 4}
Expected Output: Array = [1, 2, 3, 4]
▼ Hint
- Use the
toArray()method available on everyArrayListto produce an array of its elements. - Pass a correctly typed array as an argument, such as
new Integer[0], so the method returns the proper array type instead of a plainObject[]. - Store the result in a variable of the matching array type, like
Integer[]. - Use
Arrays.toString()to print the array's contents in a readable format.
▼ Solution & Explanation
Explanation:
numbers.toArray(new Integer[0]): Converts the list's elements into anInteger[]array, using the provided zero-length array purely to specify the desired return type.- Zero-length array argument: If the array passed in is too small,
toArray()allocates a new array of the correct size internally, so a zero-length array is an efficient and idiomatic choice. Arrays.toString(array): Provides a readable, comma-separated representation of the array's contents, since arrays don't have a useful defaulttoString()likeArrayListdoes.- Alternative: You could call
numbers.toArray()without arguments to get a plainObject[], but that loses type information and requires casting each element when accessed.
Exercise 19: Replace Elements Conditionally
Problem Statement: Given an ArrayList of integers, replace all negative numbers with the value 0.
Purpose: This exercise helps you practice conditionally updating list elements in place using an index-based loop.
Given Input: numbers = {5, -3, 8, -1, 0, -7}
Expected Output: Result = [5, 0, 8, 0, 0, 0]
▼ Hint
- Loop through the list using an index-based loop so you can update elements at specific positions.
- Check whether each element is negative using a simple comparison.
- Use
set(index, 0)to replace any negative value with zero, leaving other values untouched. - Avoid using a for-each loop for this task, since modifying list contents by index requires knowing the position.
▼ Solution & Explanation
Explanation:
for (int i = 0; i < numbers.size(); i++): Uses an index-based loop so each element can be checked and replaced at its exact position.numbers.get(i) < 0: Checks whether the current element is negative before deciding to replace it.numbers.set(i, 0): Overwrites only the negative elements in place, leaving zero and positive values unchanged.- Alternative: You could use
numbers.replaceAll(n -> n < 0 ? 0 : n)with a lambda expression for a more concise, functional-style solution.
Exercise 20: Filter Even Numbers
Problem Statement: Write a method that takes an ArrayList of integers and removes all odd numbers, leaving only even numbers.
Purpose: This exercise helps you practice the removeIf() method, which safely removes elements matching a condition during a single pass.
Given Input: numbers = {1, 2, 3, 4, 5, 6, 7, 8}
Expected Output: Result = [2, 4, 6, 8]
▼ Hint
- Use the
removeIf()method, which accepts a predicate describing which elements to remove. - Write a lambda expression that returns true for odd numbers, since those are the elements you want removed.
- Check for oddness using the modulus operator.
- Avoid removing elements while manually iterating with a for-each loop, since that throws a
ConcurrentModificationException.
▼ Solution & Explanation
Explanation:
numbers.removeIf(n -> n % 2 != 0): Removes every element for which the lambda condition evaluates to true, in this case any number with a non-zero remainder when divided by 2.n % 2 != 0: Identifies odd numbers, since even numbers always produce a remainder of 0 when divided by 2.- Safe removal during iteration:
removeIf()internally handles the iteration and removal process safely, avoiding theConcurrentModificationExceptionthat manual removal during a for-each loop would cause. - Alternative: You could build a brand new list containing only the even numbers using a stream, like
numbers.stream().filter(n -> n % 2 == 0).collect(Collectors.toList()), which avoids mutating the original list.
Exercise 21: Trim Capacity
Problem Statement: Optimize the memory of an ArrayList by trimming its capacity to match its current size.
Purpose: This exercise helps you practice using trimToSize(), and understand the difference between a list's size and its internal backing array capacity.
Given Input: ArrayList<Integer> numbers = new ArrayList<>(20); with only 3 elements added
Expected Output: Size = 3
▼ Hint
- Create the
ArrayListwith a large initial capacity using the constructor that accepts anint, such asnew ArrayList<>(20). - Add only a few elements, leaving most of the reserved capacity unused.
- Call
trimToSize()to shrink the internal backing array down to exactly the current number of elements. - Note that
size()and the list's contents are unaffected by trimming; only the unused reserved space is released.
▼ Solution & Explanation
Explanation:
new ArrayList<>(20): Creates a list with an initial backing array capacity of 20 elements, even though it starts out empty.numbers.trimToSize(): Resizes the internal backing array down to match the current number of elements, releasing the unused reserved capacity back to the JVM.- Invisible via public API: There's no public method to directly observe an
ArrayList's capacity, so this optimization matters for memory usage internally even thoughsize()still reports 3 both before and after. - Alternative: You could avoid over-allocating capacity in the first place by using the no-argument
new ArrayList<>()constructor, which starts with a small default capacity and grows only as needed.
Exercise 22: Compare Two Lists
Problem Statement: Compare two ArrayLists to check if they are identical (contain the same elements in the exact same order).
Purpose: This exercise helps you practice using equals() to compare list contents, and understand that order matters for this comparison.
Given Input: listA = {1, 2, 3}, listB = {1, 2, 3}, listC = {3, 2, 1}
Expected Output:
listA equals listB = true listA equals listC = false
▼ Hint
- Use the
equals()method directly on oneArrayList, passing the other as the argument. ArrayList'sequals()implementation checks both that the lists are the same size and that every element matches at the same position.- Two lists with the same elements but in a different order are not considered equal by this method.
- Print the boolean result of each comparison to confirm the expected outcome.
▼ Solution & Explanation
Explanation:
listA.equals(listB): Returns true because both lists contain the same elements in the same order, which is exactly whatArrayList'sequals()checks for.listA.equals(listC): Returns false because, despite containing the same elements,listChas them in a different order.- Order-sensitive comparison: Unlike a
Set, anArrayList's equality depends on element order, reflecting its nature as a sequential, indexed collection. - Alternative: You could manually loop through both lists comparing elements at each index, but
equals()already implements this logic correctly and concisely.
Exercise 23: Remove Duplicates (With Set)
Problem Statement: Remove all duplicate elements from an ArrayList by converting it to a HashSet, then converting it back.
Purpose: This exercise helps you practice using a set-backed conversion to quickly deduplicate a list's elements.
Given Input: numbers = {1, 2, 2, 3, 4, 4, 4, 5}
Expected Output: Unique = [1, 2, 3, 4, 5]
▼ Hint
- Create a set and pass the original
ArrayListinto its constructor, which automatically discards duplicate values. - Create a new
ArrayListand pass the set into its constructor to convert the unique values back into a list. - Be aware that a plain
HashSetdoes not preserve insertion order, so the resulting list's order may differ from the original. - Print the final list to confirm all duplicates have been removed.
▼ Solution & Explanation
Explanation:
new LinkedHashSet<>(numbers): Copies the list's elements into a set, automatically discarding duplicates while preserving the original insertion order.new ArrayList<>(uniqueSet): Converts the deduplicated set back into a list so the result supports indexed access and the usualArrayListmethods again.LinkedHashSetversusHashSet: A plainHashSetwould also remove duplicates but wouldn't guarantee the original order is preserved, which is whyLinkedHashSetis used here.- Alternative: You could use a plain
HashSetif the resulting order doesn't matter for your use case, which has marginally less overhead thanLinkedHashSet.
Exercise 24: Remove Duplicates (Without Set)
Problem Statement: Remove all duplicate elements from an ArrayList without using any other collection class (like Set or another list).
Purpose: This exercise helps you practice in-place deduplication using nested loops and careful index management, without relying on auxiliary collections.
Given Input: numbers = {1, 2, 2, 3, 4, 4, 4, 5}
Expected Output: Unique = [1, 2, 3, 4, 5]
▼ Hint
- Use two nested loops, both operating directly on the original list rather than creating any new collection.
- For each element at index
i, scan the remaining elements from the end of the list backward, checking for duplicates. - When a duplicate is found later in the list, remove it immediately using its index.
- Scanning backward for removals in the inner loop avoids skipping elements that would otherwise happen due to shifting indices after a removal.
▼ Solution & Explanation
Explanation:
- Outer loop (index
i): Treats each element in turn as the "reference" value to compare against everything after it. - Inner loop (index
j, counting down): Scans from the end of the list back towardi + 1, checking for any later duplicate of the reference value. numbers.remove(j): Removes a confirmed duplicate immediately; counting the inner loop downward ensures removing an element doesn't disturb the indices still left to check.- Alternative: You could achieve a similar in-place result with a single forward pass that shifts elements manually, but the backward-scanning nested loop is simpler to reason about correctly.
Exercise 25: Find Common Elements
Problem Statement: Given two different ArrayLists, find and display all elements that are common to both lists.
Purpose: This exercise helps you practice using contains() to cross-reference the elements of two separate lists.
Given Input: listA = {1, 2, 3, 4, 5}, listB = {3, 4, 5, 6, 7}
Expected Output: Common = [3, 4, 5]
▼ Hint
- Create a new
ArrayListto hold the elements found in both lists. - Loop through the first list, and for each element, check whether it also exists in the second list using
contains(). - If an element exists in both lists, add it to the results list.
- Print the results list to see which elements were shared between the two originals.
▼ Solution & Explanation
Explanation:
for (Integer value : listA): Iterates through every element of the first list to check it against the second.listB.contains(value): Determines whether the current element fromlistAalso appears somewhere inlistB.common.add(value): Collects every element confirmed to exist in both lists into the results list.- Alternative: You could use
retainAll()on a copy oflistA, likenew ArrayList<>(listA).retainAll(listB), which achieves the same result with a single built-in method call.
Exercise 26: Frequency Counter
Problem Statement: Count the number of times each unique element appears in an ArrayList and store the results in a Map<Element, Integer>.
Purpose: This exercise helps you practice building a frequency map using getOrDefault(), a common pattern for counting occurrences.
Given Input: items = {"apple", "banana", "apple", "orange", "banana", "apple"}
Expected Output:
apple = 3 banana = 2 orange = 1
▼ Hint
- Create a
Map<String, Integer>to store each unique element alongside its count. - Loop through the list, and for each element, use
getOrDefault()to retrieve its current count (or 0 if not seen yet). - Put the incremented count back into the map for that element.
- After the loop, iterate over the map's entries to print each element with its final frequency.
▼ Solution & Explanation
Explanation:
Map<String, Integer> frequency: Associates each unique element with a running count of how many times it has appeared.frequency.getOrDefault(item, 0) + 1: Retrieves the current count for an element, defaulting to zero if it's the first occurrence, then increments it.LinkedHashMap: Preserves the order in which elements were first encountered, so the printed output follows a predictable sequence.- Alternative: You could use
frequency.merge(item, 1, Integer::sum)instead ofgetOrDefault()combined withput(), which condenses the increment logic into a single method call.
Exercise 27: Split an ArrayList
Problem Statement: Split a large ArrayList into two smaller ArrayLists based on a condition (e.g., one list for strings shorter than 5 characters, and another for strings 5 characters or longer).
Purpose: This exercise helps you practice classifying and distributing elements into separate lists during a single pass.
Given Input: words = {"cat", "elephant", "dog", "hippopotamus", "ant", "kangaroo"}
Expected Output:
Short = [cat, dog, ant] Long = [elephant, hippopotamus, kangaroo]
▼ Hint
- Create two empty
ArrayLists, one for each category of elements. - Loop through the original list once, checking each element's length against the threshold.
- Add each element to the appropriate list based on the condition.
- Print both resulting lists to confirm the elements were split correctly.
▼ Solution & Explanation
Explanation:
word.length() < 5: Determines which category a word belongs to based on its character count.shortWords.add(word)/longWords.add(word): Places each word into the appropriate list without modifying the originalwordslist.- Single pass: The original list is only iterated once, with each element classified and placed immediately.
- Alternative: You could use streams with
partitioningBy(), likewords.stream().collect(Collectors.partitioningBy(w -> w.length() < 5)), which returns both groups in a singleMap<Boolean, List<String>>.
Exercise 28: Merge Sorted Lists
Problem Statement: Given two pre-sorted ArrayLists of integers, merge them into a single, final sorted ArrayList without invoking Collections.sort() at the end.
Purpose: This exercise helps you practice the two-pointer merge technique used in merge sort, taking advantage of the fact that both inputs are already sorted.
Given Input: listA = {1, 3, 5, 7}, listB = {2, 4, 6, 8}
Expected Output: Merged = [1, 2, 3, 4, 5, 6, 7, 8]
▼ Hint
- Use two index variables to track the current position within each of the two source lists.
- Compare the current elements from both lists, and add the smaller one to the merged result, advancing only that list's pointer.
- Once one list is fully consumed, append all of the remaining elements from the other list directly.
- This approach preserves sorted order without needing to call
Collections.sort()at the end.
▼ Solution & Explanation
Explanation:
while (i < listA.size() && j < listB.size()): Continues comparing elements from both lists as long as both still have unprocessed elements remaining.listA.get(i) <= listB.get(j): Determines which of the two current elements is smaller, adding it to the merged result and advancing only that list's pointer.- Trailing while loops: Once one list runs out, the remaining elements of the other list are already sorted, so they can be appended directly without further comparison.
- Alternative: You could combine both lists and call
Collections.sort()on the result, but that ignores the fact that both inputs are already sorted and does unnecessary extra work.
Exercise 29: Find Continuous Sublist Sum
Problem Statement: Given an ArrayList of positive integers, find a contiguous sublist that adds up to a specific target sum.
Purpose: This exercise helps you practice the sliding window technique for a sum-based problem, taking advantage of the fact that all values are positive.
Given Input: numbers = {1, 2, 3, 7, 5}, target = 12
Expected Output: Sublist Sum Found = [2, 3, 7]
▼ Hint
- Use a sliding window with two pointers representing the start and end of the current sublist.
- Keep a running sum of the elements currently within the window.
- If the running sum exceeds the target, shrink the window from the left by subtracting the leftmost element's value and advancing the start pointer.
- If the running sum exactly matches the target, capture the current window as your answer.
▼ Solution & Explanation
Explanation:
sum += numbers.get(end): Expands the window by adding the next element to the running sum.while (sum > target && start <= end): Shrinks the window from the left whenever the running sum overshoots the target, since all values are positive and removing elements only decreases the sum.sum == target: Confirms the current window's elements add exactly to the target, at which point the matching sublist is captured usingsubList().- Alternative: You could use a brute-force approach checking every possible start and end combination, but the sliding window technique runs in linear time and only works correctly here because all numbers are positive.
Exercise 30: Custom Object Sorting
Problem Statement: Create a custom class Student with attributes id, name, and gpa. Create an ArrayList<Student> and sort the students by their gpa in descending order using a custom Comparator.
Purpose: This exercise helps you practice writing a custom Comparator to sort objects that don't have a natural ordering of their own.
Given Input: students = [(1, "Alice", 3.8), (2, "Bob", 3.2), (3, "Charlie", 3.9)]
Expected Output:
Charlie - GPA: 3.9 Alice - GPA: 3.8 Bob - GPA: 3.2
▼ Hint
- Define a simple
Studentclass with private fields for id, name, and gpa, plus a constructor and getter methods. - Create an
ArrayList<Student>and populate it with a fewStudentobjects. - Use
Collections.sort()with aComparatorthat compares two students' gpa values, reversing the natural order to sort from highest to lowest. - Print each student's name and gpa after sorting to confirm the descending order.
▼ Solution & Explanation
Explanation:
Comparator<Student>: Defines custom comparison logic forStudentobjects, since they don't have a natural ordering of their own.Double.compare(b.getGpa(), a.getGpa()): Compares the two gpa values in reverse order (bbeforea), which produces a descending sort instead of the default ascending one.Collections.sort(students, comparator): Applies the custom comparator to sort the list in place according to the defined logic.- Alternative: You could use a lambda expression instead of an anonymous
Comparatorclass, likestudents.sort((a, b) -> Double.compare(b.getGpa(), a.getGpa())), or useComparator.comparingDouble(Student::getGpa).reversed()for a more fluent, readable style.

Leave a Reply