Split AbstractMap into readonly and mutable.
This commit is contained in:
@@ -20,7 +20,7 @@
|
||||
|
||||
package kotlin.collections
|
||||
|
||||
public abstract class AbstractMap<K, V> protected constructor() : MutableMap<K, V> {
|
||||
public abstract class AbstractMutableMap<K, V> protected constructor() : AbstractMap<K, V>(), MutableMap<K, V> {
|
||||
|
||||
/**
|
||||
* A mutable [Map.Entry] shared by several [Map] implementations.
|
||||
@@ -44,67 +44,14 @@ public abstract class AbstractMap<K, V> protected constructor() : MutableMap<K,
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* An immutable [Map.Entry] shared by several [Map] implementations.
|
||||
*/
|
||||
class SimpleImmutableEntry<out K, out V>(override val key: K, override val value: V) : Map.Entry<K, V> {
|
||||
constructor(entry: Map.Entry<K, V>) : this(entry.key, entry.value)
|
||||
|
||||
override fun hashCode(): Int = entryHashCode(this)
|
||||
override fun toString(): String = entryToString(this)
|
||||
override fun equals(other: Any?): Boolean = entryEquals(this, other)
|
||||
}
|
||||
|
||||
|
||||
override fun clear() {
|
||||
entries.clear()
|
||||
}
|
||||
|
||||
override fun containsKey(key: K): Boolean {
|
||||
return implFindEntry(key, false) != null
|
||||
}
|
||||
|
||||
override fun containsValue(value: V): Boolean = entries.any { it.value == value }
|
||||
|
||||
internal fun containsEntry(entry: Map.Entry<*, *>?): Boolean {
|
||||
// since entry comes from @UnsafeVariance parameters it can be virtually anything
|
||||
if (entry !is Map.Entry<*, *>) return false
|
||||
val key = entry.key
|
||||
val value = entry.value
|
||||
val ourValue = get(key)
|
||||
|
||||
if (value != ourValue) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Perhaps it was null and we don't contain the key?
|
||||
if (ourValue == null && !containsKey(key)) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other === this) return true
|
||||
if (other !is Map<*, *>) return false
|
||||
if (size != other.size) return false
|
||||
|
||||
return other.entries.all { containsEntry(it) }
|
||||
}
|
||||
|
||||
override operator fun get(key: K): V? = implFindEntry(key, false)?.value
|
||||
|
||||
override fun hashCode(): Int = entries.hashCode()
|
||||
|
||||
override fun isEmpty(): Boolean = size == 0
|
||||
override val size: Int get() = entries.size
|
||||
|
||||
|
||||
override val keys: MutableSet<K> get() {
|
||||
return object : AbstractMutableSet<K>() {
|
||||
override fun clear() {
|
||||
this@AbstractMap.clear()
|
||||
this@AbstractMutableMap.clear()
|
||||
}
|
||||
|
||||
override operator fun contains(element: K): Boolean = containsKey(element)
|
||||
@@ -120,13 +67,13 @@ public abstract class AbstractMap<K, V> protected constructor() : MutableMap<K,
|
||||
|
||||
override fun remove(element: K): Boolean {
|
||||
if (containsKey(element)) {
|
||||
this@AbstractMap.remove(element)
|
||||
this@AbstractMutableMap.remove(element)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override val size: Int get() = this@AbstractMap.size
|
||||
override val size: Int get() = this@AbstractMutableMap.size
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,17 +87,9 @@ public abstract class AbstractMap<K, V> protected constructor() : MutableMap<K,
|
||||
}
|
||||
}
|
||||
|
||||
override fun remove(key: K): V? = implFindEntry(key, true)?.value
|
||||
|
||||
override fun toString(): String = entries.joinToString(", ", "{", "}") { toString(it) }
|
||||
|
||||
private fun toString(entry: Map.Entry<K, V>): String = toString(entry.key) + "=" + toString(entry.value)
|
||||
|
||||
private fun toString(o: Any?): String = if (o === this) "(this Map)" else o.toString()
|
||||
|
||||
override val values: MutableCollection<V> get() {
|
||||
return object : AbstractMutableCollection<V>() {
|
||||
override fun clear() = this@AbstractMap.clear()
|
||||
override fun clear() = this@AbstractMutableMap.clear()
|
||||
|
||||
override operator fun contains(element: V): Boolean = containsValue(element)
|
||||
|
||||
@@ -163,7 +102,7 @@ public abstract class AbstractMap<K, V> protected constructor() : MutableMap<K,
|
||||
}
|
||||
}
|
||||
|
||||
override val size: Int get() = this@AbstractMap.size
|
||||
override val size: Int get() = this@AbstractMutableMap.size
|
||||
|
||||
// TODO: should we implement them this way? Currently it's unspecified in JVM
|
||||
override fun equals(other: Any?): Boolean {
|
||||
@@ -175,29 +114,18 @@ public abstract class AbstractMap<K, V> protected constructor() : MutableMap<K,
|
||||
}
|
||||
}
|
||||
|
||||
private fun implFindEntry(key: K, remove: Boolean): Map.Entry<K, V>? {
|
||||
override fun remove(key: K): V? {
|
||||
val iter = entries.iterator()
|
||||
while (iter.hasNext()) {
|
||||
var entry = iter.next()
|
||||
val k = entry.key
|
||||
if (key == k) {
|
||||
if (remove) {
|
||||
entry = SimpleEntry(entry)
|
||||
iter.remove()
|
||||
}
|
||||
return entry
|
||||
val value = entry.value
|
||||
iter.remove()
|
||||
return value
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
internal fun entryHashCode(e: Map.Entry<*, *>): Int = with(e) { (key?.hashCode() ?: 0) xor (value?.hashCode() ?: 0) }
|
||||
internal fun entryToString(e: Map.Entry<*, *>): String = with(e) { "$key=$value" }
|
||||
internal fun entryEquals(e: Map.Entry<*, *>, other: Any?): Boolean {
|
||||
if (other !is Map.Entry<*, *>) return false
|
||||
return e.key == other.key && e.value == other.value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ package kotlin.collections
|
||||
import kotlin.collections.Map.Entry
|
||||
import kotlin.collections.MutableMap.MutableEntry
|
||||
|
||||
open class HashMap<K, V> : AbstractMap<K, V> {
|
||||
public open class HashMap<K, V> : AbstractMutableMap<K, V> {
|
||||
|
||||
private inner class EntrySet : AbstractMutableSet<MutableEntry<K, V>>() {
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
package kotlin.collections
|
||||
|
||||
import kotlin.collections.MutableMap.MutableEntry
|
||||
import kotlin.collections.AbstractMap.SimpleEntry
|
||||
import kotlin.collections.AbstractMutableMap.SimpleEntry
|
||||
|
||||
/**
|
||||
* A simple wrapper around JavaScriptObject to provide [java.util.Map]-like semantics for any
|
||||
|
||||
@@ -21,7 +21,7 @@ package kotlin.collections
|
||||
|
||||
import kotlin.collections.MutableMap.MutableEntry
|
||||
|
||||
open class LinkedHashMap<K, V> : HashMap<K, V>, Map<K, V> {
|
||||
public open class LinkedHashMap<K, V> : HashMap<K, V>, Map<K, V> {
|
||||
|
||||
/**
|
||||
* The entry we use includes next/prev pointers for a doubly-linked circular
|
||||
@@ -35,7 +35,7 @@ open class LinkedHashMap<K, V> : HashMap<K, V>, Map<K, V> {
|
||||
* small modifications. Paying a small storage cost only if you use
|
||||
* LinkedHashMap and minimizing code size seemed like a better tradeoff
|
||||
*/
|
||||
private class ChainEntry<K, V>(key: K, value: V) : AbstractMap.SimpleEntry<K, V>(key, value) {
|
||||
private class ChainEntry<K, V>(key: K, value: V) : AbstractMutableMap.SimpleEntry<K, V>(key, value) {
|
||||
internal var next: ChainEntry<K, V>? = null
|
||||
internal var prev: ChainEntry<K, V>? = null
|
||||
}
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/*
|
||||
* Based on GWT AbstractMap
|
||||
* Copyright 2007 Google Inc.
|
||||
*/
|
||||
|
||||
package kotlin.collections
|
||||
|
||||
public abstract class AbstractMap<K, out V> protected constructor() : Map<K, V> {
|
||||
|
||||
override fun containsKey(key: K): Boolean {
|
||||
return implFindEntry(key) != null
|
||||
}
|
||||
|
||||
override fun containsValue(value: @UnsafeVariance V): Boolean = entries.any { it.value == value }
|
||||
|
||||
internal fun containsEntry(entry: Map.Entry<*, *>?): Boolean {
|
||||
// since entry comes from @UnsafeVariance parameters it can be virtually anything
|
||||
if (entry !is Map.Entry<*, *>) return false
|
||||
val key = entry.key
|
||||
val value = entry.value
|
||||
val ourValue = get(key)
|
||||
|
||||
if (value != ourValue) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Perhaps it was null and we don't contain the key?
|
||||
if (ourValue == null && !containsKey(key)) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other === this) return true
|
||||
if (other !is Map<*, *>) return false
|
||||
if (size != other.size) return false
|
||||
|
||||
return other.entries.all { containsEntry(it) }
|
||||
}
|
||||
|
||||
override operator fun get(key: K): V? = implFindEntry(key)?.value
|
||||
|
||||
override fun hashCode(): Int = entries.hashCode()
|
||||
|
||||
override fun isEmpty(): Boolean = size == 0
|
||||
override val size: Int get() = entries.size
|
||||
|
||||
|
||||
override val keys: Set<K> get() {
|
||||
return object : AbstractSet<K>() {
|
||||
override operator fun contains(element: K): Boolean = containsKey(element)
|
||||
|
||||
override operator fun iterator(): Iterator<K> {
|
||||
val outerIter = entries.iterator()
|
||||
return object : Iterator<K> {
|
||||
override fun hasNext(): Boolean = outerIter.hasNext()
|
||||
override fun next(): K = outerIter.next().key
|
||||
}
|
||||
}
|
||||
|
||||
override val size: Int get() = this@AbstractMap.size
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(): String = entries.joinToString(", ", "{", "}") { toString(it) }
|
||||
|
||||
private fun toString(entry: Map.Entry<K, V>): String = toString(entry.key) + "=" + toString(entry.value)
|
||||
|
||||
private fun toString(o: Any?): String = if (o === this) "(this Map)" else o.toString()
|
||||
|
||||
override val values: Collection<V> get() {
|
||||
return object : AbstractCollection<V>() {
|
||||
override operator fun contains(element: @UnsafeVariance V): Boolean = containsValue(element)
|
||||
|
||||
override operator fun iterator(): Iterator<V> {
|
||||
val outerIter = entries.iterator()
|
||||
return object : Iterator<V> {
|
||||
override fun hasNext(): Boolean = outerIter.hasNext()
|
||||
override fun next(): V = outerIter.next().value
|
||||
}
|
||||
}
|
||||
|
||||
override val size: Int get() = this@AbstractMap.size
|
||||
|
||||
// TODO: should we implement them this way? Currently it's unspecified in JVM
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other !is Collection<*>) return false
|
||||
return AbstractList.orderedEquals(this, other)
|
||||
}
|
||||
override fun hashCode(): Int = AbstractList.orderedHashCode(this)
|
||||
}
|
||||
}
|
||||
|
||||
private fun implFindEntry(key: K): Map.Entry<K, V>? = entries.firstOrNull { it.key == key }
|
||||
|
||||
internal companion object {
|
||||
|
||||
internal fun entryHashCode(e: Map.Entry<*, *>): Int = with(e) { (key?.hashCode() ?: 0) xor (value?.hashCode() ?: 0) }
|
||||
internal fun entryToString(e: Map.Entry<*, *>): String = with(e) { "$key=$value" }
|
||||
internal fun entryEquals(e: Map.Entry<*, *>, other: Any?): Boolean {
|
||||
if (other !is Map.Entry<*, *>) return false
|
||||
return e.key == other.key && e.value == other.value
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,4 +3,5 @@ package kotlin.collections
|
||||
|
||||
public typealias AbstractMutableCollection<E> = java.util.AbstractCollection<E>
|
||||
public typealias AbstractMutableList<E> = java.util.AbstractList<E>
|
||||
public typealias AbstractMutableSet<E> = java.util.AbstractSet<E>
|
||||
public typealias AbstractMutableSet<E> = java.util.AbstractSet<E>
|
||||
public typealias AbstractMutableMap<K, V> = java.util.AbstractMap<K, V>
|
||||
@@ -125,6 +125,30 @@ public abstract class kotlin/collections/AbstractList : kotlin/collections/Abstr
|
||||
public fun toArray ([Ljava/lang/Object;)[Ljava/lang/Object;
|
||||
}
|
||||
|
||||
public abstract class kotlin/collections/AbstractMap : java/util/Map, kotlin/jvm/internal/markers/KMappedMarker {
|
||||
public static final field Companion Lkotlin/collections/AbstractMap$Companion;
|
||||
protected fun <init> ()V
|
||||
public fun clear ()V
|
||||
public fun containsKey (Ljava/lang/Object;)Z
|
||||
public fun containsValue (Ljava/lang/Object;)Z
|
||||
public final fun entrySet ()Ljava/util/Set;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public fun get (Ljava/lang/Object;)Ljava/lang/Object;
|
||||
public abstract fun getEntries ()Ljava/util/Set;
|
||||
public fun getKeys ()Ljava/util/Set;
|
||||
public fun getSize ()I
|
||||
public fun getValues ()Ljava/util/Collection;
|
||||
public fun hashCode ()I
|
||||
public fun isEmpty ()Z
|
||||
public final fun keySet ()Ljava/util/Set;
|
||||
public fun put (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
|
||||
public fun putAll (Ljava/util/Map;)V
|
||||
public fun remove (Ljava/lang/Object;)Ljava/lang/Object;
|
||||
public final fun size ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
public final fun values ()Ljava/util/Collection;
|
||||
}
|
||||
|
||||
public abstract class kotlin/collections/AbstractSet : kotlin/collections/AbstractCollection, java/util/Set, kotlin/jvm/internal/markers/KMappedMarker {
|
||||
public static final field Companion Lkotlin/collections/AbstractSet$Companion;
|
||||
protected fun <init> ()V
|
||||
|
||||
Reference in New Issue
Block a user