How to create a new list from another in Kotlin? - list

In Java we can create a new list from another like this:
List<Integer> list1 = new ArrayList<>();
list1.add(1)
list1.add(-10)
list1.add(12)
list1.add(37)
List<Integer> list2 = new ArrayList<>(list1);
how can we achieve the same result as above in Kotlin using listOf() or mutableListOf()?

You can use .toList() and .toMutableList() extensions to copy a container (an array, a collection, a sequence) into a new list:
val list1 = listOf(1, -10, 12, 37)
val list2 = list1.toList()
val mutableList2 = list2.toMutableList()

Related

Getting the elements from a list of lists with the Java Stream API in Kotlin

The following code (written in Kotlin) extracts the elements from a list of lists. It works, but looks rather ugly and difficult to read.
Is there a nicer way to write the same with the java stream api? (Examples can be given in Kotlin or Java)
val listOfLists: List<Any> = ...
val outList: MutableList<Any> = mutableListOf()
listOfLists.forEach {
list ->
if (list is ArrayList<*>) list.forEach {
l ->
outList.add(l)
}
}
return outList;
In Kotlin it's super easy without any excessive boilerplate:
val listOfLists: List<List<String>> = listOf()
val flattened: List<String> = listOfLists.flatten()
flatten() is the same as doing flatMap { it }
In Java, you need to utilize Stream API:
List<String> flattened = listOfLists.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
You can also use Stream API in Kotlin:
val flattened: List<String> = listOfLists.stream()
.flatMap { it.stream() }
.collect(Collectors.toList())
You could flatMap each list:
List<List<Object>> listOfLists = ...;
List<Object> flatList =
listOfLists.stream().flatMap(List::stream).collect(Collectors.toList());
Use flatMap
List<Integer> extractedList = listOfLists.stream().flatMap(Collection::stream).collect(Collectors.toList());
flatMap() creates a stream out of each list in listOfLists. collect() collects the stream elements into a list.

How do I pass by reference in Scala? with a ListBuffer

I want to pass an object in Scala by reference.
The pseudo code is something like
var list1 = List(//stuff in here)
var list2 = List(//stuff in here).toBuffer
list1.forEach(element => foo(element,list2)
def foo(element,list2){
remove something from list 2
}
so on each iteration of the forEach, list2 would be different :/
What would be the best way to do this on scala. Thanks :D
A List().toBuffer will generate a ArrayBuffer which itself is mutable. So you don't have to use var.
The key thing is that what's the code piece in "remove something from list 2". Here's a sample code to do this without problem:
val a = List(1,2)
val b = List(1,3,2).toBuffer
a.foreach(ele => foo(ele, b))
println(b)
def foo(ele: Int, b: mutable.Buffer[Int]): Unit = {
b -= ele
}
In the foo, use BufferLike.-= method to remove inside the Buffer of it, then it would be fine if this is what you want. The code will generate output:
ArrayBuffer(3)
def main(args: Array[String]): Unit = {
var list1 = List(1, 2, 3)
var list2 = List(1, 2, 3, 4).toBuffer
list1.foreach(
element =>
list2 = foo(element, list2)
)
}
def foo(element: Int, list2: Buffer[Int]) = {
println("list2 length:" + list2.length)
list2.foreach(println)
var newlist = list2.drop(element)
newlist
}
Something like this ? It's not a good way as Dima said.

I want to add element at the end of list in scala. How can i achieve it?

Lets take an example where store is my class.
class store(val a:Int) { }
In the code i want to create a list of store.
val list : List[store] = new List[store]()
How can i add a store in the same list?
First off, it's usually a good idea to capitalize your class names.
scala> class Store(val a:Int) { }
defined class Store
scala> val list : List[Store] = List.empty
list: List[Store] = List()
scala> val newList = new Store(4) :: list
newList: List[Store] = List(Store#243306de)
Your list is, by default, immutable so you'll have a new list every time an element is added.
scala> val newerList = new Store(71) :: newList
newerList: List[Store] = List(Store#30f57af0, Store#243306de)
ADDENDUM
If you need a mutable list (not usually recommended) you could try the following.
scala> import scala.collection.mutable.MutableList
import scala.collection.mutable.MutableList
scala> val myList: MutableList[Store] = MutableList.empty
myList: scala.collection.mutable.MutableList[Store] = MutableList()
scala> myList += new Store(56)
res322: myList.type = MutableList(Store#6421614e)
scala> myList += new Store(29)
res323: myList.type = MutableList(Store#6421614e, Store#85b26)
scala> myList += new Store(11)
res324: myList.type = MutableList(Store#6421614e, Store#85b26, Store#5d2f7883)
Mutable variables are considered poor style and an impediment to proper Functional Programming.
To add element to the beginning of the list use :: :
val l = List(1, 2, 3)
val l1 = 5 :: l // List(5, 1, 2, 3)
or
val l1 = l.::(5)
To add element to the end of the list use :+ :
val l2 = l :+ 5 // List(1, 2, 3, 5)
So, to add store object to the end of the list (though it is not efficient), write this:
val s = new Store(1)
val newList = list :+ s // list is immutable

Scala hashmap of listbuffers

I am trying to emulate a defaultdict(list) in Scala (I've already declared scala.collection.mutable.HashMap).
Right now I am trying
val d = new HashMap[Int,ListBuffer[Int]](){ override def default(key:Int) = ListBuffer[Int]() }
And then to append to a list I try something like:
d(integerKey) += integerValToInsertIntoList
But nothing seems to work and d acts like it's always empty?
Here is the proper way of implementing this for mutable Maps:
val d = new HashMap[Int,ListBuffer[Int]]() {
override def apply(key: Int) = super.getOrElseUpdate(key, ListBuffer())
}
d(4) append 4
d(5) append 5
scala> d(4)
res1: scala.collection.mutable.ListBuffer[Int] = ListBuffer(4)
scala> d(5)
res2: scala.collection.mutable.ListBuffer[Int] = ListBuffer(5)
Note
Using withDefaultValue does not work as expected for mutable Maps. It will reuse the same "default" ListBuffer() for all new entries.
val d = new HashMap[Int,ListBuffer[Int]]().withDefaultValue(ListBuffer())
d(4) append 4
d(5) append 5
In the REPL we see that d(4) (same for d(5)) will hold both new added entries:
scala> d(4)
res1: scala.collection.mutable.ListBuffer[Int] = ListBuffer(4, 5)
scala> d(5)
res2: scala.collection.mutable.ListBuffer[Int] = ListBuffer(4, 5)

Adding consecutive elements of ArrayList

I am trying to achieve the following:
Given a list {146,7,-2,-1} write a new list such that its ith element consists of sums of "i" and i+1".
So this list: {146,153,151,150} would be transformed into 146 as 146+7=153, 153+(-2)=151 and so on.
I wrote the following:
List<Integer> list = new ArrayList<Integer>();
List<Integer> list2 = new ArrayList<Integer>();
list2.add(0, list.get(0));
for(int i=0;i<list.size()-1;i++)
{
list2.add(i+1, list.get(i+1)+list.get(i));
System.out.println(list2);
}
However, this is returning {146,153,6,-3}. What I am doing wrong?
You should be adding to list2.get(i) instead of list.get(i)
List<Integer> list = new ArrayList<Integer>();
List<Integer> list2 = new ArrayList<Integer>();
list2.add(0, list.get(0));
for(int i=0;i<list.size()-1;i++)
{
list2.add(i+1, list.get(i+1)+list2.get(i));
System.out.println(list2);
}