Tuesday, 7 June 2022

Implement a Closeable iterator in Java

A Closeable iterator is an iterator that is auto closeable (implements java.lang.AutoCloseable interface). A typical use case of this iterator is for those  are based on native-resources such as files, network, or database connections.

 

This is continuation to my previous post How to read the file in iterator way in Java?

 

What is iterator?

Iterator is used to traverse the collection of elements. There is also a legacy class called Enumeration, it is also used to traverse collection of elements. Only difference is by using iterator you can remove an element while traversing, by using enumerator you can’t.

 

Let me brief the methods in iterator interface.

Method

Description

boolean hasNext()

Returns true if the iteration has more elements.

E next()

Returns the next element in the iteration.

default void remove()

Removes from the underlying collection the last element returned by this iterator. Java provides default implementation for this method. The default implementation throws an instance of UnsupportedOperationException and performs no other action.

 

Iterable interface

All the Java collections implementing Iterable interface, to return an iterator. Implementing this interface allows an object to be the target of the "foreach" statement. Following table summarizes the methods in Iterable interface.

 

Method

Description

Iterator<T> iterator()

Returns an iterator over a set of elements of type T.

 

Now let’s come to the problem, I want to implement my a closeable iterator that close the resources automatically (when used I try-with resources statement) post reading the iterator elements.

 

 

Follow below step-by-step procedure to build a Closeable iterator.

 

Step 1: Define CloseableIterator interface.

 

CloseableIterator.java

package com.sample.app;

import java.util.Iterator;

public interface CloseableIterator<T> extends Iterator<T>, AutoCloseable{

	static <T> CloseableIterator<T> getIterator(Iterator<T> iterator, AutoCloseable autoCloseable){
		return new CloseableIteratorImpl<>(iterator, autoCloseable);
		
	}

}

 

Step 2: Implement CloseableIterator interface.

 

CloseableIteratorImpl.java

package com.sample.app;

import java.util.Iterator;

public class CloseableIteratorImpl<T> implements CloseableIterator<T> {

	private Iterator<T> iterator;
	private AutoCloseable autoCloseable;

	public CloseableIteratorImpl(Iterator<T> iterator, AutoCloseable autoCloseable) {
		this.iterator = iterator;
		this.autoCloseable = autoCloseable;
	}

	@Override
	public boolean hasNext() {
		return iterator.hasNext();
	}

	@Override
	public T next() {
		return iterator.next();
	}

	@Override
	public void remove() {
		iterator.remove();
	}

	@Override
	public void close() throws Exception {
		System.out.println("Closing "+ autoCloseable);
		autoCloseable.close();
	}

}

Step 3: Define FileReadIterable class. It is used to read the file content in iterator fashion.

 

FileReadIterable.java

package com.sample.app;

import java.io.BufferedReader;
import java.io.IOException;
import java.util.Iterator;

/**
 * FileReadIterable class is used to read the file using an iterator.
 */
public class FileReadIterable implements Iterable<String> {

	private BufferedReader bufferedReader;

	public FileReadIterable(BufferedReader bufferedReader) {
		this.bufferedReader = bufferedReader;
	}

	@Override
	public Iterator<String> iterator() {
		return new FileReadIterator(bufferedReader);
	}

	private static class FileReadIterator implements Iterator<String> {

		private BufferedReader bufferedReader;
		private String line;

		public FileReadIterator(BufferedReader bufferedReader) {
			this.bufferedReader = bufferedReader;
		}

		@Override
		public boolean hasNext() {
			try {
				line = bufferedReader.readLine();
			} catch (IOException e) {
				return false;
			}
			return line != null;
		}

		@Override
		public String next() {
			return line;
		}

	}

}

Step 4: Create demo.txt file.

 

demo.txt

line1
line2
line3

Step 5: Define CloseableIteratorDemo class.

 

CloseableIteratorDemo.java

package com.sample.app;

import java.io.BufferedReader;
import java.io.FileReader;
import java.net.URL;
import java.util.Iterator;

public class CloseableIteratorDemo {
	public static String resourceFilePath(String resourceFile) {
		ClassLoader classLoader = FileIteratorDemo.class.getClassLoader();
		URL url = classLoader.getResource(resourceFile);
		return url.getPath();
	}

	public static void main(String[] args) throws Exception {
		String filePath = resourceFilePath("demo.txt");
		BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
		FileReadIterable fileReadIterable = new FileReadIterable(bufferedReader);
		Iterator<String> fileIterator = fileReadIterable.iterator();

		try (CloseableIterator<String> iterator = CloseableIterator.getIterator(fileIterator, bufferedReader)) {
			while (iterator.hasNext()) {
				System.out.println(iterator.next());
			}
		}

	}

}

Output

line1
line2
line3
Closing java.io.BufferedReader@15db9742



You may like

Interview Questions

Can I run a class file that is compiled in lower environment?

How to solve the Error: Could not find or load main?

float vs double in Java

Quick guide to race condition in Java with examples

How to read the file content using an iterator in Java?

No comments:

Post a Comment