https://kotlinlang.org logo
Title
k

klizter

03/20/2019, 3:07 PM
Is it possible to create Kotlin
Map
where key is
String
and case insensitive?
a

amanda.hinchman-dominguez

03/20/2019, 3:08 PM
If anything, you might just want to process it before like
mapName[keyName.toLowerCase()]
or something
☝️ 1
a

Alowaniak

03/20/2019, 3:09 PM
Maybe make your own Map doing that preprocessing
s

streetsofboston

03/20/2019, 3:10 PM
You could also create you own key type:
class LowerCase(val value: String) {
  // write your own equals and hashCode to make it case insensitive
}
and have some nice toplevel or extension function to create a LowerCase from a String
👍 1
d

David Cuesta

03/20/2019, 3:10 PM
Just wrap the String into a data class that extends from Comparator and then implement the compators
k

karelpeeters

03/20/2019, 3:15 PM
Comparator
? That's not really necessary here, right?
k

klizter

03/20/2019, 3:15 PM
The thing is, AWS does some magic when mapping requests to the open class request contract. Can’t find a way to intervene that process. Going to check key type @streetsofboston – looks promising
f

Fredrik Larsen

03/20/2019, 3:16 PM
On Android be very careful with toLowerCase(). It'll use the default locale and on e.g. Turkish devices the
i
will be replaced with
ı
.
d

David Cuesta

03/20/2019, 3:20 PM
Sorry I had a lapsus, it is enough with hashCode and Equeals
k

klizter

03/20/2019, 3:33 PM
data class HeaderName(val key: String) {

    override fun hashCode() = key.toLowerCase().hashCode()

    override fun equals(other: Any?): Boolean {
        return this.hashCode() == other.hashCode()
    }
}
Looks good?
k

karelpeeters

03/20/2019, 3:34 PM
No! Hashes aren't unique!
Also now you're using the default locale instead of a fixed one.
a

amanda.hinchman-dominguez

03/20/2019, 3:35 PM
I mean, depending on the use, they could be unique enough, right?
k

karelpeeters

03/20/2019, 3:35 PM
And you don't do type checking in
equals
at all, there's a bunch of stuff you need to check there.
k

klizter

03/20/2019, 3:37 PM
Now I’m really confused. I opened REPL and made to strings that are similar, and did hashCode(), they are the same.
k

karelpeeters

03/20/2019, 3:37 PM
@amanda.hinchman-dominguez Depending on hashcodes of strings being distinct is a terrible idea, there are lots of 3-letter collision examples.
What you have now will always say equal strings are equal, but there are also non-equal things that it's going to say are equal.
k

klizter

03/20/2019, 3:38 PM
god damnit, that’s definitely not good
a

amanda.hinchman-dominguez

03/20/2019, 3:39 PM
Yeah, to @karelpeeters point, I'm not sure why there are unique keys being made if they're not case sensitive
k

karelpeeters

03/20/2019, 3:40 PM
I think this is correct:
class HeaderName(val key: String) {
	override fun hashCode() = key.toLowerCase(Locale.ROOT).hashCode()

	override fun equals(other: Any?): Boolean {
		if (this === other) return true
		if (javaClass != other?.javaClass) return false
		other as HeaderName
		
		return key.toLowerCase(Locale.ROOT) == other.key.toLowerCase(Locale.ROOT)
	}
}
You can also keep the
toLowerCase
result:
class HeaderName(key: String) {
	val key = key.toLowerCase(Locale.ROOT)
	
	override fun hashCode() = key.hashCode()

	override fun equals(other: Any?): Boolean {
		if (this === other) return true
		if (javaClass != other?.javaClass) return false
		other as HeaderName

		return key == other.key
	}
}
k

klizter

03/20/2019, 3:47 PM
Thanks, that’s definitely more strict