不可为空的可变映射
Not nullable Mutable Map
- Java :
1.8.0_102
- 科特林:
1.0.4
我正在尝试创建一个地图,您可以在其中执行类似 map["key"] += 5
类似于 javascript 的操作。
Kotlin 已经有 withDefault
解决了这个问题的一部分,但是 map 的 get 函数仍然是 returns 一个可以为 null 的值,所以我开始自己实现这个,灵感来自 withDefault
interface NonNullableMutableMap<K,V> : MutableMap<K,V> {
override fun put(key: K, value: V): V
override fun get(key: K): V
}
fun <K,V> MutableMap<K,V>.withoutNullValues(default: () -> V): NonNullableMutableMap<K, V> {
return NonNullableMapWrapper(this, default)
}
class NonNullableMapWrapper<K,V>(val map: MutableMap<K,V>, val default: () -> V) : NonNullableMutableMap<K,V> {
override fun put(key: K, value: V): V = map.put(key, value) ?: default()
override fun get(key: K): V {
val value = map.getOrPut(key, default)
return value
}
override val size: Int get() = map.size
override fun containsKey(key: K): Boolean = map.containsKey(key)
override fun containsValue(value: V): Boolean = map.containsValue(value)
override fun isEmpty(): Boolean = map.isEmpty()
override val entries: MutableSet<MutableMap.MutableEntry<K, V>> get() = map.entries
override val keys: MutableSet<K> get() = map.keys
override val values: MutableCollection<V> get() = map.values
override fun clear() {
map.clear()
}
override fun putAll(from: Map<out K, V>) {
map.putAll(from)
}
override fun remove(key: K): V {
return map.remove(key) ?: default()
}
}
我创建了以下单元测试来测试它
class NonNullableMapTest {
@Test
fun notNullableTest() {
val map = HashMap<String, Long>().withoutNullValues { 0 }
map["first"] += 10L
map["second"] -= 10L
assertThat(map["first"]).isEqualTo(10L)
assertThat(map["second"]).isEqualTo(-10L)
assertThat(map["third"]).isEqualTo(0L)
}
}
但是我 运行 测试时出现以下错误:
tried to access method kotlin.collections.MapsKt__MapsJVMKt.set(Ljava/util/Map;Ljava/lang/Object;Ljava/lang/Object;)V from class foo.bar.NonNullableMapTest
java.lang.IllegalAccessError: tried to access method kotlin.collections.MapsKt__MapsJVMKt.set(Ljava/util/Map;Ljava/lang/Object;Ljava/lang/Object;)V from class foo.bar.NonNullableMapTest
知道如何解决这个问题吗?
我觉得这像是一个错误。我建议在 Kotlin (KT) | YouTrack.
报告
解决此问题的一种方法是在 NonNullableMutableMap
界面上显式定义 set
。例如:
interface NonNullableMutableMap<K, V> : MutableMap<K, V> {
override fun put(key: K, value: V): V
override fun get(key: K): V
operator fun set(key: K, value: V) {
put(key, value)
}
}
关于您遇到的运行时错误,目前在如何为内联 MutableMap.set
扩展函数编译 +=
运算符方面存在一个错误:https://youtrack.jetbrains.com/issue/KT-14227
解决方法是不使用 +=
:
map["first"] = map["first"] + 10L
- Java :
1.8.0_102
- 科特林:
1.0.4
我正在尝试创建一个地图,您可以在其中执行类似 map["key"] += 5
类似于 javascript 的操作。
Kotlin 已经有 withDefault
解决了这个问题的一部分,但是 map 的 get 函数仍然是 returns 一个可以为 null 的值,所以我开始自己实现这个,灵感来自 withDefault
interface NonNullableMutableMap<K,V> : MutableMap<K,V> {
override fun put(key: K, value: V): V
override fun get(key: K): V
}
fun <K,V> MutableMap<K,V>.withoutNullValues(default: () -> V): NonNullableMutableMap<K, V> {
return NonNullableMapWrapper(this, default)
}
class NonNullableMapWrapper<K,V>(val map: MutableMap<K,V>, val default: () -> V) : NonNullableMutableMap<K,V> {
override fun put(key: K, value: V): V = map.put(key, value) ?: default()
override fun get(key: K): V {
val value = map.getOrPut(key, default)
return value
}
override val size: Int get() = map.size
override fun containsKey(key: K): Boolean = map.containsKey(key)
override fun containsValue(value: V): Boolean = map.containsValue(value)
override fun isEmpty(): Boolean = map.isEmpty()
override val entries: MutableSet<MutableMap.MutableEntry<K, V>> get() = map.entries
override val keys: MutableSet<K> get() = map.keys
override val values: MutableCollection<V> get() = map.values
override fun clear() {
map.clear()
}
override fun putAll(from: Map<out K, V>) {
map.putAll(from)
}
override fun remove(key: K): V {
return map.remove(key) ?: default()
}
}
我创建了以下单元测试来测试它
class NonNullableMapTest {
@Test
fun notNullableTest() {
val map = HashMap<String, Long>().withoutNullValues { 0 }
map["first"] += 10L
map["second"] -= 10L
assertThat(map["first"]).isEqualTo(10L)
assertThat(map["second"]).isEqualTo(-10L)
assertThat(map["third"]).isEqualTo(0L)
}
}
但是我 运行 测试时出现以下错误:
tried to access method kotlin.collections.MapsKt__MapsJVMKt.set(Ljava/util/Map;Ljava/lang/Object;Ljava/lang/Object;)V from class foo.bar.NonNullableMapTest
java.lang.IllegalAccessError: tried to access method kotlin.collections.MapsKt__MapsJVMKt.set(Ljava/util/Map;Ljava/lang/Object;Ljava/lang/Object;)V from class foo.bar.NonNullableMapTest
知道如何解决这个问题吗?
我觉得这像是一个错误。我建议在 Kotlin (KT) | YouTrack.
报告解决此问题的一种方法是在 NonNullableMutableMap
界面上显式定义 set
。例如:
interface NonNullableMutableMap<K, V> : MutableMap<K, V> {
override fun put(key: K, value: V): V
override fun get(key: K): V
operator fun set(key: K, value: V) {
put(key, value)
}
}
关于您遇到的运行时错误,目前在如何为内联 MutableMap.set
扩展函数编译 +=
运算符方面存在一个错误:https://youtrack.jetbrains.com/issue/KT-14227
解决方法是不使用 +=
:
map["first"] = map["first"] + 10L