Guys how can I fix the error java.util.ConcurrentModificationException: null
experiments.forEach {
if(NAME_VARIANT == it.variantName) {
for (i in (0..Math.min(result.size - 1, Constants.MAX_METHODS_APPLIED))) {
if (response.paymentMethods[i].scoring.rules!!.none { it.ruleName == NAME_RULE}) {
response.appliedExperiments.clear()
}
}
}
}
This exception ConcurrentModificationException is thrown when you're trying to modify a collection at the same time as iterating over it.
In the piece of code you provided, you're iterating over experiments, and you're modifying response.appliedExperiments (by calling clear() on it). If those 2 variables actually point to the same collection, calling clear() is expected to throw.
In order to do what you want, you probably want those lists to start off as copies of each other, but still be different. When you create response.appliedExperiments, make sure it's a new list and not the same list.
EDIT: in the code you provided, you are passing experiments directly to the constructor of SortingServiceResponse, and I'm guessing this constructor uses the list as-is as the appliedExperiments property of reponse. Instead, you should pass a copy of the list, for instance using toMutableList():
val response = SortingServiceResponse(experiments.toMutableList(), result)
An even better approach would be to use read-only List instead of MutableList for experiments to avoid making this kind of mistakes in the first place. Only use mutable collections when you really need to. Most of the time, you can use operators (like filter or map) that create new read-only lists instead of working with mutable lists directly.
I have a very simple problem, I need to convert a LinkedHashSet that holds one type of object, into another.
So basically what I want to do is something like this(if map could return anything else than TypeB:
LinkedHashSet<TypeA> firstSet
LinkedHashSet<TypeB> secondSet = firstSet.map {
TypeB(firstSet.value1, firstSet.value2)
}
This is mostly written to signalize what I want to achieve, of course it doesn't work. Could someone help me write this in Kotlin?
map returns a List, but you can use mapTo to insert the resulting elements directly into a collection that you provide as its first argument. This collection is also returned so you can assign it to secondSet:
val secondSet: LinkedHashSet<TypeB> = firstSet.mapTo(LinkedHashSet<TypeB>()) {
TypeB(it.value1, it.value2)
}
This is more efficient than using map because it avoids creating an intermediate List to hold the results.
The question I want to ask is about programming related question in kotlin.
This question may seem really bad , but I can't think how to handle this situation.
val array = ArrayList<ArrayList<Int>>()
val subAnswer = ArrayList<Int>()
subAnswer.add(1)
subAnswer.add(2)
subAnswer.add(3)
array.add(subAnswer)
subAnswer.clear()
If I printed out the array , it is empty . The behaviour I have expected is subAnswer is cleared but the array will contain [[1,2,3]]
I want to know why.
Isn't it supposed to contained [[1,2,3]] ?
Why clearing subAnswer also cleared the array?
And how can it be solved?
I thought an object was copied and added to the array so the added object to array and subAnswer doesn't share the same memory address. In this case , it seems like the added object is just a reference of the subAnswer so clearing subAnswer can also affect the array.
If I want to get the expected behavior, how can I do it ?
If there's any programming concept related blogs about this problem , please let me know it.
Thank you.
At first you've added a reference of an array contained in subAnswer to variable array and then cleared values in that reference.
Since they were the same reference in the heap, changing it from one variable changes it.
To preserve the list, you can make a duplicate of it,
array.add(ArrayList(subAnswer)) // <- creates a new ArrayList with elements from subAnswer
subAnswer.clear()
PS: Using ArrayList directly is not a recommended style in Kotlin, you should use MutableList instead.
val list = mutableListOf<List<Int>>() // or use MutableList instead if you like too use
val subAnswer = mutableListOf<Int>()
subAnswer.add(1)
subAnswer.add(2)
subAnswer.add(3)
list.add(subAnswer.toList()) // copies and create new list, or use toMutableList to create a mutable list
subAnswer.clear()
We are encouraged to have immutable variables as much as we can.
But sometimes when I have to modify a list I start to wonder which approach would be better for current situation...
val mutableList = mutableListOf()
// where I can just .add() / .remove() accordingly
or
var immutableList = listOf()
// where I can create a new list (using filter or `+`) each time a change is made
I guess there are different scenarios one is preferred over the other.
Hence I would like to know when one should be used over the other
val -> You could think that you can't reassign for the variable.
//that is ok
var a:Int = 1
a=2
//Even you can reassign but you can't change its type
a= "string" //that's wrong
//that is wrong
val b:Int = 1
b = 2
ListOf -> You could think that you can't insert/delete/alter any element in the list
(can't do anything to the content of the list)
var list:List<Int> = listOf(1,2,3,4) //[1,2,3,4]
//you can read list
list.get(0)
list[0]
//but you can't change(/write) the content of the list (insert/delete/alter)
list.set(0, 100)
list.add(5)
list.removeAt(0)
var mutableList:MutableList<Int> = mutableListOf(1,2,3,4) //[1,2,3,4]
//you can read and write
mutableList.get(0)
mutableList.set(0, 100) //[100,2,3,4]
mutableList.add(5) //[100,2,3,4,5]
mutableList.removeAt(0) //[2,3,4,5]
SO
combine both of them, you will get four cases
Case 1: var mutableList:MutableList = mutableListOf(1,2,3,4)
//you can reassign
mutableList = mutableListOf(4,5,6,7) //[4,5,6,7]
//you can alter the content
mutableList.set(0, 100) //[100,5,6,7]
mutableList.add(8) //[100,5,6,7,8]
mutableList.removeAt(0) //[5,6,7,8]
Case 2: val mutableList:MutableList = mutableListOf(1,2,3,4)
//you can't reassign
mutableList = mutableListOf(4,5,6,7) //that's wrong
//you can alter the content
mutableList.set(0, 100) //[100,2,3,4]
mutableList.add(8) //[100,2,3,4,8]
mutableList.removeAt(0) //[2,3,4,8]
Case 3: var list:List = ListOf(1,2,3,4)
//you can reassign
list= ListOf(4,5,6,7) //[4,5,6,7]
//you can't alter the content
list.set(0, 100) //that's wrong
list.add(8) //that's wrong
list.removeAt(0) //that's wrong
Case 4: val list:List = ListOf(1,2,3,4)
//you can't reassign
list= ListOf(4,5,6,7) //that's wrong
//you can't alter the content
list.set(0, 100) //that's wrong
list.add(8) //that's wrong
list.removeAt(0) //that's wrong
//the only thing you can do is Read
list.get(0) //return 1
list[0] //return 1
Mutable and immutable list increase the design clarity of the model.
This is to force developer to think and clarify the purpose of collection.
If the collection will change as part of design, use mutable collection
If model is meant only for viewing, use immutable list
Purpose of val and var is different from immutable and mutable list.
val and var keyword talk about the how a value/reference of a variable should be treated.
var - value/reference assigned to a variable can be changed at any point of time.
val - value/reference can be assigned only once to a variable and can't be changed later point in the execution.
It is completely valid in Kotlin to assign mutable list to a val and add element to it.
val a = mutableListOf(1,2,3,4)
a.add(5)
println(a)
will output
[1, 2, 3, 4, 5]
I guess there are different scenarios one is preferred over the other. Hence would like to get to know when one should be used over the other etc.
There are several reasons why immutable objects are often preferable:
They encourage functional programming, where state is not mutated, but passed on to the next function which creates a new state based on it. This is very well visible in the Kotlin collection methods such as map, filter, reduce, etc.
A program without side effects is often easier to understand and debug (you can be sure that the value of an object will always be the one at its definition).
In multithreaded programs, immutable resources cannot cause race conditions, as no write access is involved.
You have also some disadvantages:
Copying entire collections just to add/remove a single element is computationally expensive.
In some cases, immutability can make the code more complex, when you tediously need to change single fields. In Kotlin, data classes come with a built-in copy() method where you can copy an instance, while providing new values for only some of the fields.
Which one you end up using depends on the use case at hand. For data classes (bundling a few attributes together), it's often a good idea to stick to immutability. For collections, if you use immutable ones just to modify their copies and re-assign the reference pointing to them all the time, you can as well use mutable ones. If you share a collection to many parts of your application that depend on the state remaining constant, use immutable.
Keep in mind that Kotlin collections have different concepts:
Mutable collections: MutableList<T>, MutableSet<T>, MutableMap<T>
These can be modified at any time.
Read-only collections: List<T>, Set<T>, Map<T>
These provide a read-only view on the collection, i.e. the collection cannot be modified through that reference. It gives no guarantee about immutability though (another mutable reference to it can still exist and used for modification).
(Proposed, not yet part of Kotlin)
Immutable collections: ImmutableList<T>, ImmutableSet<T>, ImmutableMap<T>
These would guarantee true immutability, and provide patterns to build new modified collections based on them. See the Proposal for details.
I'm going through this example of a force based layout.
http://bl.ocks.org/sathomas/774d02a21dc1c714def8
The layout is defined as
force = d3.layout.force()
.size([width, height])
.nodes(dataNodes)
.links(dataLinks);
Later in the code though the author iterates through the link array with this call
force.linkStrength(function(link) {
if (link.className === 'red') return 0.1;
return 1;
});
How does the author know that function(link) will iterate over the link array and not the node array?
Because when you write this:
force = d3.layout.force()
.size([width, height])
.nodes(dataNodes)
.links(dataLinks);
You're doing what is called a method chaining. d3.js is known to use them a lot and each method chaining (with this framework at least) returns an object, depending of the method you call. With this particular code, it acts this way:
Set the size of the force object and return the force object
Set the nodes of the force object and return the nodes property of force
Set the links of the nodes object, and return the links property of nodes
So, each method chaining that you add returns something different. At the end of all the method calls, the whole thing will be considered as returning the return value of your last call, and it will assign it to the variable at the left of the = operator. Here, your force variable.
It's exactly as if you wrote:
force = d3.layout.force()
force = force.size([width, height])
force = force.nodes(dataNodes)
force = force.links(dataLinks)
When, later on, you iterate over your force variable, you necessarily iterate over the links array, because that's what you assigned to force.
Tip 1: The tricky part is that here, and generally in d3.js, each method does not return the same objects. Both d3.layout.force() and size() return the actual force object, whereas nodes() returns the nodes object and links() returns the links object. It's cascading method chaining. Each element of the chain is called on the object returned by the previous method call.
Tip 2: you can understand from this that it's not necessarily the best fit to name this variable force.
There's also a cool explanation that goes into further details from Scott Murray.