Provide implementation of read-only AbstractCollection, AbstractList and AbstractSet,

Alias AbstactMutableCollection to java.util.AbstractCollection.
Change inheritance hierarchy of reversed list views.
This commit is contained in:
Ilya Gorbunov
2016-08-31 22:53:58 +03:00
parent 53cd079333
commit 2bb1d6d5b4
6 changed files with 316 additions and 10 deletions
@@ -0,0 +1,40 @@
/*
* 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.
*/
package kotlin.collections
public abstract class AbstractCollection<out E> : Collection<E> {
abstract override val size: Int
abstract override fun iterator(): Iterator<E>
override fun contains(element: @UnsafeVariance E): Boolean = any { it == element }
override fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean =
elements.all(this::contains)
override fun isEmpty(): Boolean = size == 0
abstract override fun hashCode(): Int
abstract override fun equals(other: Any?): Boolean
override fun toString(): String = joinToString(", ", "[", "]") {
if (it === this) "(this Collection)" else it.toString()
}
}
@@ -0,0 +1,151 @@
/*
* 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 AbstractList
* Copyright 2007 Google Inc.
*/
package kotlin.collections
public abstract class AbstractList<out E> : AbstractCollection<E>(), List<E> {
abstract override val size: Int
abstract override fun get(index: Int): E
override fun iterator(): Iterator<E> = IteratorImpl()
override fun indexOf(element: @UnsafeVariance E): Int = indexOfFirst { it == element }
override fun lastIndexOf(element: @UnsafeVariance E): Int = indexOfLast { it == element }
override fun listIterator(): ListIterator<E> = ListIteratorImpl(0)
override fun listIterator(index: Int): ListIterator<E> = ListIteratorImpl(index)
override fun subList(fromIndex: Int, toIndex: Int): List<E> = SubList(this, fromIndex, toIndex)
internal open class SubList<out E>(private val list: AbstractList<E>, private val fromIndex: Int, toIndex: Int) : AbstractList<E>() {
private var _size: Int = 0
init {
checkRangeIndexes(fromIndex, toIndex, list.size)
this._size = toIndex - fromIndex
}
override fun get(index: Int): E {
checkElementIndex(index, _size)
return list[fromIndex + index]
}
override val size: Int get() = _size
}
override fun equals(other: Any?): Boolean {
if (other === this) return true
if (other !is List<*>) return false
return orderedEquals(this, other)
}
override fun hashCode(): Int = orderedHashCode(this)
internal open inner class IteratorImpl : Iterator<E> {
/** the index of the item that will be returned on the next call to [next]`()` */
protected var index = 0
/** the index of the item that was returned on the previous call to [next]`()`
* or [ListIterator.previous]`()` (for `ListIterator`),
* -1 if no such item exists
*/
protected var last = -1
override fun hasNext(): Boolean = index < size
override fun next(): E {
if (!hasNext()) throw NoSuchElementException()
last = index++
return get(last)
}
}
/**
* Implementation of `MutableListIterator` for abstract lists.
*/
internal open inner class ListIteratorImpl(index: Int) : IteratorImpl(), ListIterator<E> {
init {
checkPositionIndex(index, this@AbstractList.size)
this.index = index
}
override fun hasPrevious(): Boolean = index > 0
override fun nextIndex(): Int = index
override fun previous(): E {
if (!hasPrevious()) throw NoSuchElementException()
last = --index
return get(last)
}
override fun previousIndex(): Int = index - 1
}
companion object {
internal fun checkElementIndex(index: Int, size: Int) {
if (index < 0 || index >= size) {
throw IndexOutOfBoundsException("index: $index, size: $size")
}
}
internal fun checkPositionIndex(index: Int, size: Int) {
if (index < 0 || index > size) {
throw IndexOutOfBoundsException("index: $index, size: $size")
}
}
internal fun checkRangeIndexes(start: Int, end: Int, size: Int) {
if (start < 0 || end > size) {
throw IndexOutOfBoundsException("fromIndex: $start, toIndex: $end, size: $size")
}
if (start > end) {
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
}
}
}
@@ -0,0 +1,35 @@
/*
* 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.
*/
package kotlin.collections
public abstract class AbstractSet<out E> protected constructor() : AbstractCollection<E>(), Set<E> {
override fun equals(other: Any?): Boolean {
if (other === this) return true
if (other !is Set<*>) return false
if (other.size != size) return false
return containsAll(other)
}
override fun hashCode(): Int {
var hashCode = 0
for (element in this) {
hashCode = (hashCode + (element?.hashCode() ?: 0)) or 0
}
return hashCode
}
}
@@ -18,25 +18,31 @@
package kotlin.collections
import java.util.*
private open class ReversedListReadOnly<T>(protected open val delegate: List<T>) : AbstractList<T>() {
private open class ReversedListReadOnly<out T>(private val delegate: List<T>) : AbstractList<T>() {
override val size: Int get() = delegate.size
override fun get(index: Int): T = delegate[index.flipIndex()]
override fun get(index: Int): T = delegate[reverseElementIndex(index)]
protected fun Int.flipIndex(): Int = if (this in 0..size - 1) size - this - 1 else throw IndexOutOfBoundsException("index $this should be in range [${0..size - 1}].")
protected fun Int.flipIndexForward(): Int = if (this in 0..size) size - this else throw IndexOutOfBoundsException("index $this should be in range [${0..size}].")
}
private class ReversedList<T>(protected override val delegate: MutableList<T>) : ReversedListReadOnly<T>(delegate) {
override fun clear() = delegate.clear()
override fun removeAt(index: Int): T = delegate.removeAt(index.flipIndex())
private class ReversedList<T>(private val delegate: MutableList<T>) : AbstractMutableList<T>() {
override val size: Int get() = delegate.size
override fun get(index: Int): T = delegate[reverseElementIndex(index)]
override fun set(index: Int, element: T): T = delegate.set(index.flipIndex(), element)
override fun clear() = delegate.clear()
override fun removeAt(index: Int): T = delegate.removeAt(reverseElementIndex(index))
override fun set(index: Int, element: T): T = delegate.set(reverseElementIndex(index), element)
override fun add(index: Int, element: T) {
delegate.add(index.flipIndexForward(), element)
delegate.add(reversePositionIndex(index), element)
}
}
private fun List<*>.reverseElementIndex(index: Int) = // TODO: Use AbstractList.checkElementIndex: run { AbstractList.checkElementIndex(index, size); lastIndex - index }
if (index in 0..size - 1) size - index - 1 else throw IndexOutOfBoundsException("Index $index should be in range [${0..size - 1}].")
private fun List<*>.reversePositionIndex(index: Int) =
if (index in 0..size) size - index else throw IndexOutOfBoundsException("Index $index should be in range [${0..size}].")
/**
* Returns a reversed read-only view of the original List.
@@ -0,0 +1,6 @@
@file:JvmVersion
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>