I have:
var myList: MutableList<MutableList<Int>>
and I want to dynamically create a list (i, j) which are Int and it is to the myList.
I tried
myList.add(mutableListOf(i,j))
But it doesn't work.
Firstly I get error: variable 'myList' must be initialized
And I am not sure that's the right way to make a list on the go and add it to a list of lists
As the error mentions, you have to initialize the list before using it.
var myList: MutableList<MutableList<Int>> with this you just declare its type.
var myList = mutableListOf<MutableList<Int>>() with this you have empty list. After that you can freely add another list inside it as an element.
initialize the list
var myList: MutableList<Int> = ArrayList()
Related
I am a beginner in this field, I want to create a list of float values in kotlin
Example: In python
myList=[]
mylist.append(1.5)
mylist.append(2.5)
but how to do this in kotlin
We need to specify the list element's data type (Float in this case) when initializing empty mutable list using mutableListOf().
val myList = mutableListOf<Float>()
myList.add(1.5f)
myList.add(2.5f)
Use the listOf function:
val listOfFloats: List<Float> = listOf(1.1f, 2.2f, 3.3f)
In kotlin you can make a list like this
var myList: List<Int> = listOf<Int>(1, 2, 7, 9);
But if you want to push an item to the list you need to make it a mutable list. So I would say that you use a MutableList instead of a List
So it looks like this
var myList : MutableList<Int> = mutableListOf<Int>(); //You can add initial values inside the parentheses
myList.add(10);
myList.add(20);
I am reading through the existing codebase for my team, and I notice mutableListOf are always declared as val. In some scenarios, elements are added to the mutableListOf only once. E.g
val jobList = mutableListOf<JobActivity>()
jobList.addAll(job.activities)
In other scenarios, elements are added to mutableListOf in a loop. E.g
val jobList = mutableListOf<JobActivity>()
newJobList.filterScanType(retrieveJobType(JobContext.NEW)).forEach {
jobList.add(it)
}
Since the list is not initialized on creation, why not declare mutableListOf as var? A lot of examples found online also follow the same pattern of declaring mutableListOf as val.
Which is best to use in the 2 scenarios described, val or var?
I think it's declared as val because the list will be the same always, the only thing that changes is it's elements. You'll never do something like:
joblist = anotherList
And as #Taseer said, the properties of the object can be changed even if it's a val. For example:
data class Example(var name: String)
val exampleObject = Example("SomeName")
You'll still be able to do this:
exampleObject.name = "AnotherName"
But you can't do this:
exampleObject = anotherObject
The general rule of thumb while using Kotlin.
Difference in val and var
You may already know the differences but for the sake of an answer, I will repeat it. var lets you modify the reference of an object while val does not permit to change the reference of an object.
An object can be declared safely using either var or val keyword but the reason why you want to use val on an object(in most cases) is that you don't want to refer that class member with a new reference of a new instance of an object. That way, you always keep a reference to the original object and you can modify object properties.
In the case of var, though nothing wrong with it, you can still use it 'without' any problems. You can still access the object properties and modify them and also you will be able to refer that class member to a reference of a new object.
Example:
val myObject = MyObject()
myObject.something = 1 //can still modify object property.
myOjbect = MyObject() //re-referencing the object, NOT POSSIBLE
var myNewObject = MyNewObject()
myNewObject.someThing = "Hello world!" //can still modify object properties
myNewObject = MyNewObject() //can still reference it.
Why to use val over var in case of 'immutable' objects?
It gives you the security of not 'accidentally' placing a new reference.
But is there any performance benefit using val?
Answer: Final keyword benefit
val is more idiomatic for the reasons given in other answers and comments.
You said the val is not instantiated, but in your example code, it is.
val jobList = mutableListOf<JobActivity>()
is a factory that instantiates an empty MutableList<JobActivity>
Using this pattern (val not var, instantiated upon declaration) ensures that your code will never find an uninitialized or null value for jobList; and the compiler can prove it.
In short - there are no rules, its up to you
if you use val you can modify mutableList, but not reassign
if you need reassign another list to same variable, use var. In most cases you dont need it, thats why your team uses it frequently
Whether a variable is var or val distinguishes between a variable of which the value (reference) can be changed (var = mutable) or not (val = immutable).
You should always strive to use val over var to avoid unwanted side-effects (changing it in another thread for example).
In case of the MutableList you should most likely use a val, because you don't want to mutate the reference to the list but rather its contents.
Here an overview of your options:
// Do you want to change its reference (r) / contents (c)?
var a = mutableListOf(1, 2, 3) // r = yes, c = yes
var b = listOf(1, 2, 3) // r = yes, c = no
val c = mutableListOf(1, 2, 3) // r = no, c = yes
val d = listOf(1, 2, 3) // r = no, c = no
You create a variable with var that is mutable (that can change). Mutable means variable can be changed in future.
val is used when variable will not be changed in future that means constant or final.
Here changed means new value or new things will be assigned to the variable but
val list = mutableListOf()
in this list variable you assigned mutable list. You just changed the value of the list. But you didn't assign new instance or new value to the variable you just added and remove value from the list. That's it. So here list is immutable itself.
It will be mutable if you do things like below...
var list = mutableListOf()
list = mutableListOf()
Two initialization on the same variable.
I am trying to copy one ArrayList to another ArrayList in Kotlin
1st ArrayList:
private var leadList1: ArrayList<Lead> = ArrayList()
2nd ArrayList:
val leadList2: ArrayList<Lead?>?
I tried to use addAll(). leadList1.addAll(leadList2)
But its not working.
Error showing:
Required: Collection<Lead>
Found: kotlin.collections.ArrayList<Lead?>?
This isn't safe to do, because your first list can only contain objects of type Lead, while your second one has Lead? as its type parameter, meaning that it might contain null values. You can't add those to the first list.
The solution for this problem will depend on your context, but you can either let the first list contain nullable elements too:
private var leadList1: ArrayList<Lead?> = ArrayList()
Or you can add only the non-null elements of the second list to the first one:
leadList1.addAll(leadList2.filterNotNull())
And in either case, you'll have to perform a null check on leadList2, because the entire list itself is marked as potentially null as well, signified by the last ? of the type ArrayList<Lead?>?.
if (leadList2 != null) {
leadList1.addAll(leadList2.filterNotNull())
}
You can simply pass another List instance into the constructor of your new List
val originalList = arrayListOf(1,2,3,4,5)
val orginalListCopy = ArrayList(originalList)
Do this:
leadList1.addAll(leadList2.orEmpty().filterNotNull())
And to filter by property you can do like this:
leadList1.addAll(leadList2.orEmpty().filter { item -> item?.type == YourTypeString })
How do I convert a Map<key,value> to a List<value>? Should I iterate over all map values and insert them into a list?
List<Value> list = new ArrayList<Value>(map.values());
assuming:
Map<Key,Value> map;
The issue here is that Map has two values (a key and value), while a List only has one value (an element).
Therefore, the best that can be done is to either get a List of the keys or the values. (Unless we make a wrapper to hold on to the key/value pair).
Say we have a Map:
Map<String, String> m = new HashMap<String, String>();
m.put("Hello", "World");
m.put("Apple", "3.14");
m.put("Another", "Element");
The keys as a List can be obtained by creating a new ArrayList from a Set returned by the Map.keySet method:
List<String> list = new ArrayList<String>(m.keySet());
While the values as a List can be obtained creating a new ArrayList from a Collection returned by the Map.values method:
List<String> list = new ArrayList<String>(m.values());
The result of getting the List of keys:
Apple
Another
Hello
The result of getting the List of values:
3.14
Element
World
Using the Java 8 Streams API.
List<Value> values = map.values().stream().collect(Collectors.toList());
map.entrySet() gives you a collection of Map.Entry objects containing both key and value. you can then transform this into any collection object you like, such as new ArrayList(map.entrySet());
a list of what ?
Assuming map is your instance of Map
map.values() will return a Collection containing all of the map's values.
map.keySet() will return a Set containing all of the map's keys.
I guess you want to convert the values contained in the Map to a list? Easiest is to call the values() method of the Map interface. This will return the Collection of value objects contained in the Map.
Note that this Collection is backed by the Map object and any changes to the Map object will reflect here. So if you want a separate copy not bound to your Map object, simply create a new List object like an ArrayList passing the value Collection as below.
ArrayList<String> list = new ArrayList<String>(map.values());
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("java", 20);
map.put("C++", 45);
Set <Entry<String, Integer>> set = map.entrySet();
List<Entry<String, Integer>> list = new ArrayList<Entry<String, Integer>>(set);
we can have both key and value pair in list.Also can get key and value using Map.Entry by iterating over list.
If you want to ensure the values in the resultant List<Value> are in the key-ordering of the input Map<Key, Value>, you need to "go via" SortedMap somehow.
Either start with a concrete SortedMap implementation (Such as TreeMap) or insert your input Map into a SortedMap before converting that to List. e.g.:
Map<Key,Value> map;
List<Value> list = new ArrayList<Value>( new TreeMap<Key Value>( map ));
Otherwise you'll get whatever native ordering the Map implementation provides, which can often be something other than the natural key ordering (Try Hashtable or ConcurrentHashMap, for variety).
// you can use this
List<Value> list = new ArrayList<Value>(map.values());
// or you may use
List<Value> list = new ArrayList<Value>();
for (Map.Entry<String, String> entry : map.entrySet())
{
list.add(entry.getValue());
}
Map<String, String > map = new HapshMap<String, String>;
map.add("one","java");
map.add("two", "spring");
Set<Entry<String, String>> set = map.entrySet();
List<Entry<String, String>> list = new ArrayList<Entry<String, String>> (set);
for(Entry<String, String> entry : list) {
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
Here's the generic method to get values from map.
public static <T> List<T> ValueListFromMap(HashMap<String, T> map) {
List<T> thingList = new ArrayList<>();
for (Map.Entry<String, T> entry : map.entrySet()) {
thingList.add(entry.getValue());
}
return thingList;
}
public List<Object> convertMapToList(Map<Object, Object> map){
return new ArrayList<>(map.values());
}
If you want an immutable copy of the values:
List<Value> list = List.copyOf(map.values())
I want to create a List of item from the field within another List of items.
private var destinies: MutableList<String> = ArrayList()
fun createDestinies(sources: List<Source>) {
for (source in sources) {
destinies.add(source.endpoint)
}
}
In order to do that, I need to define my destinies as MutableList, so that I could "add" to it. But I just need the "add" loop once.
Is there a way for me to do that, without need to have a MutableList? (i.e. I prefer an immutable List, since it doesn't need to change after that)
Apparently quite simple as below
private var destinies: List<String> = ArrayList()
fun createDestinies(sources: List<Source>) {
destinies = sources.map { it.endpoint }
}