Update:
- Fixed last item is not removed during iteration
- Fixed
clear()during iteration does nothing - Fixed addition of removed item is ignored
The lasted code can be found here. Unitest can be found here.
As part of my Signals library, I needed to create a custom Linked List with the below properties
- It should allow "addition" and "removal" of items during iteration, aka when
iterator()is called, like in theforloop. - It should ignore-Addition of duplicated items.
- It should ignore-Removal of nonexisting items.
- it should be a thread-safe
I ended up with the below implementation. Please tell me what do you think in terms of
- clean code
- bugs
- performance
package com.gazman.signals
import java.util.*
internal class ListenersList<T> : Iterable<T?> {
private val none = Node<T>(null)
private var head: Node<T>? = null
private var tail: Node<T>? = null
private var map = IdentityHashMap<T, Node<T>>()
fun isNotEmpty(): Boolean {
return map.isNotEmpty()
}
fun add(listener: T) {
synchronized(this) {
if (map.containsKey(listener)) {
return
}
val node = Node(listener)
map[listener] = node
if (tail == null) {
head = node
tail = node
} else {
node.previous = tail
tail?.next = node
tail = node
}
}
}
fun remove(listener: T) {
synchronized(this) {
val node = map[listener]
node?.previous?.next = node?.next
node?.next?.previous = node?.previous
}
}
override fun iterator(): Iterator<T?> {
return object : Iterator<T?> {
var node: Node<T>? = none
override fun hasNext() = node != null && node != tail
override fun next(): T? {
node = if (node == none) {
[email protected]
} else {
node?.next
}
return node?.value
}
}
}
fun clear() {
synchronized(this) {
head = null
tail = null
map.clear()
}
}
}
Node
package com.gazman.signals
internal class Node<T>(val value: T?) {
var previous: Node<T>? = null
var next: Node<T>? = null
}