Diving array into subarrays issue

Remco Bravenboer :

I am trying to divide an array containing many numbers into smaller arrays and I use a 2D array for that.

In the below example I have an array containing 16 elements (int[] numbers). In the code below you will see what I have made so far. splitArray is working when I want to divide it into 4 smaller arrays (int arrayAmount). I am trying to spread the array across a 2D array splittedArray.

private static final int NUMBER_COUNT = 16;
private static int threadAmount = 4;
private static int lowestNumber = Integer.MAX_VALUE;

public static void main(String[] args) {
        int[] numbers = generateNumber(NUMBER_COUNT);
        System.out.println("Original array:\n" + Arrays.toString(numbers));
        int[][] splittedArray = new int[threadAmount][(numbers.length/threadAmount)];

        // Split arrays and print them
        splitArray(threadAmount, numbers, splittedArray);
        System.out.println("\nSplit arrays:\n" + Arrays.deepToString(splittedArray));
    }

private static void splitArray(int arrayAmount, int[] numbers, int[][] splittedArray) {
        int elPerSubArr = numbers.length / arrayAmount;

        int x = 0;
        int i = x;

        if (numbers.length != 0) {
            while (i < numbers.length) {
                for (int j = 0; j < elPerSubArr; j++) {
                    splittedArray[x][j] = numbers[i];
                    i++;
                }
                x++;
            }
        } else {
            System.out.println("There are no elements inside this array!");
        }
    }

Now when I call the splitArray method with an arrayAmount and a length of numbers that's % 0 when divided by the arrayAmount it works fine. For example: 16 and 4. splitArray[0] to [3] will all contain 4 elements then in that case.

How can I modify my code so that it also works when I put 15 elements? I am obviously getting an ArrayIndexOutOfBoundsException on the line where I set a value for splittedArray[x][j] since it will always loop 4 times. I have been trying for hours now and can't figure it out.

Karol Dowbecki :

You can delay the int[][] allocation until you reach the remaining elements. The last array in the result will be smaller.

Do note that you current numbers.length / arrayAmount expression won't calculate the correct length e.g. 3 / 2 = 1 due to integer arithmetic. You can fix it by using Math.ceil().

public static void main(String[] args) {
    int[] numbers = {1, 2, 3, 4, 5};
    int[][] splits = splitArray(2, numbers);
    System.out.println("Split arrays: " + Arrays.deepToString(splits));
}

private static int[][] splitArray(int splitCount, int[] numbers) {
    if (numbers.length == 0) {
        return new int[0][0];
    }

    int splitLength = (int) Math.ceil((double) numbers.length / (double) splitCount);
    int[][] splits = new int[splitCount][];

    int j = 0;
    int k = 0;
    for (int i = 0; i < numbers.length; i++) {
        if (k == splitLength) {
            k = 0;
            j++;
        }
        if (splits[j] == null) {
            int remainingNumbers = numbers.length - i;
            splits[j] = new int[Math.min(remainingNumbers, splitLength)];
        }
        splits[j][k++] = numbers[i];
    }
    return splits;
}

Will print:

Split arrays: [[1, 2, 3], [4, 5]]

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325399&siteId=1