I was testing this code in java and was wondering, why manipulating Instance List2 affects Instance List1?
As both prints print the same list including "Kiwi"
Is that because List2 is a List reference while list1 is an ArrayList Class instance?
import java.util.ArrayList;
import java.util.List;
public static void main(String[] args) {
ArrayList<String> List1 = new ArrayList<String>();
List1.add("Apple");
List1.add("Banana");
List1.add("Orange");
List<String> List2 = List1;
List2.add("Kiwi");
System.out.printf("List1 =%s\n", List1);
System.out.printf("List2 =%s\n", List2);
}
}
It would be great to get an explanation,
thanks!
After this line...
List<String> List2 = List1;
... you have two variables pointing to the same ArrayList object.
Copying objects like lists is not trivial in Java. The next step for you might be:
List<String> List2 = new ArrayList<>(List1)
(btw... you shouldn't capitalize your variable names)
That will behave more according to you expectations, I think. If you define List2 that way, only List2 will get "Kiwi" added to it. List1 will remain as it was ("Apple", "Banana", "Orange").
This is actually all you need, since you are putting String objects in your lists, and Strings are immutable in Java.
However, suppose you did something like:
ArrayList<MyComplexObject> list1 = new ArrayList<>();
list1.add(new MyComplexObject());
list1.add(new MyComplexObject());
list1.add(new MyComplexObject());
ArrayList<MyComplexObject> list2 = new ArrayList<>(list1);
... you will have two separate lists. If you remove an element from list2, it will still be in list1. However, if you modify an element in list2, it will also be modified in list1. This is because, while the lists are separate objects, each one is pointing to the same instances of MyComplexObject.
If that behavior is not what you need, you need to do a "deep copy" of the List, which can be involved.
Related
Could you give an example to this quotation:
A key thing to keep in mind when working with collection interfaces is that read-only collections aren’t necessarily immutable. If you’re working with a variable that has a read-only interface type, this can be just one of the many references to the same collection. Other references can have a mutable interface type
I want to write a function that adds elements to some collection, while creating a val someCollection: List <> in the fun main(). I can do this through the var someCollection: List <> = funAdd(someCollection.toMutable), but can I do it like this without using a variable var?
Example
fun addEl(numbers:MutableList<Int>):List<Int>{
for (i in 1..10){
numbers.add(i)
}
return numbers.toList()
}
fun main(args: Array<String>){
var readOnlyNumbers: List<Int> = emptyList()
readOnlyNumbers = addEl(readOnlyNumbers.toMutableList())
println(readOnlyNumbers.size)
}
Can I avoid using var and reassigment readOnlyNumbers or not?
Here are various ways of rewriting your code without using var:
fun addEl(numbers:MutableList<Int>):List<Int>{
for (i in 1..10) {
numbers.add(i)
}
return numbers.toList()
}
fun main(args: Array<String>){
val readOnlyNumbers: List<Int> = addEl(mutableListOf())
println(readOnlyNumbers.size)
}
or simply
fun createEl(): List<Int> {
return (1..10).toList()
}
fun main(args: Array<String>){
val readOnlyNumbers = createEl()
println(readOnlyNumbers.size)
}
To answer this part:
Could you give an example to this quotation:
A key thing to keep in mind when working with collection interfaces is that read-only collections aren’t necessarily immutable. If you’re working with a variable that has a read-only interface type, this can be just one of the many references to the same collection. Other references can have a mutable interface type
This is simply talking about situations like this:
val mutableList: MutableList<Int> = mutableListOf<Int>()
val list: List<Int> = mutableList
println(list) // []
mutableList.add(0)
println(list) // [0]
Even though list has type List<Int> and not MutableList<Int>, its contents have changed.
Note that this is an example of
I want to write a function that adds elements to some collection, while creating a val someCollection: List <> in the fun main().
as well, but I wouldn't recommend writing this code; go with one of JB Nizet's versions.
I want to have an immutable list, since I don't really need the mutability so it likely to just cause bugs. However, the list is a lateinit var declared at the class level.
I want to initially populate the list with values from a loop somewhat like this:
for (items in someOtherCollection) {
val itemToAdd = doSomeProcessingOnThisData()
list.add(itemToAdd)
}
However, since the list is immutable, I can't call add(). Is there a better way to init a list such as this without simply adding all the values to a second, mutable list and then assigning it to an immutable list?
My current solution is this, but it just seems inefficient:
val tmpList = mutableListOf<Data>()
foos.forEach() {
val itemToAdd = doSomeProcessing()
foos.add(itemToAdd)
}
this.list = tmpList
If you want to make a new list processing some data in another collection, try this:
this.list = someOtherCollection.map {
doSomeProcessing()
}
Give this a read for a better understanding: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/map.html
I have a list of objects, each of which has a list of things. I wish to create a list of the things held in all of the objects. Is there a more pythonic way of doing this?
class Holder(object):
def __init__(self, things):
self.things = things
holder_one= Holder([1, 2])
holder_two = Holder(['a', 'b'])
holders = [holder_one, holder_two]
all_things = []
for holder in holders:
for thing in holder.things:
all_things.append(thing)
print all_things
You could either:
Make Holder inherit from list then this becomes pretty trivial.
Use extend instead of append, which will save you an explicit loop:
all_things = []
for holder in holders:
all_things.extend(holder.things)
print all_things
I have a following scenario
Object A has
-- List<B>
-- List<C>
-- Object A
Object A contains: List<B> and List<C>
I want to collect all objects of type 'B' in a List after traversal in a given object 'A'.
Note: List<C> may contain object 'A', so iteration becomes recursive.
I/P: Object A = {List<B>,List<C>}
O/P: List<B>//list of all objects of type B
What is the best way to iterate over this and collect objects of type 'B' to a List in JAVA 8.
Thanks
What I don't understand is why it has to be done soly with Stream? Why don't you just create a recursive function? And your List<A> definitely does not contain another List<A> and List<B>, your object A probably contains those two lists.
Here is a simple recursive method that should help you, but keep in mind that you did not really provide the code of A and B so we cannot really know:
public List<B> getAllBs(List<A> aList) {
return aList.stream()
.map(a -> getAllBs(a))
.collect(Collectors.toList());
}
private List<B> getAllBs(A someA) {
List<B> returnList = new ArrayList<B>();
returnList.addAll(someA.getListOfB());
for(A otherA: someA.getListOfA()) {
returnList.addAll(getAllBs(otherA);
}
return returnList;
}
Assuming that list is a List<List<A>> and B extends A, and you mean that any sub-list could have any amount of Bs but you don't want As:
List<A> allBs = list.stream() //Stream<List<A>>
.flatMap(l -> l.stream()) //Stream<A>
.filter(a -> a instanceof B) //Stream<A> containing only Bs
.collect(Collectors.toList()); //List<A> containing only Bs
Admittedly untested, because I'm working off many assumptions from a poor question.
I have a list and I want to copy three other lists into it.
// The main list
List<List<string>> list= new List<List<string>>();
// The lists which I want to combine
ArrayList sublist1= new ArrayList();;
ArrayList sublist2= new ArrayList();;
ArrayList sublist3= new ArrayList();;
What I tried is:
list[0].AddRange(sublist1);
list[0].AddRange(sublist2);
list[0].AddRange(sublist3);
It doesn't work because It is multidimensional list. I need this type of list for the future plans.
How can I accomplist it?
As already mentioned in comments just use List<string> instead of ArrayList.
It has nothing to do about multidimensional arrays, just types mismatch.
Then you say List<List<string>> it basically means create list type, which will contain List<string> as items (the part in angle brackets), so you need to add them, not ArrayLists. Similarly List<string> means type of list which will contain string as items.
As in the comments, you need to pass a type that follows IEnumerable. For example, you can change your ArrayLists to List
// The main list
List<List<string>> list = new List<List<string>>();
// The lists which I want to combine
var sublist1 = new List<string>();
var sublist2 = new List<string>();
var sublist3 = new List<string>();
list[0].AddRange(sublist1);
list[0].AddRange(sublist2);
list[0].AddRange(sublist3);
change type of sublists to some IEnumerable<string> (string[] or List<string> or something else)
var sublist1 = new string[] {};
var sublist2 = new string[] {};
var sublist3 = new string[] {};
OR do cast
list[0].AddRange((IEnumerable<string>) sublist1);
list[0].AddRange((IEnumerable<string>) sublist2);
list[0].AddRange((IEnumerable<string>) sublist3);
Because you are trying to use AddRange method of System.Collections.Generic.List<T>
and the signature of this method is
public void AddRange(System.Collections.Generic.IEnumerable<T> collection)
so it requires IEnumerable as a parameter.