Blog Infos
Author
Published
Topics
, , ,
Published
Purpose of the pattern

Iterator lets you traverse through Collections of elements without exposing the Collection type and traversing direction. The Iterating Responsibility is delegated to separate objects.

It’s beneficial when dealing with complex structures like Graphs where you can iterate over the elements in more than 1 way, like Breadth-First or Width-First.

What do we get from that?
  • Single Responsibility, the iterating code is extracted from the Collection.
  • Flexibility: you can create generic algorithms based on iterating and use them in your program.
  • Each Iterator has its state. You can iterate through the Collection in parallel.
  • Open/Closed, you can always add a new Iterator implementation without modifying the existing codebase.
  • You can pause the iteration at any point and continue it later.

The biggest drawback is that iterating over objects can be inefficient.

Implementation
Iterator class diagram

Our concrete Collection is Iterable meaning it provides a way to get an Iterator , then we’re able to implement multiple Iterator s and provide them by Iterable . It’s a compelling way to create very generic algorithms based on traversing through Collection .

Usually, we don’t write the Iterators ourselves but use the ones defined in Standard Library.

Example

In your app, you need to iterate through List from the middle, then to the right and the left until there are no elements like this:

Iterator example, ordered by numbers in boxes

 

This example is a bit different because we want to write an Iterator for a class in the Standard Library, but in reality, that’s what you most likely will have to do in real apps.

Example iterator class diagram

 

Job Offers

Job Offers

There are currently no vacancies.

OUR VIDEO RECOMMENDATION

, ,

Migrating to Jetpack Compose – an interop love story

Most of you are familiar with Jetpack Compose and its benefits. If you’re able to start anew and create a Compose-only app, you’re on the right track. But this talk might not be for you…
Watch Video

Migrating to Jetpack Compose - an interop love story

Simona Milanovic
Android DevRel Engineer for Jetpack Compose
Google

Migrating to Jetpack Compose - an interop love story

Simona Milanovic
Android DevRel Engin ...
Google

Migrating to Jetpack Compose - an interop love story

Simona Milanovic
Android DevRel Engineer f ...
Google

Jobs

We’ll use the Iterator interface from the standard library. The same goes for List :

public interface Iterator<out T> {
    public operator fun next(): T
    public operator fun hasNext(): Boolean
}

public interface List<out E> : Collection<E> {
    // There's too much unnecessary code to show it here
}

Now for our Iterator. Please don’t get into the details of the code. What matters is that we’re implementing Iterator<T> interface:

class MiddleListIterator<out T>(
    private val list: List<T>,
) : Iterator<T> {
    private var cycles = 0
    private var previousRight = true

    override fun hasNext(): Boolean = if (previousRight) {
        list.size / 2 + cycles < list.size
    } else {
        list.size / 2 - cycles >= 0
    }

    override fun next(): T = if (previousRight) {
        previousRight = false
        val element = list[list.size / 2 - cycles]
        cycles++
        element
    } else {
        previousRight = true
        list[list.size / 2 + cycles]
    }
}

How to use it?

fun main() {
    val list = listOf(4, 2, 0, 1, 3)
    val middleIterator = MiddleListIterator(list)
    while (middleIterator.hasNext()) {
        print("${middleIterator.next()} ") // 0 1 2 3 4
    }
    // Or use built-in forEach for Iterator
    middleIterator.forEach {value ->
        print("$value ") // 0 1 2 3 4
    }
}

We’re even able to use build-in extension functions for Iterator !

If you’re comfortable with the Extension function in your project, you can add it:

fun <T> List<T>.middleIterator() = MiddleListIterator(this)

Then you would use it like this:

fun main() {
    val list = listOf(4, 2, 0, 1, 3)
    list.middleIterator().forEach {value ->
        print("$value ") // 0 1 2 3 4
    }
}

Thanks for reading! Please clap if you learned something, and follow me for more!

Learn more about design patterns:

https://medium.com/@michalankiersztajn/list/design-patterns-in-kotlin-12e52466affe?source=post_page—–75be6bedfd79——————————–

Based on the book:

“Wzorce projektowe : elementy oprogramowania obiektowego wielokrotnego użytku” — Erich Gamma Autor; Janusz Jabłonowski (Translator); Grady Booch (Introduction author); Richard Helm (Author); Ralph Johnson (Author); John M Vlissides (Author)

This article is previously published on proandroiddev.com

YOU MAY BE INTERESTED IN

YOU MAY BE INTERESTED IN

blog
It’s one of the common UX across apps to provide swipe to dismiss so…
READ MORE
blog
Hi, today I come to you with a quick tip on how to update…
READ MORE
blog
Automation is a key point of Software Testing once it make possible to reproduce…
READ MORE
blog
Drag and Drop reordering in Recyclerview can be achieved with ItemTouchHelper (checkout implementation reference).…
READ MORE

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.

Menu