From ee9b6cd87f1775b02e06248cdca1a0f41b274ea0 Mon Sep 17 00:00:00 2001 From: tursom <tursom@foxmail.com> Date: Tue, 18 Feb 2020 13:55:24 +0800 Subject: [PATCH] add concurrent list --- src/main/kotlin/cn/tursom/core/Tools.kt | 2 +- .../core/datastruct/AbstractMutableList.kt | 131 +++++++++++++ .../cn/tursom/core/datastruct/SubList.kt | 20 ++ .../concurrent/BlockingArrayList.kt | 3 + .../concurrent/BlockingLinkedList.kt | 5 + .../datastruct/concurrent/BlockingList.kt | 33 ++++ .../concurrent/ConcurrentLinkedList.kt | 174 ++++++++++++++++++ 7 files changed, 367 insertions(+), 1 deletion(-) create mode 100644 src/main/kotlin/cn/tursom/core/datastruct/AbstractMutableList.kt create mode 100644 src/main/kotlin/cn/tursom/core/datastruct/SubList.kt create mode 100644 src/main/kotlin/cn/tursom/core/datastruct/concurrent/BlockingArrayList.kt create mode 100644 src/main/kotlin/cn/tursom/core/datastruct/concurrent/BlockingLinkedList.kt create mode 100644 src/main/kotlin/cn/tursom/core/datastruct/concurrent/BlockingList.kt create mode 100644 src/main/kotlin/cn/tursom/core/datastruct/concurrent/ConcurrentLinkedList.kt diff --git a/src/main/kotlin/cn/tursom/core/Tools.kt b/src/main/kotlin/cn/tursom/core/Tools.kt index bfae1e3..98d752e 100644 --- a/src/main/kotlin/cn/tursom/core/Tools.kt +++ b/src/main/kotlin/cn/tursom/core/Tools.kt @@ -250,7 +250,7 @@ fun <T> T.println(): T { } @Suppress("UNCHECKED_CAST") -fun <T> Any.cast(): T = this as T +fun <T> Any?.cast(): T = this as T inline fun loop(`continue`: () -> Boolean = { true }, action: () -> Unit) { while (`continue`()) action() diff --git a/src/main/kotlin/cn/tursom/core/datastruct/AbstractMutableList.kt b/src/main/kotlin/cn/tursom/core/datastruct/AbstractMutableList.kt new file mode 100644 index 0000000..620c04c --- /dev/null +++ b/src/main/kotlin/cn/tursom/core/datastruct/AbstractMutableList.kt @@ -0,0 +1,131 @@ +package cn.tursom.core.datastruct + +interface AbstractMutableList<T> : MutableList<T> { + override fun contains(element: T): Boolean { + forEach { + if (it == element) return true + } + return false + } + + override fun subList(fromIndex: Int, toIndex: Int): MutableList<T> { + return SubList(this, fromIndex, toIndex) + } + + override fun clear() { + repeat(size) { + removeAt(size - 1) + } + } + + override fun containsAll(elements: Collection<T>): Boolean { + elements.forEach { + if (contains(it).not()) { + return false + } + } + return true + } + + override fun indexOf(element: T): Int { + forEachIndexed { i, t -> + if (element == t) return i + } + return -1 + } + + override fun isEmpty(): Boolean = size == 0 + + override fun lastIndexOf(element: T): Int { + var last = -1 + forEachIndexed { index, t -> + if (t == element) last = index + } + return last + } + + override fun addAll(index: Int, elements: Collection<T>): Boolean { + elements.forEachIndexed { i, t -> + add(index + i, t) + } + return true + } + + override fun addAll(elements: Collection<T>): Boolean { + elements.forEach { + add(it) + } + return true + } + + override fun retainAll(elements: Collection<T>): Boolean { + val iterator = iterator() + var changed = false + while (iterator.hasNext()) { + val value = iterator.next() + if (elements.contains(value).not()) { + iterator.remove() + changed = true + } + } + return changed + } + + override fun listIterator(): MutableListIterator<T> = listIterator(0) + + override fun remove(element: T): Boolean { + val index = indexOf(element) + return if (index < 0) { + false + } else { + removeAt(index) + true + } + } + + override fun removeAll(elements: Collection<T>): Boolean { + var changed = false + elements.forEach { + if (remove(it)) { + changed = true + } + } + return changed + } + + override fun iterator(): MutableIterator<T> = listIterator() + + override fun listIterator(index: Int): MutableListIterator<T> = AbstractListIterator(this, index) + + class AbstractListIterator<T>(val list: MutableList<T>, var index: Int = 0) : MutableListIterator<T> { + init { + index-- + } + + override fun hasPrevious(): Boolean = index > 0 + + override fun previousIndex(): Int = index - 1 + override fun previous(): T { + return list[--index] + } + + override fun add(element: T) { + list.add(index, element) + } + + override fun hasNext(): Boolean = index < list.size + override fun nextIndex(): Int = index + 1 + override fun next(): T { + return list[++index] + } + + override fun remove() { + list.removeAt(index) + } + + override fun set(element: T) { + list[index] = element + } + } +} + diff --git a/src/main/kotlin/cn/tursom/core/datastruct/SubList.kt b/src/main/kotlin/cn/tursom/core/datastruct/SubList.kt new file mode 100644 index 0000000..28e58a8 --- /dev/null +++ b/src/main/kotlin/cn/tursom/core/datastruct/SubList.kt @@ -0,0 +1,20 @@ +package cn.tursom.core.datastruct + +class SubList<T>( + val parent: MutableList<T>, + val fromIndex: Int, + val toIndex: Int +) : AbstractMutableList<T> { + override val size: Int get() = toIndex - fromIndex + + override fun add(element: T): Boolean { + parent.add(toIndex, element) + return true + } + + override fun add(index: Int, element: T) = parent.add(fromIndex + index, element) + override fun removeAt(index: Int): T = parent.removeAt(fromIndex + index) + override fun retainAll(elements: Collection<T>): Boolean = parent.retainAll(elements) + override fun set(index: Int, element: T): T = parent.set(fromIndex + index, element) + override fun get(index: Int): T = parent[fromIndex + index] +} \ No newline at end of file diff --git a/src/main/kotlin/cn/tursom/core/datastruct/concurrent/BlockingArrayList.kt b/src/main/kotlin/cn/tursom/core/datastruct/concurrent/BlockingArrayList.kt new file mode 100644 index 0000000..87984c6 --- /dev/null +++ b/src/main/kotlin/cn/tursom/core/datastruct/concurrent/BlockingArrayList.kt @@ -0,0 +1,3 @@ +package cn.tursom.core.datastruct.concurrent + +class BlockingArrayList<T> : BlockingList<T>(ArrayList<T>()) \ No newline at end of file diff --git a/src/main/kotlin/cn/tursom/core/datastruct/concurrent/BlockingLinkedList.kt b/src/main/kotlin/cn/tursom/core/datastruct/concurrent/BlockingLinkedList.kt new file mode 100644 index 0000000..ec540b2 --- /dev/null +++ b/src/main/kotlin/cn/tursom/core/datastruct/concurrent/BlockingLinkedList.kt @@ -0,0 +1,5 @@ +package cn.tursom.core.datastruct.concurrent + +import java.util.* + +class BlockingLinkedList<T> : BlockingList<T>(LinkedList<T>()) diff --git a/src/main/kotlin/cn/tursom/core/datastruct/concurrent/BlockingList.kt b/src/main/kotlin/cn/tursom/core/datastruct/concurrent/BlockingList.kt new file mode 100644 index 0000000..ff6e45e --- /dev/null +++ b/src/main/kotlin/cn/tursom/core/datastruct/concurrent/BlockingList.kt @@ -0,0 +1,33 @@ +package cn.tursom.core.datastruct.concurrent + +import cn.tursom.core.datastruct.AbstractMutableList +import java.util.* +import java.util.concurrent.locks.ReentrantReadWriteLock +import kotlin.concurrent.read +import kotlin.concurrent.write + +open class BlockingList<T>(val list: MutableList<T> = LinkedList()) : AbstractMutableList<T> { + private var lock = ReentrantReadWriteLock() + override val size: Int get() = list.size + + override fun add(element: T): Boolean = lock.write { + list.add(element) + } + + override fun add(index: Int, element: T) = lock.write { + list.add(index, element) + } + + override fun removeAt(index: Int): T = lock.write { + list.removeAt(index) + } + + override fun set(index: Int, element: T): T = lock.write { + list.set(index, element) + } + + override fun get(index: Int): T = lock.read { + list[index] + } +} + diff --git a/src/main/kotlin/cn/tursom/core/datastruct/concurrent/ConcurrentLinkedList.kt b/src/main/kotlin/cn/tursom/core/datastruct/concurrent/ConcurrentLinkedList.kt new file mode 100644 index 0000000..0efc026 --- /dev/null +++ b/src/main/kotlin/cn/tursom/core/datastruct/concurrent/ConcurrentLinkedList.kt @@ -0,0 +1,174 @@ +package cn.tursom.core.datastruct.concurrent + +import cn.tursom.core.datastruct.AbstractMutableList +import java.util.concurrent.locks.ReentrantReadWriteLock +import kotlin.concurrent.read +import kotlin.concurrent.write + +@Suppress("MemberVisibilityCanBePrivate") +class ConcurrentLinkedList<T> : AbstractMutableList<T> { + private var length = 0 + private var lock = ReentrantReadWriteLock() + private var root = Node() + + override val size: Int get() = length + + override fun get(index: Int): T { + val p = prevNodeOfIndex(index).next + @Suppress("UNCHECKED_CAST") + return p.value as T + } + + override fun add(element: T): Boolean = lock.write { + addBeforeNode(root.prev, element) + return true + } + + override fun add(index: Int, element: T) = if (index > size) { + throw IndexOutOfBoundsException() + } else lock.write { + val p = prevNodeOfIndex(index) + addBeforeNode(p, element) + } + + fun addAndGetIndex(element: T): Int = lock.write { + addBeforeNode(root.prev, element) + return size - 1 + } + + fun addAndGetIterator(element: T): MutableListIterator<T> = lock.write { + addBeforeNode(root.prev, element) + return Iterator(size - 1, root.prev) + } + + override fun clear() = lock.write { + length = 0 + root.next = root + root.prev = root + } + + override fun removeAt(index: Int): T = if (index > size) { + throw IndexOutOfBoundsException() + } else lock.write { + val p = prevNodeOfIndex(index) + val removed = p.next + p.next = p.next.next + p.next.prev = p + @Suppress("UNCHECKED_CAST") + removed.value as T + } + + override fun set(index: Int, element: T): T = if (index < 0 || index > size) { + throw IndexOutOfBoundsException() + } else lock.read { + val p = prevNodeOfIndex(index).next + val oldValue = p.value + p.value = element + @Suppress("UNCHECKED_CAST") + oldValue as T + } + + override fun listIterator(index: Int): MutableListIterator<T> = Iterator(index) + + override fun toString(): String { + return if (length == 0) { + "[]" + } else { + val sb = StringBuilder("[") + var node = root.next + while (node != root) { + sb.append("${node.value}, ") + node = node.next + } + repeat(2) { + sb.deleteCharAt(sb.length - 1) + } + sb.append(']') + sb.toString() + } + } + + private fun addBeforeNode(p: Node, value: T) = lock.write { + length++ + val new = Node(value, p.next.prev, p.next) + new.next.prev = new + new.prev.next = new + } + + private fun prevNodeOfIndex(index: Int): Node = if (index < 0) { + root + } else lock.read { + var p = root + if (index <= length / 2) { + // 从前向后遍历 + repeat(index) { + p = p.next + } + } else { + // 从后向前遍历 + repeat(length - index + 1) { + p = p.prev + } + } + return p + } + + private inner class Node { + var value: T? + var prev: Node + var next: Node + + constructor(value: T? = null, prev: Node, next: Node) { + this.value = value + this.next = next + this.prev = prev + } + + constructor(value: T? = null) { + this.value = value + this.next = this + this.prev = this + } + } + + private inner class Iterator( + var index: Int, + var p: Node = prevNodeOfIndex(index - 1) + ) : MutableListIterator<T> { + + override fun hasPrevious(): Boolean = p.prev != root + + override fun previousIndex(): Int = index - 1 + override fun previous(): T { + p = p.prev + index-- + return get() + } + + override fun add(element: T) { + addBeforeNode(p, element) + } + + override fun nextIndex(): Int = index + 1 + override fun hasNext(): Boolean = p.next != root + override fun next(): T { + p = p.next + index++ + return get() + } + + override fun remove() = lock.write { + p.next.prev = p.prev + p.prev.next = p.next + } + + override fun set(element: T) { + p.value = element + } + + fun get(): T { + @Suppress("UNCHECKED_CAST") + return p.value as T + } + } +} \ No newline at end of file