eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

Course – LJB – NPI EA (cat = Core Java)
announcement - icon

Code your way through and build up a solid, practical foundation of Java:

>> Learn Java Basics

Partner – LambdaTest – NPI EA (cat= Testing)
announcement - icon

Distributed systems often come with complex challenges such as service-to-service communication, state management, asynchronous messaging, security, and more.

Dapr (Distributed Application Runtime) provides a set of APIs and building blocks to address these challenges, abstracting away infrastructure so we can focus on business logic.

In this tutorial, we'll focus on Dapr's pub/sub API for message brokering. Using its Spring Boot integration, we'll simplify the creation of a loosely coupled, portable, and easily testable pub/sub messaging system:

>> Flexible Pub/Sub Messaging With Spring Boot and Dapr

1. Overview

In this tutorial, we’ll look at the usage of Iterable and Iterator interfaces in Java and the differences between them.

2. Iterable Interface

Iterable interface belongs to the java.lang package. It represents a data structure that can be iterated over.

The Iterable interface provides a method that produces an Iterator. When using an Iterable, we cannot get an element by index. Similarly, we cannot get the first or the last elements from the data structure as well.

All collections in Java implement the Iterable interface.

2.1. Iterate Over an Iterable

We can iterate over elements inside a collection using the enhanced for loop, also called the for-each loop. However, only objects that implement an Iterable interface can be used within such a statement. It’s also possible to iterate over elements using the while statement in combination with an Iterator.

Let’s see an example of iterating over elements in a List using the for-each statement:

List<Integer> numbers = getNumbers();
for (Integer number : numbers) {
    System.out.println(number);
}

Similarly, we can use the forEach() method in combination with lambda expressions:

List<Integer> numbers = getNumbers();
numbers.forEach(System.out::println);

2.2. Implementing the Iterable Interface

Custom implementations of the Iterable interface can come in handy when we have custom data structures that we’d like to iterate over.

Let’s begin by creating a class representing a shopping cart that will hold elements in an array. We’ll not call the for-each loop directly on the array. Instead, we’ll implement the Iterable interface. We don’t want our clients to depend on the chosen data structure. If we provide clients the ability to iterate, we can easily use a different data structure without clients having to change code.

The ShoppingCart class implements the Iterable interface and overrides its iterate() method:

public class ShoppingCart<E> implements Iterable<E> {

    private E[] elementData;
    private int size;

    public void add(E element) {
        ensureCapacity(size + 1);
        elementData[size++] = element;
    }

    @Override
    public Iterator<E> iterator() {
        return new ShoppingCartIterator();
    }
}

The add() method stores elements in an array. Due to an array’s fixed size and capacity, we expand the maximum number of elements using the ensureCapacity() method.

Each invocation of the iterator() method on the custom data structure produces a new instance of an Iterator. We create a new instance since an iterator is responsible for maintaining the current iteration state.

By providing a concrete implementation of the iterator() method, we can use an enhanced for statement to iterate over objects of the implemented class.

Now, let’s create an inner class inside the ShoppingCart class that represents our custom iterator:

public class ShoppingCartIterator implements Iterator<E> {
    int cursor;
    int lastReturned = -1;

    public boolean hasNext() {
        return cursor != size;
    }

    public E next() {
        return getNextElement();
    }

    private E getNextElement() {
        int current = cursor;
        exist(current);

        E[] elements = ShoppingCart.this.elementData;
        validate(elements, current);

        cursor = current + 1;
        lastReturned = current;
        return elements[lastReturned];
    }
}

Lastly, let’s create an instance of our iterable class and use it in the enhanced for loop:

ShoppingCart<Product> shoppingCart  = new ShoppingCart<>();

shoppingCart.add(new Product("Tuna", 42));
shoppingCart.add(new Product("Eggplant", 65));
shoppingCart.add(new Product("Salad", 45));
shoppingCart.add(new Product("Banana", 29));
 
for (Product product : shoppingCart) {
   System.out.println(product.getName());
}

3. Iterator Interface

Iterator is a member of the Java Collections Framework. It belongs to the java.util package. This interface allows us to retrieve or remove elements from a collection during the iteration.

In addition, it has two methods that help iterate over the data structure and retrieve its elements – next() and hasNext().

Moreover, it has a remove() method, which removes the current element pointed to by the Iterator.

Finally, the forEachRemaining(Consumer<? super E> action) method performs the given action for each remaining element inside the data structure.

3.1. Iterate Over Collection

Let’s see how to iterate over a List of Integer elements. In the example, we’ll combine the while loop and methods hasNext() and next().

The List interface is a part of Collection and, therefore, it extends the Iterable interface. To get an iterator from the collection, we simply need to call the iterator() method:

List<Integer> numbers = new ArrayList<>();
numbers.add(10);
numbers.add(20);
numbers.add(30);
numbers.add(40);

Iterator<Integer> iterator = numbers.iterator();

Furthermore, we can check if the iterator has any remaining elements by calling the hasNext() method. Afterward, we can get an element by calling the next() method:

while (iterator.hasNext()) {
   System.out.println(iterator.next());
}

The next() method returns the next element from the iteration. On the other hand, if there is no such element, it throws NoSuchElementException.

3.2. Implementing the Iterator Interface

Now, we’ll implement the Iterator interface. Custom implementation can be useful when we need to iterate over a collection using conditional element retrieval. For instance, we can use a custom iterator for iterating over odd or even numbers.

To illustrate, we’re going to iterate over prime numbers from the given collection. As we know, a number is considered a prime if it’s only divisible by one and by itself.

First, let’s create a class that contains a collection of numeric elements:

class Numbers {
 
    private static final List<Integer> NUMBER_LIST =
      Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
}

Furthermore, let’s define a concrete implementation of the Iterator interface:

private static class PrimeIterator implements Iterator<Integer> {

    private int cursor;

    @Override
    public Integer next() {
        exist(cursor);
        return NUMBER_LIST.get(cursor++);
    }

    @Override
    public boolean hasNext() {
        if (cursor > NUMBER_LIST.size()) {
            return false;
        }

        for (int i = cursor; i < NUMBER_LIST.size(); i++) {
            if (isPrime(NUMBER_LIST.get(i))) {
                cursor = i;
                return true;
            }
        }

        return false;
    }
}

Concrete implementations are usually created as inner classes. In addition, they’re responsible for maintaining the current iteration state. In the example above, we stored the current position of the next prime number inside the instance variable. Every time we call the next() method, the variable will contain an index of the upcoming prime number.

Any implementation of the next() method should throw a NoSuchElementException exception when there are no more elements left. Otherwise, the iteration can cause unexpected behavior

Let’s define a method inside the Number class that returns a new instance of the PrimeIterator class:

public static Iterator<Integer> iterator() {
    return new PrimeIterator();
}

Finally, we can use our custom iterator within the while statement:

Iterator<Integer> iterator = Numbers.iterator();
 
while (iterator.hasNext()) {
   System.out.println(iterator.next());
}

4. Differences Between Iterable and Iterator

To sum up, the following table shows the main differences between the Iterable and the Iterator interfaces:

Iterable Iterator
Represents a collection that can be iterated over using a for-each loop Represents an interface that can be used to iterate over a collection
When implementing an Iterable, we need to override the iterator() method When implementing an Iterator, we need to override the hasNext() and next() methods
Doesn’t store the iteration state Stores the iteration state
Removing elements during the iteration isn’t allowed Removing elements during the iteration is allowed

5. Conclusion

In this article, we looked at the differences between the Iterable and the Iterator interfaces in Java and their usage.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

eBook Jackson – NPI EA – 3 (cat = Jackson)