Alex Craft
Alex Craft

Reputation: 15416

How can I define Map of String or Int in Kotlin?

Is there way to declare a Map that would accept both String and Int in Kotlin? Like:

var map: Map<String, String | Int>

Upvotes: 1

Views: 3136

Answers (2)

Joffrey
Joffrey

Reputation: 37829

There is no union type in Kotlin, so you can't directly express this.

A few options:

  1. use TreeMap<String, Any>, which is the simplest of all, but it allows more types than just Int and String, and requires additional conversion boilerplate on the consumer side when accessing values.

  2. use a custom sealed class to encapsulate your "Int or String" type, and use it in a regular TreeMap<String, IntOrString>. This will have some runtime overhead for wrapping/unwrapping the int/string objects for each insertion/access. Also, this puts the burden of (un)wrapping on the consumer side. That being said, maybe your domain can be better modeled with clearer names than Int or String, so it might actually improve the consumer's experience to define such types.

  3. use a custom map type, with independent accessors for ints and strings, but backed by a single TreeMap<String, Any> behind the scenes. This has the advantage of encapsulating the logic and exposing a neat API for the consumers. If you extend TreeMap you will save some overhead as opposed to composition, but it shouldn't matter much.

I am wondering about the actual use case at hand, though. Usually the need for union types stems from using plain generic primitive types to represent meaningful domain data that could maybe better be expressed using more specific custom domain types.

Option 2 would therefore usually be my choice, but I would use a sealed class that actually represents my domain data instead of the generic "string or int".

Upvotes: 6

deHaar
deHaar

Reputation: 18588

You can use Any here, see this example:

import java.util.TreeMap

fun main() {
    var map = TreeMap<String, Any>()
    map.put("One", 1)
    map.put("Two", "two")
    println(map)
}

which outputs

{One=1, Two=two}

Please note:
This will allow more types than just the desired String and Int, because the Kotlin Docs state (...). Every Kotlin class has Any as a superclass..

Upvotes: 3

Related Questions