Overview · Learning Goals · Files · How an ArrayList Works · Tasks · Testing · Checkpoint · Submission
In this lab you will build a simplified version of Java's
ArrayList. An ArrayList stores elements in an underlying array,
but unlike an ordinary array, it can grow when more space is needed.
Java already provides an ArrayList, but implementing the data
structure yourself provides insights into how an array-backed list actually
works.
It is not enough to just get the code to "work." It is more important that you understand why the code is designed the way it is and what is happening inside the data structure when an element is added, retrieved, replaced, or removed.
Hand and Deck classes will depend on the
ArrayList you build today. Take the time to make each operation work
correctly before moving on.
By completing this lab, you should become more comfortable with:
toString() representation of an objectDownload the provided files and place them in a folder named Lab1.
You will write your code in ArrayList.java. Look for
TODO comments throughout the file. Some TODOs contain hints,
but you are responsible for writing the implementation.
ArrayListTester.java is provided to help you test your work
incrementally. Do not modify the tester.
initializeArray method creates the underlying array. It uses
Java syntax involving generic arrays and Object that we have
not covered yet, so the complete method has been provided. You do not need
to modify it.
Our ArrayList keeps track of two important pieces of information:
arr — the underlying array that holds the elementssize — the number of elements currently stored in the listSuppose an ArrayList currently contains the values 8, 3, and 6:
index 0 1 2 3 4
+-------+-------+-------+-------+-------+
arr | 8 | 3 | 6 | null | null |
+-------+-------+-------+-------+-------+
size = 3
capacity = 5
The size is 3 because the list contains three elements. The capacity is 5 because the underlying array has five available positions.
Begin by identifying the information that every ArrayList needs to keep
track of. The declaration for the underlying generic array,
arr, has been provided for you.
Complete the TODOs that declare:
DEFAULT_CAPACITY constant, with a value of 10size instance variable, which holds the number of elements currently stored in the ArrayList
Begin by completing both constructors and the size() method.
public ArrayList()
public ArrayList(int initialCapacity)
public int size()
A newly constructed ArrayList should be empty, regardless of the capacity of its underlying array.
this operator to call
the one-argument constructor using the DEFAULT_CAPACITY constant.
size describes how many elements are currently in the list.
Make sure you understand this distinction and can explain it in your own words.
Notice that size() is, in fact, a getter. Sometimes
get can be dropped from a getter's name when the method name
is unambiguous.
Complete:
public void add(T item)
private void changeCapacity(int newCapacity)
add places a new item at the end of the list. If there is no
room left in the underlying array, the ArrayList must create a larger array
before storing the new item.
size.
The provided initializeArray method creates an empty
underlying array. When changeCapacity creates a new array,
your existing elements must not disappear.
Complete:
public T get(int index)
public void set(int index, T item)
get returns the element currently stored at an index.
set replaces the element at an existing index.
For example, if the list contains:
[10, 20, 30]
then:
get(1) → 20
set(1, 99) → list becomes [10, 99, 30]
set is a destructive operation: it overwrites the element
currently stored at the specified index. The previous element at that
index is replaced. set does not add another element, so the
size of the list should not change.
Complete:
public T remove(int index)
Removing an element from an array-backed list requires more work than simply clearing one array position.
Consider:
index 0 1 2 3
+-------+-------+-------+-------+
before | A | B | C | D |
+-------+-------+-------+-------+
remove(1)
+-------+-------+-------+-------+
after | A | C | D | null |
+-------+-------+-------+-------+
The method must return the element that was removed. The elements after
that position must shift one position to the left, and the size of the
list must decrease. After the shift and size change, set the old location
of the last element to null.
Complete:
public String toString()
Your method should return a String showing the elements in order, enclosed in square brackets and separated by commas and spaces.
empty list → []
one element → [4]
three elements → [4, 7, 2]
Do not wait until the end of the lab to test everything at once. Complete one task, compile your files, run the tester, and then move to the next task.
javac ArrayList.java ArrayListTester.java
java ArrayListTester
Tasks 1 and 2 are special cases. Declarations cannot be verified through
normal ArrayList behavior, and a newly constructed ArrayList should have
size 0 while the unfinished skeleton's placeholder size()
also returns 0. Before moving on, ask the instructor or a TA to review
your code for Tasks 1 and 2. The tester begins its behavioral checks with
Task 3.
As you progress, the tester will report results such as:
PASS: Added value can be retrieved
PASS: Several adds update size correctly
FAIL: ArrayList grows beyond its initial capacity
expected=8, got=2
Task result: 2/3 tests passed
TASK NOT YET COMPLETE
ArrayListTester.java passes all of its automated tests.
Then demonstrate the passing tester to a TA or instructor.
The tester checks whether your ArrayList behaves correctly. The checkpoint also checks whether you understand the code you wrote. Be prepared to answer questions about your implementation. A TA or instructor may choose a couple of questions such as:
add is called and the underlying
array is full?
Explain how your code increases the capacity without losing the elements
already stored in the list.
null.
set different from add?
Explain why set is a destructive operation and why it does
not change the size of the list.
this(...) accomplishes and why it is
preferable to duplicating the initialization code.
If you finish the ArrayList and pass the checkpoint, begin working on Project 1.
It is your responsibility to upload your lab files before the end of the lab period.
ArrayList.java file in that folder.