Arrays.fill с многомерным массивом в Java - PullRequest
51 голосов
/ 19 августа 2011

Как я могу заполнить многомерный массив в Java без использования цикла?Я пробовал:

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

Это приводит к java.lang.ArrayStoreException: java.lang.Double

Заранее спасибо!

Ответы [ 11 ]

83 голосов
/ 19 августа 2011

Это потому, что double[][] - это массив double[], которому вы не можете присвоить 0.0 (это все равно что делать double[] vector = 0.0).Фактически, в Java нет настоящих многомерных массивов.

Как это бывает, 0.0 - это значение по умолчанию для двойных чисел в Java, таким образом, матрица будет фактически заполнена нулями, когда выполучить его от new.Однако, если вы хотите заполнить его, скажем, 1.0, вы можете сделать следующее:

Я не верю, что API предоставляет метод для решения этой проблемы без использования цикла.Однако достаточно просто сделать это с циклом for-each.

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

// Fill each row with 1.0
for (double[] row: matrix)
    Arrays.fill(row, 1.0);
59 голосов
/ 19 августа 2011
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);
9 голосов
/ 19 августа 2011

ОП спросил, как решить эту проблему без петли !По некоторым причинам в наши дни модно избегать петель.Почему это?Вероятно, есть осознание того, что использование map, reduce, filter, друзей и таких методов, как each, скрывают циклы и сокращают программные ошибки, и это довольно круто.То же самое касается действительно хороших конвейеров Unix.Или код JQuery.Вещи просто отлично выглядят без циклов.

Но есть ли в Java метод map?Не совсем, но мы могли бы определить один с Function интерфейсом с помощью метода eval или exec.Это не слишком сложно и будет хорошим упражнением.Это может быть дорого и не использоваться на практике.

Другой способ сделать это без цикла - использовать хвостовую рекурсию.Да, это глупо, и никто бы не использовал его на практике, но это показывает, может быть, что циклы в этом случае хороши.Тем не менее, просто для того, чтобы показать «еще один пример без петель» и повеселиться, вот что:

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));
    }
}

Это не красиво, но в ответе на вопрос ОП нет никаких явных петли.

5 голосов
/ 29 декабря 2018

Согласно Java 8, мы можем использовать этот способ.

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

Мы можем инициализировать значение в многомерном массиве более хорошим и умным способом.

4 голосов
/ 19 августа 2011

как заполнить многомерный массив в Java без использования цикла?

Многомерные массивы - это просто массивы массивов, а fill(...) не проверяет тип массива и значение, которое вы передаете (эта ответственность ложится на разработчика).

Таким образом, вы не можете заполнить многомерный массив достаточно хорошо без использования цикла.

Помните о том, что в отличие от языков, таких как C или C ++, массивы Java являются объектами, а в многомерных массивах все, кроме последнего уровня, содержат ссылки на другие Array объекты. Я не уверен на 100% в этом, но, скорее всего, они распределены в памяти, поэтому вы не можете просто заполнить непрерывный блок без цикла, как C / C ++ позволил бы вам это сделать.

3 голосов
/ 19 июня 2013

В качестве дополнения к ответу я нашел этот пост, но собирался заполнить 4-мерный массив.Исходный пример - это только двумерный массив, но в вопросе сказано «многомерный».Я не хотел публиковать новый вопрос для этого ...

Вы можете использовать тот же метод, но вы должны вложить их так, чтобы в итоге вы получили одномерный массив.

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);
        }
    }
};
1 голос
/ 30 января 2016

Не всем ли нам иногда хотелось, чтобы был
<T>void java.util.Arrays.deepFill(T[]…multiDimensional). Проблемы начинаются с
Object threeByThree[][] = new Object[3][3];
threeByThree[1] = null; и
threeByThree[2][1] = new int[]{42}; совершенно законно.
(Если бы только Object twoDim[]final[] было законным и четко определенным…)
(Использование одного из общедоступных методов снизу сохраняет циклы в исходном коде вызова.
Если вы настаиваете на том, чтобы вообще не использовать циклы, замените циклы и вызов на Arrays.fill() (!) С помощью рекурсии.)

/** 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);
}
0 голосов
/ 29 сентября 2018

Простыми словами java donot предоставляют такой API.Вам нужно перебрать цикл и, используя метод заливки, вы можете заполнить 2D-массив одним циклом.

      int row = 5;
      int col = 6;
      int cache[][]=new int[row][col];
      for(int i=0;i<=row;i++){
          Arrays.fill(cache[i]);
      }
0 голосов
/ 15 августа 2017

Используя Java 8, вы можете объявить и инициализировать двумерный массив без использования (явного) цикла следующим образом:

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][]);

Это инициализирует массивы со значениями по умолчанию (0.0 вcase double).

Если вы хотите явно определить значение заполнения, которое будет использоваться, вы можете добавить в 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][]);
0 голосов
/ 08 марта 2016
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]);
        }
    }

Я надеюсь, что это хорошо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...