I have Set<FlagFilter>
and I need to convert it to Map<Class<out FlagFilter>, FlagFilter>
.
I tried doing it like this:
val result: Map<Class<out FlagFilter>, FlagFilter> =
target
.takeIf { !it.isEmpty() }
?.map { mapOf(it.javaClass to it) }
?: emptyMap<>()
but instead of a Map
it turns out to be a List
and I get a compilation error:
Type mismatch.
Required: Map<Class<out FlagFilter>, FlagFilter>
Found: List<Map<Class<FlagFilter>, FlagFilter>>
What am I doing wrong? As if there is not enough operation, but I do not understand yet which one
CodePudding user response:
map
isn't anything to do with the Map
type - it's a functional programming term (coming from a broader mathematical concept) that basically means a function that maps each input value to an output value.
So it's a transformation or conversion that takes a collection of items, transforms each one, and results in another collection with the same number of items. In Kotlin, you get a List
of items (unless you're working with a Sequence
, in which case you get another Sequence
that yields the same number of items).
It's worth getting familiar with the kotlin.collections package - there's lots of useful stuff in there! But each function has a specific purpose, in terms of how they process the collection and what they return:
map
- returns a new value for each itemonEach
- returns the original items (allows you to do something with each, then continue processing the collection)forEach
- returns nothing (allows you to do something with each, but as a final operation - you can't chain another operation, it's terminal)filter
- returns a subset of the original items, matching a predicatefirst
- returns a single item, matching a predicatereduce
- returns a single item, transforming the values to produce a single resultcount
- returns a single item, based on an attribute of the collection (not the values themselves)
There's more but you get the idea - some things transform, some things pass-through, some things give you an identically sized collection, or a potentially smaller one, or a single value. map
is just the one that takes a collection, and gives you a collection of the same size where every item has been (potentially) altered.
Like Vadik says, use one of the associate*
functions to turn values into a Map
object, effectively transforming each item in the collection into a Map.Entry
. Which is technically mapping it to a mapping, so I wasn't totally accurate earlier when I said it's nothing to do with Map
s, but I figured I'd save this thought til the end ;)
CodePudding user response:
Just use associateBy
extension function:
val result: Map<Class<out FlagFilter>, FlagFilter> =
target.associateBy { it.javaClass }
Or if you want to fix your code, remove the excessive call of mapOf(). Just convert your Set to List of Pairs, and then call toMap() to create a map:
val result: Map<Class<out FlagFilter>, FlagFilter> =
target.map { it.javaClass to it }.toMap()