Skip to content

Instantly share code, notes, and snippets.

@heinrichreimer
Created January 20, 2020 11:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save heinrichreimer/2a3a981b743c90f57f497f9db544bb45 to your computer and use it in GitHub Desktop.
Save heinrichreimer/2a3a981b743c90f57f497f9db544bb45 to your computer and use it in GitHub Desktop.
Add-only Kotlin collections.
package de.webis.webisstud.thesis.reimer
/**
* A generic collection of elements that supports adding elements.
*
* @param E the type of elements contained in the collection.
* The mutable collection is invariant on its element type.
*/
interface AddOnlyCollection<E> : Collection<E> {
/**
* Adds the specified element to the collection.
*
* @return `true` if the element has been added,
* `false` if the collection does not support duplicates
* and the element is already contained in the collection.
*/
fun add(element: E): Boolean
/**
* Adds all of the elements of the specified collection to this collection.
*
* @return `true` if any of the specified elements was added to the collection,
* `false` if the collection was not modified.
*/
fun addAll(elements: Collection<E>): Boolean
}
/**
* A generic ordered collection of elements that supports adding elements.
* @param E the type of elements contained in the list. The mutable list is invariant on its element type.
*/
interface AddOnlyList<E> : AddOnlyCollection<E>, List<E> {
/**
* Adds the specified element to the end of this list.
*
* @return `true` because the list is always modified as the result of this operation.
*/
override fun add(element: E): Boolean
/**
* Adds all of the elements of the specified collection to the end of this list.
*
* The elements are appended in the order they appear in the [elements] collection.
*
* @return `true` if the list was changed as the result of the operation.
*/
override fun addAll(elements: Collection<E>): Boolean
/**
* Inserts all of the elements of the specified collection [elements] into this list at the specified [index].
*
* @return `true` if the list was changed as the result of the operation.
*/
fun addAll(index: Int, elements: Collection<E>): Boolean
/**
* Inserts an element into the list at the specified [index].
*/
fun add(index: Int, element: E): Unit
override fun listIterator(): AddOnlyListIterator<E>
override fun listIterator(index: Int): AddOnlyListIterator<E>
override fun subList(fromIndex: Int, toIndex: Int): AddOnlyList<E>
}
/**
* An iterator over a mutable collection that supports indexed access. Provides the ability
* to add, modify elements while iterating.
*/
interface AddOnlyListIterator<T> : ListIterator<T>, Iterator<T> {
override fun next(): T
override fun hasNext(): Boolean
/**
* Adds the specified element [element] into the underlying collection immediately before the element that would be
* returned by [next], if any, and after the element that would be returned by [previous], if any.
* (If the collection contains no elements, the new element becomes the sole element in the collection.)
* The new element is inserted before the implicit cursor: a subsequent call to [next] would be unaffected,
* and a subsequent call to [previous] would return the new element. (This call increases by one the value \
* that would be returned by a call to [nextIndex] or [previousIndex].)
*/
fun add(element: T)
}
/**
* A generic unordered collection of elements that does not support duplicate elements, and supports
* adding elements.
* @param E the type of elements contained in the set. The mutable set is invariant on its element type.
*/
interface AddOnlySet<E> : Set<E>, AddOnlyCollection<E> {
/**
* Adds the specified element to the set.
*
* @return `true` if the element has been added, `false` if the element is already contained in the set.
*/
override fun add(element: E): Boolean
override fun addAll(elements: Collection<E>): Boolean
}
/**
* A modifiable collection that holds pairs of objects (keys and values) and supports efficiently retrieving
* the value corresponding to each key. Map keys are unique; the map holds only one value for each key.
* @param K the type of map keys. The map is invariant on its key type.
* @param V the type of map values. The mutable map is invariant on its value type.
*/
interface AddOnlyMap<K, V> : Map<K, V> {
/**
* Associates the specified [value] with the specified [key] in the map.
*
* @return the previous value associated with the key, or `null` if the key was not present in the map.
*/
fun put(key: K, value: V): V?
/**
* Updates this map with key/value pairs from the specified map [from].
*/
fun putAll(from: Map<out K, V>): Unit
/**
* Returns an [AddOnlySet] of all keys in this map.
*/
override val keys: AddOnlySet<K>
/**
* Returns an [AddOnlyCollection] of all values in this map. Note that this collection may contain duplicate values.
*/
override val values: AddOnlyCollection<V>
/**
* Returns an [AddOnlySet] of all key/value pairs in this map.
*/
override val entries: AddOnlySet<MutableMap.MutableEntry<K, V>>
}
fun <E> MutableCollection<E>.restrictAddOnly(): AddOnlyCollection<E> {
return object : AddOnlySet<E>, Collection<E> by this {
override fun add(element: E) = this@restrictAddOnly.add(element)
override fun addAll(elements: Collection<E>) = this@restrictAddOnly.addAll(elements)
}
}
fun <E> MutableList<E>.restrictAddOnly(): AddOnlyList<E> {
return object : AddOnlyList<E>, List<E> by this {
override fun add(element: E) = this@restrictAddOnly.add(element)
override fun addAll(elements: Collection<E>) = this@restrictAddOnly.addAll(elements)
override fun add(index: Int, element: E) = this@restrictAddOnly.add(index, element)
override fun addAll(index: Int, elements: Collection<E>) = this@restrictAddOnly.addAll(index, elements)
override fun listIterator() = this@restrictAddOnly.listIterator().restrictAddOnly()
override fun listIterator(index: Int) = this@restrictAddOnly.listIterator(index).restrictAddOnly()
override fun subList(fromIndex: Int, toIndex: Int) = this@restrictAddOnly.subList(fromIndex, toIndex).restrictAddOnly()
}
}
fun <E> MutableListIterator<E>.restrictAddOnly(): AddOnlyListIterator<E> {
return object : AddOnlyListIterator<E>, ListIterator<E> by this {
override fun add(element: E) = this@restrictAddOnly.add(element)
}
}
fun <E> MutableSet<E>.restrictAddOnly(): AddOnlySet<E> {
return object : AddOnlySet<E>, Set<E> by this {
override fun add(element: E) = this@restrictAddOnly.add(element)
override fun addAll(elements: Collection<E>) = this@restrictAddOnly.addAll(elements)
}
}
fun <K, V> MutableMap<K, V>.restrictAddOnly(): AddOnlyMap<K, V> {
return object : AddOnlyMap<K, V>, Map<K, V> by this {
override fun put(key: K, value: V) = this@restrictAddOnly.put(key, value)
override fun putAll(from: Map<out K, V>) = this@restrictAddOnly.putAll(from)
override val keys get() = this@restrictAddOnly.keys.restrictAddOnly()
override val values get() = this@restrictAddOnly.values.restrictAddOnly()
override val entries get() = this@restrictAddOnly.entries.restrictAddOnly()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment