Skip to content

Latest commit

 

History

History
119 lines (90 loc) · 4.5 KB

07_iterator.adoc

File metadata and controls

119 lines (90 loc) · 4.5 KB

Extensions to Iterator

To map from an Iterator (over references) to a PrimitiveIterators, the class de.fhg.fokus.xtensions.iteration.IteratorExtensions provides the methods mapInt, mapLong and mapDouble.

import static java.util.stream.Collectors.*
import static extension de.fhg.fokus.xtensions.iteration.IteratorExtensions.*
// ...
val Iterable<String> strings = #["fooooo", "baar", "baz"]
val summary = strings.iterator.mapInt[length].summarize
println("Size of longest string is " + summary.max)
Tip
See Primitive Iterators for more information on the summarize extension function.

To exclude elements of one Iterable from the sequence provided by an Iterator, the method withoutAll can be used.

val s = #["I", "boo", "pity", "char", "the", "fool"]
	.iterator
	.withoutAll(#{"boo", "char"})
	.join(" ")
println(s)
Caution
Performance of withoutAll is best when using an appropriate java.util.Set, such as HashSet for the elements to exclude.

To partition the elements provided by an iterator based on a predicate or the class (elements are tested to be instance of) into two parts: selected and rejected. The selected part will contain the elements for which the predicate evaluates to true or elements are instance of the given partitioning class. The rejected part will contain the other elements.

Example:

import static extension de.fhg.fokus.xtensions.iteration.IteratorExtensions.*
// ...
val char[] chars = #[0x0020 as char, 0x0034 as char]
val List<CharSequence> list = #[
	"Hello",
	new StringBuilder().append(chars),
	"Xtend",
	new StringBuilder().append(0x0032 as char)
]
list.iterator.partitionBy(String) => [
	println('''Selected: "«selected.join(" ")»"''')
	println('''Rejected: "«rejected.join("")»"''')
]

For both versions of the partitionBy method there exist overloads that take instances of Collector.

Example:

import static extension de.fhg.fokus.xtensions.iteration.IteratorExtensions.*
import static java.util.stream.Collectors.*
import java.util.Set
import java.util.List
// ...
val list = #["foo", "bla", "foo", "hui", "fun"]
val partition = list.iterator.partitionBy([startsWith("f")], toSet, toList)
val Set<String> selected = partition.selected
val List<String> rejected = partition.rejected
println("Unique words starting with 'f' : " + selected.join(", "))
println("Other words: " + rejected.join(", "))

Note that the Collectors#partitioningBy Collector from the JDK aggregates into a Map<Boolean,List<T>> where T is the type of the elements in a collected stream. Another partitioningBy overload from Collectors aggregates the map values and returns a Map<Boolean,D> where D is the aggregation of a "downstream" Collector.

val list = #["foo", "bla", "foo", "hui", "fun"]
val partition = list.iterator.partitionBy([startsWith("f")], Collectors::toSet, Collectors::toList)
val Set<String> selected = partition.selected
val List<String> rejected = partition.rejected
println("Unique words starting with 'f' : " + selected.join(", "))
println("Other words: " + rejected.join(", "))

To allow a similar workflow to the JDK version, for the Partition of this library a asMap extension method is provided for Partitions having the same type for the selected and rejected part. The other way around an extension method is provided to wrap a Map<Boolean,X> into a Partition<X,X>.

To add elements from an Iterator to one or more collections, the into extension method is provided by the class IterableExtensions.

Example:

val namesWithB = newArrayList("Barbara", "Bob", "Brian")
val newNames = #["Justin", "Anna", "Bruce", "Chris", "Becky"]
newNames.iterator
	.filter[it.toFirstLower.startsWith("b")]
	.into(namesWithB)

namesWithB.forEach[
	println(it)
]
Tip

Related JavaDocs: