AbstractMap: cleanup and refactor

#KT-12386
This commit is contained in:
Ilya Gorbunov
2016-08-24 20:09:35 +03:00
parent c54bc2ea18
commit f5e0c504d6
2 changed files with 94 additions and 181 deletions
@@ -93,27 +93,11 @@ public abstract class AbstractList<E> protected constructor() : AbstractCollecti
override fun equals(other: Any?): Boolean {
if (other === this) return true
if (other !is List<*>) return false
if (size != other.size) return false
val otherIterator = other.iterator()
for (elem in this) {
val elemOther = otherIterator.next()
if (elem != elemOther) {
return false
}
}
return true
return orderedEquals(this, other)
}
override fun hashCode(): Int {
var hashCode = 1
for (e in this) {
hashCode = 31 * hashCode + (e?.hashCode() ?: 0)
hashCode = hashCode or 0 // make sure we don't overflow
}
return hashCode
}
override fun hashCode(): Int = orderedHashCode(this)
private open inner class IteratorImpl : MutableIterator<E> {
@@ -236,6 +220,28 @@ public abstract class AbstractList<E> protected constructor() : AbstractCollecti
throw IllegalArgumentException("fromIndex: $start > toIndex: $end")
}
}
internal fun orderedHashCode(c: Collection<*>): Int {
var hashCode = 1
for (e in c) {
hashCode = 31 * hashCode + (e?.hashCode() ?: 0)
hashCode = hashCode or 0 // make sure we don't overflow
}
return hashCode
}
internal fun orderedEquals(c: Collection<*>, other: Collection<*>): Boolean {
if (c.size != other.size) return false
val otherIterator = other.iterator()
for (elem in c) {
val elemOther = otherIterator.next()
if (elem != elemOther) {
return false
}
}
return true
}
}
}
@@ -25,88 +25,48 @@ abstract class AbstractMap<K, V> protected constructor() : MutableMap<K, V> {
/**
* A mutable [Map.Entry] shared by several [Map] implementations.
*/
open class SimpleEntry<K, V> : AbstractEntry<K, V> {
constructor(key: K, value: V) : super(key, value) {
open class SimpleEntry<K, V>(override val key: K, value: V) : MutableMap.MutableEntry<K, V> {
constructor(entry: Map.Entry<K, V>) : this(entry.key, entry.value)
private var _value = value
override val value: V get() = _value
override fun setValue(value: V): V {
val oldValue = this._value
this._value = value
return oldValue
}
constructor(entry: Entry<out K, out V>) : super(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)
}
/**
* An immutable [Map.Entry] shared by several [Map] implementations.
*/
class SimpleImmutableEntry<K, V> : AbstractEntry<K, V> {
constructor(key: K, value: V) : super(key, value) {
}
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)
constructor(entry: Entry<out K, out V>) : super(entry.key, entry.value) {
}
override fun setValue(value: V): V {
throw UnsupportedOperationException()
}
override fun hashCode(): Int = entryHashCode(this)
override fun toString(): String = entryToString(this)
override fun equals(other: Any?): Boolean = entryEquals(this, other)
}
/**
* Basic [Map.Entry] implementation used by [SimpleEntry]
* and [SimpleImmutableEntry].
*/
private abstract class AbstractEntry<K, V> protected constructor(private val key: K, private var value: V?) : Map.Entry<K, V> {
override fun getKey(): K {
return key
}
override fun getValue(): V {
return value
}
override fun setValue(value: V): V {
val oldValue = this.value
this.value = value
return oldValue
}
override fun equals(other: Any?): Boolean {
if (other !is Entry<*, *>) {
return false
}
val entry = other as Entry<*, *>?
return key == entry!!.key && value == entry!!.value
}
/**
* Calculate the hash code using Sun's specified algorithm.
*/
override fun hashCode(): Int {
return Objects.hashCode(key) xor Objects.hashCode(value)
}
override fun toString(): String {
// for compatibility with the real Jre: issue 3422
return key + "=" + value
}
}
override fun clear() {
entries.clear()
}
override fun containsKey(key: Any): Boolean {
override fun containsKey(key: K): Boolean {
return implFindEntry(key, false) != null
}
override fun containsValue(value: Any): Boolean {
for ((key, v) in entries) {
if (value == v) {
return true
}
}
return false
}
override fun containsValue(value: V): Boolean = entries.any { it.value == value }
internal fun containsEntry(entry: Entry<*, *>): Boolean {
internal fun containsEntry(entry: Map.Entry<*, *>): Boolean {
val key = entry.key
val value = entry.value
val ourValue = get(key)
@@ -123,66 +83,40 @@ abstract class AbstractMap<K, V> protected constructor() : MutableMap<K, V> {
return true
}
override fun equals(obj: Any?): Boolean {
if (obj === this) {
return true
}
if (obj !is Map<*, *>) {
return false
}
if (size != obj.size) {
return false
}
override fun equals(other: Any?): Boolean {
if (other === this) return true
if (other !is Map<*, *>) return false
if (size != other.size) return false
for (entry in obj.entries) {
if (!containsEntry(entry)) {
return false
}
}
return true
return other.entries.all { containsEntry(it) }
}
override operator fun get(key: Any): V? {
return getEntryValueOrNull<K, V>(implFindEntry(key, false))
}
override operator fun get(key: K): V? = implFindEntry(key, false)?.value
override fun hashCode(): Int {
return Collections.hashCode(entries)
}
override fun hashCode(): Int = entries.hashCode()
override fun isEmpty(): Boolean {
return size == 0
}
override fun isEmpty(): Boolean = size == 0
override val size: Int get() = entries.size
override fun keySet(): Set<K> {
override val keys: MutableSet<K> get() {
return object : AbstractSet<K>() {
override fun clear() {
this@AbstractMap.clear()
}
override operator fun contains(key: Any?): Boolean {
return containsKey(key)
}
override operator fun contains(key: K): Boolean = containsKey(key)
override operator fun iterator(): Iterator<K> {
override operator fun iterator(): MutableIterator<K> {
val outerIter = entries.iterator()
return object : Iterator<K> {
override fun hasNext(): Boolean {
return outerIter.hasNext()
}
override fun next(): K {
val entry = outerIter.next()
return entry.key
}
override fun remove() {
outerIter.remove()
}
return object : MutableIterator<K> {
override fun hasNext(): Boolean = outerIter.hasNext()
override fun next(): K = outerIter.next().key
override fun remove() = outerIter.remove()
}
}
override fun remove(key: Any?): Boolean {
override fun remove(key: K): Boolean {
if (containsKey(key)) {
this@AbstractMap.remove(key)
return true
@@ -190,89 +124,63 @@ abstract class AbstractMap<K, V> protected constructor() : MutableMap<K, V> {
return false
}
override fun size(): Int {
return this@AbstractMap.size
}
override val size: Int get() = this@AbstractMap.size
}
}
override fun put(key: K, value: V): V {
override fun put(key: K, value: V): V? {
throw UnsupportedOperationException("Put not supported on this map")
}
override fun putAll(map: Map<out K, V>) {
checkNotNull(map)
for ((key, value) in map) {
put(key, value)
}
}
override fun remove(key: Any): V {
return getEntryValueOrNull<K, V>(implFindEntry(key, true))
}
override fun remove(key: K): V? = implFindEntry(key, true)?.value
override fun size(): Int {
return entries.size
}
override fun toString(): String = entries.joinToString(", ", "{", "}") { toString(it) }
override fun toString(): String {
val joiner = StringJoiner(", ", "{", "}")
for (entry in entries) {
joiner.add(toString(entry))
}
return joiner.toString()
}
private fun toString(entry: Map.Entry<K, V>): String = toString(entry.key) + "=" + toString(entry.value)
private fun toString(entry: Entry<K, V>): String {
return toString(entry.key) + "=" + toString(entry.value)
}
private fun toString(o: Any?): String = if (o === this) "(this Map)" else o.toString()
private fun toString(o: Any): String {
return if (o === this) "(this Map)" else o.toString()
}
override fun values(): Collection<V> {
override val values: MutableCollection<V> get() {
return object : AbstractCollection<V>() {
override fun clear() {
this@AbstractMap.clear()
}
override fun clear() = this@AbstractMap.clear()
override operator fun contains(value: Any?): Boolean {
return containsValue(value)
}
override operator fun contains(value: V): Boolean = containsValue(value)
override operator fun iterator(): Iterator<V> {
override operator fun iterator(): MutableIterator<V> {
val outerIter = entries.iterator()
return object : Iterator<V> {
override fun hasNext(): Boolean {
return outerIter.hasNext()
}
override fun next(): V {
val entry = outerIter.next()
return entry.value
}
override fun remove() {
outerIter.remove()
}
return object : MutableIterator<V> {
override fun hasNext(): Boolean = outerIter.hasNext()
override fun next(): V = outerIter.next().value
override fun remove() = outerIter.remove()
}
}
override fun size(): Int {
return this@AbstractMap.size
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: Any, remove: Boolean): Entry<K, V>? {
private fun implFindEntry(key: K, remove: Boolean): Map.Entry<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.key, entry.value)
entry = SimpleEntry(entry)
iter.remove()
}
return entry
@@ -283,12 +191,11 @@ abstract class AbstractMap<K, V> protected constructor() : MutableMap<K, V> {
companion object {
internal fun <K, V> getEntryKeyOrNull(entry: Entry<K, V>?): K? {
return if (entry == null) null else entry!!.key
}
internal fun <K, V> getEntryValueOrNull(entry: Entry<K, V>?): V? {
return if (entry == null) null else entry!!.value
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
}
}
}