Java Exception Handling

Java Exception Handling – NoSuchElementException

Our journey continues through our in-depth Java Exception Handling series as, today, we dig into the depths of the NoSuchElementException. As the name suggests, a NoSuchElementException is thrown when trying to access an invalid element using a few built-in methods from the Enumeration and Iterator classes.

Throughout this article we’ll examine the NoSuchElementException in greater detail by looking at where it sits in the overall Java Exception Hierarchy. We’ll also get into some function Java code samples that will illustrate the basic usage of an Iterator, how it compares to more modern Java versions collection iteration practices, and how improper use of Iterators can lead to NoSuchElementExceptions in your own code, so let’s get going!

The Technical Rundown

All Java errors implement the java.lang.Throwable interface, or are extended from another inherited class therein. The full exception hierarchy of this error is:

Full Code Sample

Below is the full code sample we’ll be using in this article. It can be copied and pasted if you’d like to play with the code yourself and see how everything works.

When Should You Use It?

Java includes a few different ways to iterate through elements in a collection. The first of these classes, Enumeration, was introduced in JDK1.0 and is generally considered deprecated in favor of newer iteration classes, like Iterator and ListIterator. As with most programming languages, the Iterator class includes a hasNext() method that returns a boolean indicating if the iteration has anymore elements. If hasNext() returns true, then the next() method will return the next element in the iteration. Unlike Enumeration, Iterator also has a remove() method, which removes the last element that was obtained via next(). While Iterator is generalized for use with all collections in the Java Collections Framework, ListIterator is more specialized and only works with List-based collections, like ArrayList, LinkedList, and so forth. However, ListIterator adds even more functionality by allowing iteration to traverse in both directions via hasPrevious() and previous() methods.

For our example today we’ll just be sticking with the traditional Iterator class, along with a comparison to a more modern built-in syntax for iterating over common collections (an ArrayList, in this case). We start with the forEachLoopTest(ArrayList<Book> list):

This method uses the ArrayList.forEach(Consumer<? super E> action) method, which provides a simple method for performing an action on every element in an Iterable collection, such as our ArrayList<Book>. Moreover, we’re using the modern method reference syntax for our lambda expression, which simply passes the Book element that is obtained in the forEach(...) loop to our Logging.log method, which outputs it to the log.

To test this out we create a new ArrayList<Book> collection and add a few new Books to it:

Executing this code produces the following output:

As expected, our Books are created and added to our ArrayList<Book> books collection, then passed to and iterated through using the forEach(Logging::log) lambda method expression. This is the simplest way to iterate over all elements, but if we need more explicit control over iteration, we’d likely want to use an actual Iterator instance, which we’re testing in the iteratorTest(ArrayList<Book> list) method:

Here we’ve obtained the Iterator instance of our ArrayList<Book> list collection via the iterator() method, then perform a loop while iterator.hasNext() is true, in which we grab the next element via, convert it from an Object to a Book type, and output it to the log. We also return the obtained Iterator instance, which we’ll use in a moment.

Just as before, this works as expected, so executing this method produces the following output:

However, let’s see what happens if we use the now-exhausted Iterator instance returned by the iteratorTest(ArrayList<Book> list) method and try to obtain the next() element from it:

Unsurprisingly, this throws a NoSuchElementException our way, because we’ve already retrieved all three elements of the iterator within the iteratorTest(ArrayList<Book> list) method itself:

The Airbrake-Java library provides real-time error monitoring and automatic exception reporting for all your Java-based projects. Tight integration with Airbrake’s state of the art web dashboard ensures that Airbrake-Java gives you round-the-clock status updates on your application’s health and error rates. Airbrake-Java easily integrates with all the latest Java frameworks and platforms like Spring, Maven, log4j, Struts, Kotlin, Grails, Groovy, and many more. Plus, Airbrake-Java allows you to easily customize exception parameters and gives you full, configurable filter capabilities so you only gather the errors that matter most.

Check out all the amazing features Airbrake-Java has to offer and see for yourself why so many of the world’s best engineering teams are using Airbrake to revolutionize their exception handling practices!