6

In my program, I am trying to print sorted int array using stream. But I am getting false output while using normal stream. And correct details are getting printed while using int stream.

Please refer below core snippet for more details.

package com.test.sort.bubblesort;

import java.util.Arrays;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class BubbleSortWithRecursion {

    public static void bubbleSort(int[] arr, int n) {

        if (n < 2) {
            return;
        }

        int prevValue;
        int nextValue;
        for (int index = 0; index < n-1; index++) {
            prevValue = arr[index];
            nextValue = arr[index+1];

            if  (prevValue > nextValue) {
                arr[index] = nextValue;
                arr[index+1] = prevValue;
            }
        }

        bubbleSort(arr, n-1);
    }

    public static void main(String[] args) {
        int arr[] = new int[] {10,1,56,8,78,0,12};
        bubbleSort(arr, arr.length);

        **//False Output** :  [I@776ec8df
        String output = Arrays.asList(arr)
            .stream()
            .map(x -> String.valueOf(x))
            .collect(Collectors.joining(","));

        System.out.println(output);

        //Correct Output : 0,1,8,10,12,56,78
        String output2 = IntStream
            .of(arr)
            .boxed()
            .map(x -> Integer.toString(x))
            .collect(Collectors.joining(","));

        System.out.println(output2);

    }


}

And I am getting following output on console :

[I@776ec8df
0,1,8,10,12,56,78

The fist line of output was generated using normal java stream which is not correct.

Why am I getting false content using normal JAVA stream ? Am I missing something here ?

3 Answers 3

10

You can solve your issue like so :

String output = Arrays.stream(arr)
        .boxed()
        .map(String::valueOf)
        .collect(Collectors.joining(",")); // 0,1,8,10,12,56,78

Explain what happen :

when you use Arrays.asList() which look :

public static <T> List<T> asList(T... a) {
    return new ArrayList<>(a);
}

it took varargs of type T, in your case you use it for int[] Object, so Arrays.asList() will return List of int[] and not a stream of ints, so instead you have to use Arrays.stream which look like this :

public static IntStream stream(int[] array) {
    return stream(array, 0, array.length);
}

to get the correct data.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you very much for sharing the suggestion here. Your answer is smilar to Eran's answer but Varargs mapping explanation is more clearly explained in Eran's answer. So accepting the answer.
7

Arrays.asList(arr) returns a List<int[]> whose only element is arr. Therefore streaming that List and then mapping that single element to String.valueOf(x) and collecting with Collectors.joining(",") will result in a String whose value is that single array's toString(), which is the output you see.

String output = Arrays.asList(arr) // List<int[]>
    .stream() // Stream<int[]>
    .map(x -> String.valueOf(x)) // Stream<String> having a single element - "[I@776ec8df"
    .collect(Collectors.joining(",")); // "[I@776ec8df"

When you create an IntStream from the int array, you get a stream of the individual elements (the int values), so you can box them, convert then to Strings and join them to get the desired output.

You can make your first snippet work if you change:

int arr[] = new int[] {10,1,56,8,78,0,12};

to:

Integer arr[] = new Integer[] {10,1,56,8,78,0,12};

since this way Arrays.asList(arr) will produce a List<Integer> containing all the elements of the input array.

4 Comments

Thank you for sharing answer. Still I have one confusion. Arrays.asList generate List<int[]> while using primitive type. Should not it produce List<Integer[]> while using wrapper type ?
@GunjanShah to understand it better, Integer is an Object, int is just a native type, so when you use array of native type it can considered as one Object, instead of array of Integer it considered as array of Objects
@GunjanShah The signature is static <T> List<T> asList(T... a). T must be a reference type, so if you pass a primitive array, the array itself is that reference type. If you pass an array of some reference type (such as Integer array), T becomes the element type of the array (Integer).
wow... this was looking simple but very good concept is hidden here. This answer helped me to make my varargs concept more clear. Thank You !
0

You can do it even a bit shorter:

String output = Arrays.stream(arr)
        .mapToObj(String::valueOf)
        .collect(Collectors.joining(","));

The result is 0,1,8,10,12,56,78

First you create an IntStream, then you get a Stream<String> which is collected to the final String.

Comments

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.