98

How can I fill a multidimensional array in Java without using a loop? I've tried:

double[][] arr = new double[20][4];
Arrays.fill(arr, 0);

This results in java.lang.ArrayStoreException: java.lang.Double

3
  • 4
    @Caroline:If you are trying to initialize the 2d array with 0,u need not do so as it is already initialized with 0 when you allocate the array,and you cannot initialize any array without using a loop.You can just hide the loop in a function just as Arrays.fill does. Commented Aug 19, 2011 at 8:23
  • 2
    Hey guys don't exaggerate it now. All he wanted was some method in Java API to initialize multidimensional arrays to some default value in single step. That's what he wanted to say without a loop. Commented Dec 26, 2016 at 7:08
  • 2
    @Number945 I believe Caroline is a feminine name. Commented Jun 29, 2020 at 8:29

15 Answers 15

136

This is because a double[][] is an array of double[] which you can't assign 0.0 to (it would be like doing double[] vector = 0.0). In fact, Java has no true multidimensional arrays.

As it happens, 0.0 is the default value for doubles in Java, thus the matrix will actually already be filled with zeros when you get it from new. However, if you wanted to fill it with, say, 1.0 you could do the following:

I don't believe the API provides a method to solve this without using a loop. It's simple enough however to do it with a for-each loop.

double[][] matrix = new double[20][4];

// Fill each row with 1.0
for (double[] row: matrix)
    Arrays.fill(row, 1.0);
Sign up to request clarification or add additional context in comments.

3 Comments

This suffices too Arrays.fill(arr, 0d); or Arrays.fill(arr, (double)0);
I get Exception in thread "main" java.lang.ArrayStoreException: java.lang.Double unless I loop over the rows.
To nit-pick, Arrays.fill() tries to place a double into each row in the matrix.
101
double[][] arr = new double[20][4];
Arrays.fill(arr[0], 0);
Arrays.fill(arr[1], 0);
Arrays.fill(arr[2], 0);
Arrays.fill(arr[3], 0);
Arrays.fill(arr[4], 0);
Arrays.fill(arr[5], 0);
Arrays.fill(arr[6], 0);
Arrays.fill(arr[7], 0);
Arrays.fill(arr[8], 0);
Arrays.fill(arr[9], 0);
Arrays.fill(arr[10], 0);
Arrays.fill(arr[11], 0);
Arrays.fill(arr[12], 0);
Arrays.fill(arr[13], 0);
Arrays.fill(arr[14], 0);
Arrays.fill(arr[15], 0);
Arrays.fill(arr[16], 0);
Arrays.fill(arr[17], 0);
Arrays.fill(arr[18], 0);
Arrays.fill(arr[19], 0);

11 Comments

Hi. I'm just curios to know why you suggest this solution and not a classic for. Is there a motivation? Thanks!
Because of the following words in the question: "without using a loop". My solution is plainly ridiculous, but it does answer the question correctly.
Sorry, missed the "without using a loop" from the OP: removed my down-vote. Perhaps you should have made a remark in your answer that the suggestion shouldn't be taken too seriously.
No, it's also an interesting experiment: How many downvotes can you get for a correct answer?
@Bart: No problem - it doesn't matter :D
|
42

As Per Java 8, we can use this way.

double[][] arr = new double[20][4];
Arrays.stream(arr).forEach(a -> Arrays.fill(a, 0));

We can initialize a value in multidimensional array in a nicer and smart way.

3 Comments

I feel this is no better than a for loop from readability point of view.
@JianwuChen the OP asked to fill the array without a loop
@JianwuChen Actually readability depends somewhat on background: coming from scala this feels natural.
12

The OP asked how to solve this problem without a loop! For some reason it is fashionable these days to avoid loops. Why is this? Probably there is a realization that using map, reduce, filter, and friends, and methods like each hide loops and cut down on program verbage and are kind of cool. The same goes for really sweet Unix pipelines. Or jQuery code. Things just look great without loops.

But does Java have a map method? Not really, but we could define one with a Function interface with an eval or exec method. It isn't too hard and would be a good exercise. It might be expensive and not used in practice.

Another way to do this without a loop is to use tail recursion. Yes, it is kind of silly and no one would use it in practice either, but it does show, maybe, that loops are fine in this case. Nevertheless, just to show "yet another loop free example" and to have fun, here is:

import java.util.Arrays;
public class FillExample {
    private static void fillRowsWithZeros(double[][] a, int rows, int cols) {
        if (rows >= 0) {
            double[] row = new double[cols];
            Arrays.fill(row, 0.0);
            a[rows] = row;
            fillRowsWithZeros(a, rows - 1, cols);
        }
    }

    public static void main(String[] args) {
        double[][] arr = new double[20][4];
        fillRowsWithZeros(arr, arr.length - 1, arr[0].length);
        System.out.println(Arrays.deepToString(arr));
    }
}

It isn't pretty, but in answer to the OP's question, there are no explicit loops.

3 Comments

Thanks for all your solutions! The reason why I don't want to use a loop? I was looking for a simple solution for generating a n-by-n matrix of zeros like in MATLAB.
This might still cause a stack overflow, as Java has no tail recursion support, so loops definitely > recursion.
I'll tell you why it's "fashionable to avoid loops." Everyone and his brother fancies himself a Linux kernel programmer. Look at the code, and you'll find that loops are few and far between; people have, rather, hand-coded tests and branches, and the code is riddled with gotos. This made sense in early UNIX kernels in 1974, when it could be legitimately argued that the compiler generated suboptimal code for loops, but this HARDLY applies in 2016. However, every also-ran thinks that this looks terribly senior, particularly if he peppers the code with inane comments and has a Dutch surname.
5

As an extension to the answer, I found this post but was looking to fill a 4 dimensional array. The original example is only a two dimensional array, but the question says "multidimensional". I didn't want to post a new question for this...

You can use the same method, but you have to nest them so that you eventually get to a single dimensional array.

fourDArray = new float[10][10][10][1];
// Fill each row with null
for (float[][][] row: fourDArray)
{
    for (float[][] innerRow: row)
    {
        for (float[] innerInnerRow: innerRow)
        {
        Arrays.fill(innerInnerRow, -1000);
        }
    }
};

Comments

4

how can I fill a multidimensional array in Java without using a loop?

Multidimensional arrays are just arrays of arrays and fill(...) doesn't check the type of the array and the value you pass in (this responsibility is upon the developer).

Thus you can't fill a multidimensional array reasonably well without using a loop.

Be aware of the fact that, unlike languages like C or C++, Java arrays are objects and in multidimensional arrays all but the last level contain references to other Array objects. I'm not 100% sure about this, but most likely they are distributed in memory, thus you can't just fill a contiguous block without a loop, like C/C++ would allow you to do.

Comments

2

Arrays.fill works with single dimensional array, so to fill two dimensional array we can do below

for (int i = 0, len = arr.length; i < len; i++)
    Arrays.fill(arr[i], 0);

Comments

1

Don't we all sometimes wish there was a
<T>void java.util.Arrays.deepFill(T[]…multiDimensional). Problems start with
Object threeByThree[][] = new Object[3][3];
threeByThree[1] = null; and
threeByThree[2][1] = new int[]{42}; being perfectly legal.
(If only Object twoDim[]final[] was legal and well defined…)
(Using one of the public methods from below keeps loops from the calling source code.
If you insist on using no loops at all, substitute the loops and the call to Arrays.fill()(!) using recursion.)

/** Fills matrix {@code m} with {@code value}.
 * @return {@code m}'s dimensionality.
 * @throws java.lang.ArrayStoreException if the component type
 *  of a subarray of non-zero length at the bottom level
 *  doesn't agree with {@code value}'s type. */
public static <T>int deepFill(Object[] m, T value) {
    Class<?> components; 
    if (null == m ||
        null == (components = m.getClass().getComponentType()))
        return 0;
    int dim = 0;
    do
        dim++;
    while (null != (components = components.getComponentType()));
    filler((Object[][])m, value, dim);
    return dim;
}
/** Fills matrix {@code m} with {@code value}.
 * @throws java.lang.ArrayStoreException if the component type
 *  of a subarray of non-zero length at level {@code dimensions}
 *  doesn't agree with {@code value}'s type. */
public static <T>void fill(Object[] m, T value, int dimensions) {
    if (null != m)
        filler(m, value, dimensions);
}

static <T>void filler(Object[] m, T value, int toGo) {
    if (--toGo <= 0)
        java.util.Arrays.fill(m, value);
    else
        for (Object[] subArray : (Object[][])m)
            if (null != subArray)
                filler(subArray, value, toGo);
}

Comments

1

Using Java 8, you can declare and initialize a two-dimensional array without using a (explicit) loop as follows:

int x = 20; // first dimension
int y = 4; // second dimension

double[][] a = IntStream.range(0, x)
                        .mapToObj(i -> new double[y])
                        .toArray(i -> new double[x][]);

This will initialize the arrays with default values (0.0 in the case of double).

In case you want to explicitly define the fill value to be used, You can add in a DoubleStream:

int x = 20; // first dimension
int y = 4; // second dimension
double v = 5.0; // fill value

double[][] a = IntStream
        .range(0, x)
        .mapToObj(i -> DoubleStream.generate(() -> v).limit(y).toArray())
        .toArray(i -> new double[x][]);

1 Comment

This achieves the goal but man it's not simple. Java should have filled this gap when streams came in version 8.
1

In simple words java donot provide such an API. You need to iterate through loop and using fill method you can fill 2D array with one loop.

      int row = 5;
      int col = 6;
      int cache[][]=new int[row][col];
      for(int i=0;i<=row;i++){
          Arrays.fill(cache[i]);
      }

1 Comment

He wants to implement that without using the Loop, and your answer uses Loop to solve the problem.
1

Arrays.fill works only with one-dimensional array

Source of java.util.Arrays:

public static void fill(Object[] a, Object val) {
        int i = 0;

        for(int len = a.length; i < len; ++i) {
            a[i] = val;
        }

Use own loops for initialization array

Comments

0
public static Object[] fillArray(Object[] arr,Object item){
    Arrays.fill(arr, item);
    return arr;
}
Character[][] maze = new Character[10][10];
    fillArray(maze, fillArray(maze[0], '?'));

    for(int i = 0;i<10;i++){
        System.out.println();
        for(int j = 0;j<10;j++){
            System.out.print(maze[i][j]);
        }
    }

i hope this do well

2 Comments

This doesn't do well at all! Just add maze[2][2] = 'X'; after fillArray(maze, fillArray(maze[0], '?')); and you're in for a big surprise. The problem is that you create only one instance of a row and you refer to it 10 times. You discard 9 of the original 10 rows you created.
And it doesn't work win an int[][] array. It works with Character[][] because Character is an object.
0

Recursive Solution

A simple Recursive Solution to fill every row of a 2d array with any given value.

double[][] arr = new double[20][4];
int n=arr.length;
fillArrRecursively(arr, n-1, 10); //Recursion call

//Recursive method to fill every row of 'arr' with the passed variable 'val'

public static int fillArrRecursively(double arr[][], int n, int val){
    if(n<0) return 1;
    Arrays.fill(arr[n], val);
    return fillArrRecursively(arr, n-1, val);
}

1 Comment

You should at least add some explanation to your answer.
-2
     int dis[][]=new int[n][n];
     for(int x[]:dis)
        Arrays.fill(x,-1);
     

Comments

-10
Arrays.fill(arr, new double[4]);

1 Comment

This line makes every row refer to the same memory block, i.e. changing arr[1][5] will also change arr[100][5].

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.