kotlinjvm

How to handle JRE Null Iterator Interfaces cleanly in Kotlin


Some of the standard interfaces provided by the JRE are "Null Iterators" (sorry I don't know a better name) meaning they have the rough semantics of an iterator, except that they use a single method which returns null to indicate the last item has been returned, for example, ZipInputStream provides such an interface:

    ZipInputStream(stream).use { zip ->
        while (true) {
            val entry = zip.getNextEntry() ?: break
            if (entry.name.endsWith(".txt"))
                println(entry.name)
        }
    }

In Kotlin it's possible to process such an interface using a combination of a while(true) and an Elvis operator with a break (as shown above).

Is there a "cleanish" / kotlin'ish way to eliminate the while(true), I can think of several ways to eliminate it, however I wouldn't consider any of my ideas to be as clean as the code above.

Note: I know that ZipInputStream has an available() method, I am not looking for a specific solution for ZipInputStream, instead a generic solution that will work with any interface, that only has a single method - that returns null to indicate the last item has been processed.


Solution

  • The lambda parameter to generateSequence has the same semantics - returns null when the sequence ends.

    So you can do:

    for (thing in generateSequence { getNextThing() }) {
        // ...
    }
    

    where getNextThing is the method that you want to call, that returns null to indicate the end of the sequence.