6

I am probably missing something very obvious: How do I efficiently filter and iterate through the entries of a HashMap in Kotlin?

I want to do the following:

myMap.filterValues{ someCondition }.forEach { doSomethingWithTheEntry }

How can I avoid the creation of intermediate objects? filterValues will create a HashMap, which is not really needed here.

I could of course write

myMap.forEach { if(someCondition) doSomethingWithTheEntry }

but the functional-style filter approach looks more elegant.

trunklop
  • 383
  • 2
  • 10

1 Answers1

8

To avoid storing intermediate values, you can use Sequence, which is somewhat a lazy equivalent of Iterable (see another Q&A for details).

To process the entries of a Map as a Sequence, convert it with .asSequence() (again, no intermediate collection is created) and then use .filter { ... } and .forEach { ... } on the sequence:

myMap.asSequence().filter { someCondition(it) }.forEach { doSomething(it) }

This will create a pipeline which will query the entries one by one, check the predicate on them and, if matched, run the action, without storing the intermediate values.

Efficiency, however, depends on the collection size and the complexity of the operations, because the laziness of Sequence does not come for free: it introduces some overhead, which may become considerable if you only run simple transformations of small collections in performance-critical code.

hotkey
  • 140,743
  • 39
  • 371
  • 326
  • Thanks. "Sequence" was the key word I was looking for. I assume "myMap.entries.asSequence()" and "myMap.asSequence()" are equivalent? – trunklop Mar 05 '18 at 12:25
  • You're welcome. Yes, they are, good point, updated the answer. – hotkey Mar 05 '18 at 12:28