Iterators and Inner Classes
Java Iterator and Inner Class
Enhanced For Loop
A way to iterate through all elements of a Collection.
It is helpful iterating through a collection with no order (not all data structures are "positional"), such as a Set.
IndexedList<Integer> values = new ArrayIndexedList<>();
for (int val : values) {
...
}
Changing val will not change the values in values
Enhanced for loop uses syntatic sugar:
Iterator<T> it = myCollection.iterator();
while(it.hasNext()) {
MyType element = it.next();
}
for (MyType element: myCollection) {
// same as above
}
Iterator Design
The iterator design pattern states the elements of a collection (an aggregate object) shoudl be accessed and traversed without expoing its representation (underlying implementation). This goal is achieved by defining an iterator object to traverse a data tructuer and access ts elemens.
Implement using Java API interfaces: Iterable and Iterator.
The built-in array is an exception because it is an iterable but does not implement the Iterable interface. This array is a unique construct, a cross between primitive an dobjects.
Iterable Interface Declare an ADT is iterable:
public interface IndexedList<T> extends Iterable<T> {
...
Iterator<T> iterator();
}
Implementing inherited iterator method in the ArrayIndexedList:
public class ArrayIndexedList<T> implements IndexedList<T> {
@Override
public Itereator<T> iterator() {
return Arrays.stream(data).iterator();
}
}
Must implement
import java.util.Arrays;
import java.util.Iterator;
Instead of using Arrays.stream(data).iterator(), we can make our own iterator by creating a new class that implements the iterator interface.
public class ArrayIndexedListIterator<T> implements Iterator<T> {
private T[] data;
private int cursor;
public ArrayIndexedListIterator(T[] data) {
this.data = data;
this.cursor = 0;
}
@Override public boolean hasNext() {
return cursor < data.length;
}
@Override public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return data[cursor++];
}
}
Then in ArrayIndexedList.iterator:
public class ArrayIndexedList<T> implements IndexedList<T> {
@Override public Iterator<T> iterator() {
return new ArrayIndexedListIterator<>(this.data);
}
}
We can put this iterator class inside the data structure itself ("nested class"), The advantages to using an inner class:
- Logical way of grouping classes that are only used in one place.
- Increases encapsulation. The iterator can get access to all the members of the data structure. Furthermore, the iterator can be hidden from the outside world
- More readable and maintainable.
- Always use inner classes to impelment the
Iteratorinterface for a data structure in this course.
Test an Iterable ADT
@Test
@DisplayName("test iterator after IndexedList is defined")
void testEnhancedLoopAfterConstruction() {
int counter = 0;
for (int element: numbers) {
assertEquals(defaultValue, element);
count++;
}
assertEquals(size, counter);
}Linked from Data Structures