2

I want to get a list of String in ArrayList<Array<String>> by using stream() and map in Kotlin.

Each Array<String> of my arrayList has 3 values and I want to get the first index value and the last index value of each array.

This is my code:

fun main(args: Array<String>) {
    val result: List<String>
    val obj1 = arrayOf("fruit", "Mangue", "Africa")
    val obj2 = arrayOf("Milk", "Soja", "Europ")
    val obj3 = arrayOf("Meat", "cochon","Asia")
    val myArrayList: ArrayList<Array<String>> = ArrayList<Array<String>>(3)  
    val myList: MutableList<Array<String>> = mutableListOf<Array<String>>()  
    myList.add(obj1)  
    myList.add(obj2)  
    myList.add(obj3)
    myArrayList.addAll(myList)  
    result = myArrayList.stream().map{it -> ("${it[0]}-${it[2]}")}.toList()
    println("ArrayList of objects  :")
    println(myArrayList)
    println("my list of String result")
    println(result)
}

I want to have this list of String in my result:

[fruit-africa,milk-Europ,Meat-Asia]

Also, when I print myArrayList, I have a bad result:

ArrayList of objects  :
[[Ljava.lang.String;@5caf905d, [Ljava.lang.String;@27716f4, [Ljava.lang.String;@8efb846]

How can I do it, please?

3
  • You don't have to use stream in Kotlin. Just simply do this: result = myArrayList.map{it -> "${it[0]}-${it[2]}"}. You can print myArrayList in multiple ways, for example println(myArrayList.joinToString(", ", "[", "]") { it.joinToString(", ", "[", "]") }) Commented Aug 24, 2022 at 17:24
  • Your bad result is because Arrays don’t have a nice toString() function like Lists do. You should call joinToString() on an Array before printing it. Commented Aug 24, 2022 at 17:41
  • 1
    Maybe it's worth highlighting once again: ArrayList is not an array; it's an implementation of the List interface. It happens to use an array internally, but that's just an implementation detail. And: You should prefer lists to arrays. Lists are much better supported in the standard library, play better with generics, have multiple implementations you can choose between, and usually have nice toString() etc. methods. Arrays have a few specific uses (varargs, interoperability with old code, low-level implementation) but for everything else, lists are better. Commented Aug 24, 2022 at 20:13

1 Answer 1

1

Your Question

When I run your code, this is the output I see:

ArrayList of objects  :
[[Ljava.lang.String;@5b480cf9, [Ljava.lang.String;@6f496d9f, [Ljava.lang.String;@723279cf]
my list of String result
[fruit-Africa, Milk-Europ, Meat-Asia]

And in your question, you have:

I want to have this list of String in my result:

[fruit-africa,milk-Europ,Meat-Asia]

So, it looks like you already have the output you want for result. The only difference from the actual output is the lack of a space after each comma. If you don't want that space, then use joinToString to customize the output:

println(result.joinToString(",", "[", "]"))

As for:

[[Ljava.lang.String;@5b480cf9, [Ljava.lang.String;@6f496d9f, [Ljava.lang.String;@723279cf]

You see that output because arrays don't override the toString() function, and therefore use the default implementation. In Kotlin, you can use contentToString() to get similar output as you see when printing a List.

println(myArrayList.joinToString(", ", "[", "]") { it.contentToString() })

So, here is the updated code with the above changes:

fun main(args: Array<String>) {
    val result: List<String>
    val obj1 = arrayOf("fruit", "Mangue", "Africa")
    val obj2 = arrayOf("Milk", "Soja", "Europ")
    val obj3 = arrayOf("Meat", "cochon","Asia")
    val myArrayList: ArrayList<Array<String>> = ArrayList<Array<String>>(3)
    val myList: MutableList<Array<String>> = mutableListOf<Array<String>>()
    myList.add(obj1)
    myList.add(obj2)
    myList.add(obj3)
    myArrayList.addAll(myList)
    result = myArrayList.stream().map{it -> ("${it[0]}-${it[2]}")}.toList()
    println("ArrayList of objects  :")
    println(myArrayList.joinToString(", ", "[", "]") { it.contentToString() })
    println("my list of String result")
    println(result.joinToString(",", "[", "]"))
}

Which gives this output:

ArrayList of objects  :
[[fruit, Mangue, Africa], [Milk, Soja, Europ], [Meat, cochon, Asia]]
my list of String result
[fruit-Africa,Milk-Europ,Meat-Asia]

Potential Improvements

With all that said, there are a few things you can simplify in your code:

  • This is a minor point, but since you don't use the args parameter you can actually omit it.

  • Your myList is not necessary; you can add your arrays directly to myArrayList.

  • Given the small number of elements in each array, and the small number of arrays, you can actually create the List<Array<String>> and populate it with a single listOf.

    • For variable types, you should prefer using List, the interface, rather than ArrayList, the implementation. This is known as "programming to an interface". Preferring List also means better use of listOf and mutableListOf, which are the idiomatic ways of creating lists in Kotlin.
  • You should prefer using List over arrays. In other words, create a List<List<String>> instead of a List<Array<String>>.

    • Lists do override the toString() method, providing readable output. Also, lists have better API support and work better with generics.
  • You don't need to use stream(). Kotlin provides many extension functions for arrays and Iterables, one of those being map which returns a List. Yes, these transformation functions are eagerly evaluated, unlike with streams, but given you're only performing one transfomration this doesn't really matter (in fact, the stream is likely less performant).

  • Given you want the first and last elements of each array, I would use first() and last().

Here is the simplified code (I added explicit types to make it clearer what the variables reference):

fun main() {
    val lists: List<List<String>> = listOf(
        listOf("Fruit", "Mangue", "Africa"),
        listOf("Milk",  "Soja",   "Europe"),
        listOf("Meat",  "Cochon", "Asia")
    )
    println("List of lists of strings:")
    println(lists)

    val result: List<String> = lists.map { "${it.first()}-${it.last()}" }
    println("Result:")
    println(result)
}

Output:

List of Arrays:
[[Fruit, Mangue, Africa], [Milk, Soja, Europe], [Meat, Cochon, Asia]]
Result:
[Fruit-Africa, Milk-Europe, Meat-Asia]
Sign up to request clarification or add additional context in comments.

3 Comments

Also you didn't say it explicitly, but it's better to use List instead of the specific ArrayList implementation. That way you'll get used to using things like listOf and you'll avoid requiring the ArrayList type for function parameters etc
Hi @Slaw If i have this situation val arrays: List<Array<String>> = listOf( arrayOf("Fruit", "Mangue", "Africa1", "Africa2", "Africa3", "Africa4"), arrayOf("Milk", "Soja", "Europe1", "Europe2", "Europe3", "Europe4"), arrayOf("Meat", "Cochon", "Asia1", "Asia2", "Asia3", "Asia4", "Asia5") ) and i want to get the first element and the fourth element, how can i do
@ln3106 You want the first element, so nothing needs to change there. And you want the fourth element, which is not the last element, so you have to change how you get the third/last element so that you now get the fourth element. Based on the code in your question, you already know how to do this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.