9.3 KiB
Iterable interface
The interface for anything that can be iterated, e.g. finite or infinite ordered set of data that can be accessed
sequentially. Almost any data container in Lyng implements it: List, Set, Buffer, RingBuffer, BitBuffer,
Range and many others are Iterable, also Collection and Array interfaces inherit it.
Map and String have Iterable members to access its contents too.
Please see also Collection interface: many iterables are also collections, and it adds important features.
Definition:
Iterable is a class that provides function that creates the iterator:
class Iterable {
abstract fun iterator()
}
Note that each call of iterator() must provide an independent iterator.
Iterator itself is a simple interface that should provide only to method:
class Iterator {
abstract fun hasNext(): Bool
fun next(): Obj
}
Just remember at this stage typed declarations are not yet supported.
Having Iterable in base classes allows to use it in for loop. Also, each Iterable has some utility functions
available, for example
val r = 1..10 // Range is Iterable!
assertEquals( [9,10], r.takeLast(2).toList() )
assertEquals( [1,2,3], r.take(3).toList() )
assertEquals( [9,10], r.drop(8).toList() )
assertEquals( [1,2], r.dropLast(8).toList() )
>>> void
joinToString
This methods convert any iterable to a string joining string representation of each element, optionally transforming it and joining using specified separator.
Iterable.joinToString(separator=' ', transformer=null)
- if
IterableisEmpty, the empty string""is returned. separatoris inserted between items when there are more than one.transformerof specified is applied to each element, otherwise itstoString()method is used.
Here is the sample:
assertEquals( (1..3).joinToString(), "1 2 3")
assertEquals( (1..3).joinToString(":"), "1:2:3")
assertEquals( (1..3).joinToString { it * 10 }, "10 20 30")
>>> void
sum and sumOf
These, again, does the thing:
assertEquals( 6, [1,2,3].sum() )
assertEquals( 12, [1,2,3].sumOf { it*2 } )
// sum of empty collections is null:
assertEquals( null, [].sum() )
assertEquals( null, [].sumOf { 2*it } )
>>> void
map, filter and their variations
Used to transform or filter the whole iterable stream:
val source = [1,2,3,4]
// map: transform every element to something else
assertEquals(["n1", "n2", "n3", "n4"], source.map { "n"+it } )
// filter: keep only elements matching the predicate
assertEquals([2, 4], source.filter { it % 2 == 0 } )
// count: count elements matching the predicate
assertEquals(2, source.count { it % 2 == 0 } )
// mapNotNull: transform every element, skipping null results:
assertEquals(["n1", "n2", "n4"], source.mapNotNull { if( it == 3 ) null else "n"+it } )
// filterNotNull: skip all null elements:
assertEquals([1, 2, 4], [1, 2, null, 4].filterNotNull())
>>> void
You can also use flow variations that return a cold Flow instead of a List, which is useful for large or infinite sequences:
val source = [1, 2, 3, 4]
// filterFlow: returns a Flow of filtered elements
assert( source.filterFlow { it % 2 == 0 } is Flow )
// filterFlowNotNull: returns a Flow of non-null elements
assert( [1, null, 2].filterFlowNotNull() is Flow )
>>> void
minOf and maxOf
Find the minimum or maximum value of a function applied to each element:
val source = ["abc", "de", "fghi"]
assertEquals(2, source.minOf { it.length })
assertEquals(4, source.maxOf { it.length })
>>> void
flatten and flatMap
Work with nested collections:
val nested = [[1, 2], [3, 4]]
// flatten: combine nested collections into one list
assertEquals([1, 2, 3, 4], nested.flatten())
// flatMap: map each element to a collection and flatten the result
assertEquals([1, 10, 2, 20], [1, 2].flatMap { [it, it*10] })
>>> void
findFirst and findFirstOrNull
Search for the first element that satisfies the given predicate:
val source = [1, 2, 3, 4]
assertEquals( 2, source.findFirst { it % 2 == 0 } )
assertEquals( 2, source.findFirstOrNull { it % 2 == 0 } )
// findFirst throws if not found:
assertThrows( NoSuchElementException ) { source.findFirst { it > 10 } }
// findFirstOrNull returns null if not found:
assertEquals( null, source.findFirstOrNull { it > 10 } )
>>> void
Instance methods:
| fun/method | description |
|---|---|
| toList() | create a list from iterable |
| toSet() | create a set from iterable |
| contains(i) | check that iterable contains i |
i in iterable |
same as contains(i) |
| isEmpty() | check iterable is empty |
| forEach(f) | call f for each element |
| toMap() | create a map from list of key-value pairs (arrays of 2 items or like) |
| any(p) | true if any element matches predicate p |
| all(p) | true if all elements match predicate p |
| map(f) | create a list of values returned by f called for each element of the iterable |
| indexOf(i) | return index if the first encounter of i or a negative value if not found |
| associateBy(kf) | create a map where keys are returned by kf that will be called for each element |
| filter(p) | create a list of elements matching predicate p |
| count(p) | count elements matching predicate p |
| filterFlow(p) | create a Flow of elements matching predicate p |
| filterNotNull() | create a list of non-null elements |
| filterFlowNotNull() | create a Flow of non-null elements |
| minOf(f) | return minimum value of f applied to elements |
| maxOf(f) | return maximum value of f applied to elements |
| flatten() | flatten nested collections into a single List |
| flatMap(f) | map each element with f and flatten results into a List |
| findFirst(p) | return first element matching predicate p or throw (1) |
| findFirstOrNull(p) | return first element matching predicate p or null |
| first | first element (1) |
| last | last element (1) |
| take(n) | return [Iterable] of up to n first elements |
| takeLast(n) | return [Iterable] of up to n last elements |
| drop(n) | return new [Iterable] without first n elements |
| dropLast(n) | return new [Iterable] without last n elements |
| sum() | return sum of the collection applying + to its elements (3) |
| sumOf(f) | sum of the modified collection items (3) |
| sorted() | return List with collection items sorted naturally |
| sortedWith(comparator) | sort using a comparator that compares elements (1) |
| sortedBy(predicate) | sort by comparing results of the predicate function |
| joinToString(s,t) | convert iterable to string, see (2) |
| reversed() | create a list containing items from this in reverse order |
| shuffled() | create a list of shuffled elements |
(1)
:: throws NoSuchElementException if there is no such element
(2)
:: joinToString(separator=" ", transformer=null): separator is inserted between items if there are more than one, transformer is
optional function applied to each item that must return result string for an item, otherwise item.toString() is used.
(3)
:: sum of empty collection is null
Abstract methods:
fun iterator(): Iterator
For high-performance Kotlin-side interop and custom iterable implementation details, see Efficient Iterables in Kotlin Interop.
Included in interfaces:
- Collection, Array, List
Implemented in classes:
- List, Range, Buffer, [BitBuffer], [Buffer], Set, RingBuffer