Conversion of int array to ArrayList

Viewed 73

I have a function that gets an array of primitive data (int), I need to return the array of two elements the smallest and the largest number. If length of the array is 1 then just return two first elements int the array. I came up with such solution:

public static int[] minMax(int[] arr) {
    if (arr.length==1)
        return new int[]{arr[0],arr[0]} ;// return if arr is 1 element
    else {
        ArrayList<Integer> ar = new ArrayList<Integer>();
        //?
        return new int[]{Collections.max(ar),Collections.min(ar)};
    }
}

But how do I convert an array to an ArrayList? Is there a more efficient way maybe?

3 Answers

By calling Collections.min and Collections.max, you're iterating over the array twice. You can cut this time down by streaming the array and letting it do the heavy lifting, as James Mudd suggested. However, note that by doing so you'd be wasting time on calculating the sum and accumulating the count of the elements, which you don't care about. It may be more efficient to calculated these yourself:

public static int[] minMax(int[] arr) {
    // Assuming arr has at least one element
    int min = arr[0];
    int max = arr[0];
    for (int i = 1; i < arr.length; ++i) {
        int curr = arr[i];
        if (curr < min) {
            min = curr;
        } else if (curr > max) {
            max = curr;
        }
    }
    return new int[]{min, max};
}

You could use IntSummaryStatistics the method would look like

public static int[] minMax(int[] arr) {
    IntSummaryStatistics intSummaryStatistics = Arrays.stream(arr).summaryStatistics();
    return new int[] {intSummaryStatistics.getMin(), intSummaryStatistics.getMax()};
}

Here's another way of solving this task with streams.

Instead, using IntSummuryStatistics we can provide an array of two elements as a container of the resulting values while applying collect and manually define to accumulate stream elements in it.

public static int[] minMax(int[] sourceArr) {
    
    if (sourceArr.length == 0) throw new IllegalArgumentException(); // source array is empty
    
    return Arrays.stream(sourceArr)
        .collect(
            () -> new int[]{sourceArr[0], sourceArr[0]}, // mutable container
            (arr, next) -> {                             // accumulator - populating the container with elements of the stream
                arr[0] = Math.min(arr[0], next);
                arr[1] = Math.max(arr[1], next);
            },
            (left, right) -> {                           // combiner - merging containers in parallel
                left[0] = Math.min(left[0], right[0]);
                left[1] = Math.max(left[1], right[1]);
            });
}

main()

public static int[] minMax(int[] sourceArr) {
    System.out.println(Arrays.toString(minMax(new int[]{3, 5, -3, 8, 9})));
    System.out.println(Arrays.toString(minMax(new int[]{3, -1, 3, 12, 27})));
}

Output:

[-3, 9]
[-1, 27]

But how do I convert an array to an ArrayList?

It's not possible to convert an array of primitives into a List directly. When you have an array of reference type (like Integer, BigDecimal, etc.) you can use Arrays.asList() to fixed-size list wrapped around the given array. But it wouldn't work with primitive arrays.

In order to translate int[] into a List<Integer> you have to create a new list and populate it with the contents of the array.

So your actual goal is to obtain the result as a list, the code provided above might be changed like that:

public static List<Integer> minMax(int[] sourceArr) {
    
    if (sourceArr.length == 0) throw new IllegalArgumentException(); // source array is empty
    
    return Arrays.stream(sourceArr)
        .collect(
            () -> Arrays.asList(sourceArr[0], sourceArr[0]), // mutable container
            (list, next) -> {                             // accumulator - populating the container with elements of the stream
                list.set(0, Math.min(list.get(0), next));
                list.set(1, Math.max(list.get(1), next));
            },
            (left, right) -> {                           // combiner - merging containers in parallel
                left.set(0, Math.min(left.get(0), right.get(0)));
                left.set(1, Math.max(left.get(1), right.get(1)));
            });
}
Related