How to add elements to CopyInWriteCollection using Kotlin style? - kotlin

Assume we have a custom collection
class CopyOnWriteCollection<T> {
// returns copy of collection with new element
fun add(element: T): CopyOnWriteCollection<T> {
...
}
}
if i need to add several elements i would do something like this:
val newCollection = oldCollection
.add(1)
.add(2)
.add(3)
And newCollection contains elements from oldCollection and also contains 1,2,3.
Perfect!
But how can i add elements from another collection using forEach of map?
val collection = CopyOnWriteCollection()
(1..3).forEach { collection.add(it) } // this approach works only with mutable collections

You can use an imperative loop, or you can use the fold()function:
fun main() {
var collection = CopyOnWriteCollection<Int>()
var collection2 = collection
for (i in 1..3) {
collection = collection.add(i)
}
println(collection)
collection2 = (1..3).fold(collection2) { coll, i -> coll.add(i) }
println(collection2)
}
class CopyOnWriteCollection<T> {
private val list = mutableListOf<T>()
// returns copy of collection with new element
fun add(element: T): CopyOnWriteCollection<T> {
val copy = CopyOnWriteCollection<T>()
copy.list.addAll(this.list)
copy.list.add(element)
return copy;
}
override fun toString() = list.toString()
}

If the CopyOnWriteCollection class is under your control, I'd approach this by adding an addAll() method to it:
/** Returns copy of collection with new element. */
fun addAll(elements: Collection<T>): CopyOnWriteCollection<T> {
// ...
}
You could then call that with e.g.
val newCollection = oldCollection.addAll(listOf(1, 2, 3))
(Or you could take a vararg instead of a collection.)
That's likely to take a lot less time and memory.
(Also, if you really need to write your own collection class, I'd strongly recommend implementing Collection (or one of its subinterfaces if appropriate), or extending a class which does.  That will give access to the huge range of extension methods and other goodies in the stdlib.)

Related

Is there a scope function returning previous value?

I need to perform some operations on a mutable list and use its previous value. Something similar to also except that it should return the previous value.
val localList: List<String> = mainList.alsoButGetPrevious { it.clear() }
Before I write this function, is there an existing one that does this?
There is no "previous value" in this case. There is only one list and it is modified by clear(), so even if you would do something like this:
localList = mainList
mainList.clear()
Then localList would still not contain "previous" value, but it would be empty.
What you need here is to copy the list before clearing it. There is no scoping function for this, because it is specific to lists only. You can implement it by yourself:
val localList = mainList.copyAndApply { clear() }
inline fun <T> MutableList<T>.copyAndApply(block: MutableList<T>.() -> Unit): List<T> {
val result = toList()
block()
return result
}
As noted by #mightyWOZ, toList() creates a shallow copy of the data, meaning that it contains references to the same object instances as the original list. Above solution works if you need to only clear mainList or add/remove items from it. However, if you modify objects in mainList then this change will affect localList as well. There is no straightforward and universal way to perform a deep copy of the data in Java/Kotlin. If you need this, it is probably better to create utility functions that target your data structures.
As broot's answer says, there is only one list, and you should copy it with toList. You can do this inline with scope functions like this:
val localList: List<String> = mainList.run {
// here, this: MutableList<T>
toList().also { clear() } // here we are calling this.clear()
}
or if you don't mind repeating mainList,
val localList: List<String> = mainList.toList().also {
mainList.clear()
}
You can use Delagetes.observable or vetoable to observe or even with vetoable set under which conditions it should change
var myList: List<String> by Delegates.observable(listOf()) {
property: KProperty<*>, oldValue: List<String>, newValue: List<String> ->
}
var myList: List<String> by Delegates.vetoable(listOf()) { property: KProperty<*>, oldValue: List<String>, newValue: List<String> ->
newValue.size > 5
}

ArrayList field not correctly gathered

I'm actually new at Kotlin, and I encounter the following problematic:
I have a class holding an ArrayList of EnsembleVerifier class.
This other class is instantiated with an ArrayList of Square.
When I tried to get this ArrayList, I discovered that this one has no element inside.
Is there any absurdity/misconception in my code? Is it something else? Thank you in advance! :)
GridVerifiers.kt
class GridVerifiers(private val grid: Grid) {
private var verifiers: ArrayList<EnsembleVerifier> = ArrayList()
init {
generateVerifiers()
}
private fun generateVerifiers() {
generateLineVerifiers()
generateColumnVerifiers()
generateSubGridVerifiers()
}
private fun generateLineVerifiers() {
val line: ArrayList<Square> = ArrayList()
for (lineIndex in grid.gridState.indices) {
for (columnIndex in grid.gridState.indices)
line.add(grid.gridState[lineIndex][columnIndex])
println(line.size) // returns 9
verifiers.add(EnsembleVerifier(line))
line.clear()
}
}
...
EnsembleVerifier.kt
class EnsembleVerifier(private val squares: ArrayList<Square>) {
...
fun isValid(): Boolean {
val buffer: ArrayList<Int> = ArrayList()
println(squares.size) // returns 0!
for (square in squares) {
if (square.value in buffer) return false
buffer.add(square.value)
}
return true
}
In java most of the time you are working with references to objects. This means in your case, that your are always working with the same array line. Therefore, when you call line.clear you are cleaning the array that that reference is pointing at, and that's causing your issue with empty arrays.
You need to generate new objects every time instead of cleaning the list.
private fun generateLineVerifiers() {
for (lineIndex in grid.gridState.indices) {
val line: ArrayList<Square> = ArrayList()
for (columnIndex in grid.gridState.indices)
line.add(grid.gridState[lineIndex][columnIndex])
println(line.size) // returns 9
verifiers.add(EnsembleVerifier(line))
}
}

Is a std extensions to insert or update kotlin mutable list which use Comparator?

I have a list of complex objects and I want to merge this list with new one. But if in new one has same object (based on passed comparator) then element should be replaced otherwise added at end of list in order.
I wrote a extension function which do the job but I'm looking for more efficient way (and more elegant) like some combination of already existing extensions.
fun <T> MutableList<T>.insertOrUpdate(items: List<T>, comparator: Comparator<T>): List<T> {
val out = mutableListOf<T>()
val toInsert = items.toMutableList()
forEach { oldItem ->
var wasUpdated = false
items.forEach { newItem ->
if (comparator.compare(oldItem, newItem) == 0) {
out.add(newItem)
toInsert.remove(newItem)
wasUpdated = true
}
}
if(!wasUpdated){
out.add(oldItem)
}
}
out.addAll(toInsert)
return out
}

How to insert an element after another using a LinkedHashSet in Kotlin

I am trying to search for a collection type that have the following properties:
Maintain insertion order
Don't allow duplicates
Add one or more elements after another
I could create my own data collection but I wish not to.
After taking a look at all collections available in kotlin I think LinkedHashSet have almost all of my requirements, however it can't add elements after another or at nth position.
Is there any way to accomplish this with an extension method or any another trick?
You can just use List<> or any of its implementations. Its maintain insertion order, you can add one or more elements after another, and you can accomplish the "avoid duplicates" requirement by calling .distinct() when returning your list. i.e:
private fun fillData(): MutableList<String> {
var dataSet: MutableList<String> = ArrayList()
for (i in 0..10) dataSet.add("Product $i")
dataSet.add("aaa")
dataSet.add("aaa")
dataSet.add("aaa")
dataSet.add("aaa")
dataSet.add("aaa")
return dataSet.distinct().toMutableList()
}
The result of this function returns an array with 11 elements, "Product 1".. "Product 10" and just 1 "aaa" element at the end.
you can see the doc of List.distinct() here
In the standard library (& Java collection API) there isn't such a collection type as far as I know.
Apache commons collections however contains what you are looking for: ListOrderedSet
Why not implement a custom data structure that exactly serve your requirements?
class OrderedHashSet<E> : MutableSet<E>{
private val set = HashSet<E>()
private val list = LinkedList<E>()
override val size: Int
get() = list.size
override fun contains(element: E) = set.contains(element)
override fun containsAll(elements: Collection<E>) = set.containsAll(elements)
override fun isEmpty() = list.isEmpty()
override fun iterator() = list.iterator()
override fun add(element: E): Boolean {
if(set.add(element)){
list.add(element)
return true
}
return false
}
fun add(index: Int, element: E) : Boolean {
if(set.add(element)){
list.add(index, element)
return true
}
return false
}
override fun addAll(elements: Collection<E>): Boolean {
var modified = false
for(element in elements){
if(add(element)){
modified = true
}
}
return modified
}
override fun clear() {
set.clear()
list.clear()
}
override fun remove(element: E): Boolean {
set.remove(element)
return list.remove(element)
}
override fun removeAll(elements: Collection<E>): Boolean {
var modified = false
for(element in elements){
if(remove(element)){
modified = true
}
}
return modified
}
override fun retainAll(elements: Collection<E>): Boolean {
set.retainAll(elements)
return list.retainAll(elements)
}
}

Kotlin - extensible type-safe builders

I want to be able to create a custom builder-pattern DSL-type thing, and I want the ability to create new components in a clean and type-safe way. How can I hide the implementation details required for creating and extending such a builder-pattern?
The Kotlin docs give something like the following example:
html {
head {
title {+"XML encoding with Kotlin"}
}
body {
h1 {+"XML encoding with Kotlin"}
p {+"this format can be used as an alternative markup to XML"}
a(href = "http://kotlinlang.org") {+"Kotlin"}
// etc...
}
}
Here, all of the possible "elements" are predefined and implemented as functions that also return objects of the corresponding types. (eg. the html function returns an instance of the HTML class)
Each function is defined so that it adds itself to its parent context's object as a child.
Suppose someone wanted to create a new element type NewElem usable as newelem. They would have to do something cumbersome such as:
class NewElem : Element() {
// ...
}
fun Element.newelem(fn: NewElem.() -> Unit = {}): NewElem {
val e = NewElem()
e.fn()
this.addChild(e)
return e
}
every time.
Is there a clean way to hide this implementation detail?
I want to be able to create a new element by simply extending Element for example.
I do not want to use reflection if possible.
Possibilities I Tried
My main problem is coming up with a clean solution. I thought of a couple other approaches that didn't pan out.
1) Create new elements with a function call that returns a function to be used in the builder style such as:
// Pre-defined
fun createElement(...): (Element.() -> Unit) -> Element
// Created as
val newelem = createElement(...)
// Used as
body {
newelem {
p { +"newelem example" }
}
}
There are obvious downsides to this, and I don't see a clear way to implement it either - probably would involve reflection.
2) Override the invoke operator in companion object
abstract class Element {
companion object {
fun operator invoke(build: Element.() -> Unit): Element {
val e = create()
e.build()
return e
}
abstract fun create(): Element
}
}
// And then you could do
class NewElem : Element() {
companion object {
override fun create(): Element {
return NewElem()
}
}
}
Body {
NewElem {
P { text = "NewElem example" }
}
}
It is unfortunately not possible to enforce "static" functions to be implemented by subclasses in a type-safe way.
Also, companion objects aren't inherited, so the invoke on subclasses wouldn't work anyway.
And we again run into problems about adding children elements to the correct context, so the builder doesn't actually build anything.
3) Override the invoke operator on Element types
abstract class Element {
operator fun invoke(build: Element.() -> Unit): Element {
this.build()
return this
}
}
class NewElem(val color: Int = 0) : Element()
Body() {
NewElem(color = 0xff0000) {
P("NewElem example")
}
}
This might have worked, except for when you immediately try to invoke on the object created by the constructor call, the compiler cannot tell that the lambda is for the "invoke" call and tries to pass it into the constructor.
This can be fixed by making something slightly less clean:
operator fun Element.minus(build: Element.() -> Unit): Element {
this.build()
return this
}
Body() - {
NewElem(color = 0xff0000) - {
P("NewElem example")
}
}
But yet again, adding children elements to the parent elements isn't actually possible without reflection or something similar, so the builder still doesn't actually build anything.
4) Calling add() for sub-elements
To try to fix the issue of the builder not actually building anything, we could implement an add() function for sub-elements.
abstract class Element {
fun add(elem: Element) {
this.children.add(elem)
}
}
Body() - {
add(NewElem(color = 0xff0000) - {
add(P("NewElem red example"))
add(P("NewElem red example 2"))
})
add(NewElem(color = 0x0000ff) - {
add(P("NewElem blue example"))
})
}
But this is obviously not clean and is just deferring the cumbersome-ness to the usage side instead of the implementation side.
I think it's unavoidable to add some sort of a helper function for each Element subclass you create, but their implementation can be simplified with generic helper functions.
For example, you can create a function that performs the setup call and adds the new element to the parent, then you only have to call into this function and create an instance of your new element:
fun <T : Element> Element.nest(elem: T, fn: T.() -> Unit): T {
elem.fn()
this.addChild(elem)
return elem
}
fun Element.newElem(fn: NewElem.() -> Unit = {}): NewElem = nest(NewElem(), fn)
Alternatively, you could create that instance via reflection to simplify even further, but since you've stated you'd like to avoid it, this will probably seem unnecessary:
inline fun <reified T : Element> Element.createAndNest(fn: T.() -> Unit): T {
val elem = T::class.constructors.first().call()
elem.fn()
this.addChild(elem)
return elem
}
fun Element.newElem(fn: NewElem.() -> Unit = {}) = createAndNest(fn)
These still leave you with having to declare a factory function with the appropriate header, but this is the only way to achieve the syntax that the HTML example achieves, where a NewElem can be created with its own newElem function.
I came up with a solution that isn't the most elegant, but it is passable and works the way I would want it to.
It turns out that if you override an operator (or create any extension function for that matter) inside a class, it has access to its parent context.
So I overrode the unary + operator
abstract class Element {
val children: ArrayList<Element> = ArrayList()
// Create lambda to add children
operator fun minus(build: ElementCollector.() -> Unit): Element {
val collector = ElementCollector()
collector.build()
children.addAll(collector.children)
return this
}
}
class ElementCollector {
val children: ArrayList<Element> = ArrayList()
// Add child with unary + prefix
operator fun Element.unaryPlus(): Element {
this#ElementCollector.children.add(this)
return this
}
}
// For consistency
operator fun Element.unaryPlus() = this
This allows me to create new elements and use them like this:
class Body : Element()
class NewElem : Element()
class Text(val t: String) : Element()
fun test() =
+Body() - {
+NewElem()
+NewElem() - {
+Text("text")
+Text("elements test")
+NewElem() - {
+Text("child of child of child")
}
+Text("it works!")
}
+NewElem()
}