DESIGN PATTERNS SAGA #11: REAL PROJECT SITUATIONS WITH ITERATOR

Most of the time we use the Iterator from the Collections API. It’s very important to know how to implement a customized Iterator in order to understand what is happening behind the scenes. If we read Java source code, for example, we are going to find out that the elements from ArrayList are actually manipulated in a normal array. If we read Java source code we can greatly improve our programming skills. I strongly recommend that you make this a habit.

Iterator diagram:

iterator_diagram.PNG

Get the Design_Patterns_Saga_GitHub_Source_Code

1 – Iterator: This is the main class where we are able to iterate the objects. The first detail to be aware of is that we are implementing the Iterable interface using String as a generic type.

We are declaring an array of products and the index.

In the constructor, we are initializing the array of products with the size of 10 and assigning zero to the index.

In the add method, we are adding a new element inside the array. We simply check if the index is the same size as the initial size of the array, in this case, 10. If so, we are going to make the array 5 times larger than before. Following this process, we copy the old array information to the largerArray. Finally, we add the product to the final array.

In the iterator method, we are using an anonymous inner class that implements Iterator. If we are using the Iterator interface we must implement all of its methods.

Again, we are declaring the index to control the iteration.

Let’s see what happens on the Iterator methods:

hasNext: verifies if there is another element to be iterated. If the index from the iterator is lower than the size of the array and the element is different from null it means we have the next element.

next: gets the next element from the products. It simply refers to the next element from the array and returns it.

remove: it copies the old array without the removed position, returning the removed element.

public class ProductRepository implements Iterable<String> {

	private String[] products;
	private int index;

	public ProductRepository() {
		products = new String[10];
		index = 0;
	}

	public void add(String product) {
		if (index == products.length) {
			String[] largerProducts = new String[
                            products.length + 5];
			System.arraycopy(products, 0, largerProducts,
                            0, products.length);
			products = largerProducts;
			largerProducts = null;
		}

		products[index++] = product;
	}

	@Override
	public Iterator<String> iterator() {
		return new Iterator<String>() {

			private int currentIndex = 0;

			@Override
			public boolean hasNext() {
				return currentIndex < products.length
                                  && products[currentIndex] != null;
			}

			@Override
			public String next() {
				return products[currentIndex++];
			}

			@Override
			public void remove() {
				System.arraycopy(products, currentIndex + 1,
                                  products, currentIndex, products.length - 1);
			}

		};
	}
}

2 – Unit Test: Now we are going to test the Iterator.

customIteratorTest: we add some elements, we get the iterator, remove two elements and check if the remaining element is “Tablet”.

javaAPIIteratorTest: we are just using the iterator from the Java Collections API, removing all the elements and checking if the Set Collection is empty.

 public class IteratorTest {

	@Test
	public void customIteratorTest() {
		ProductRepository repo = new ProductRepository();

		repo.add("Guitar");
		repo.add("Notebook");
		repo.add("Tablet");

		Iterator<String> productIterator = repo.iterator();
		productIterator.remove();
		productIterator.remove();

		Assert.assertEquals(productIterator.next(), "Tablet");
	}

	@Test
	public void javaAPIIteratorTest() {
		Set<String> simpsons = new HashSet<>();

		simpsons.add("Homer");
		simpsons.add("Bart");
		simpsons.add("Margie");

		Iterator<String> simpsonsItr = simpsons.iterator();

		while (simpsonsItr.hasNext()) {
			String name = simpsonsItr.next();
			System.out.println(name);
			simpsonsItr.remove();
		}

		Assert.assertEquals(0, simpsons.size());
	}

}

Summary of actions:

  1. Created the Iterator class.
  2. Encapsulated an array inside the Iterator class.
  3. Implemented the Iterable interface in the Iterator class.
  4. Overrode the iterator method.
  5. Created an anonymous inner class of the Iterator type.
  6. Overrode all the methods from the Iterator interface.

To practice the Iterator Pattern you can create another Repository and iterate over the elements from it. Create another test method to make sure it works. Be sure to use TDD (Test Driven Development).

DESIGN PATTERNS SAGA #11: REAL PROJECT SITUATIONS WITH ITERATOR

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s