使用Java中的多维数组填充数组
如何在不使用循环的情况下使用Java填充多维数组?我已经试过:使用Java中的多维数组填充数组
double[][] arr = new double[20][4];
Arrays.fill(arr, 0);
这导致java.lang.ArrayStoreException: java.lang.Double
提前感谢!
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);
这是因为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);
这个就够用了'Arrays.fill(arr,0d);'或'Arrays.fill(arr,(double)0);' –
我得到'线程“main”java.lang.ArrayStoreException:java.lang.Double'中的异常,除非我循环遍历行。 – aioobe
你为什么不试着去理解这个答案?在Java(和C和C++)中没有多维数组!你的矩阵是一个简单的一维数组,每个“场”又是一个维数组。你对Arrays.fill()的调用会尝试将一个_int_(有一个双重写入0.0而不是简单的0)放入“矩阵”中,这不起作用。 –
我怎样才能填平Java多维数组,而不使用循环?
多维数组只是数组的数组,并且fill(...)
不检查数组的类型和传入的值(此责任在开发人员身上)。
因此,如果不使用循环,您无法合理填充多维数组。
请注意,与C或C++等语言不同,Java数组是对象,而在多维数组中,除最后一级外,其他所有对象都包含对其他Array
对象的引用。我对此不是100%确定,但很可能它们分布在内存中,因此,您不能仅仅填充没有循环的连续块,就像C/C++允许的那样。
OP问如何解决这个问题没有回路!由于某些原因,现在很流行避免循环。为什么是这样?可能有一种认识,使用map
,reduce
,filter
和朋友,以及像each
这样的方法可以隐藏循环并减少程序的运行时间,并且非常酷。对于非常好的Unix管道也是一样。或者jQuery代码。事情看起来很棒,没有循环。
但Java是否有map
方法?并非如此,但我们可以使用eval
或exec
方法将接口定义为Function
。这不是太难,会是一个很好的练习。它可能是昂贵的,并没有在实践中使用。
另一种方法做到这一点没有循环是使用尾递归。是的,这实在是太傻了,实际上也没有人会用它,但它确实表明,在这种情况下,循环很好。然而,只是为了显示“另一免费循环示例”和有乐趣,这里是:
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));
}
}
这是不漂亮,但在回答OP的问题,还没有明确的循环。
作为答案的延伸,我找到了这篇文章,但正在寻找填充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);
}
}
};
Arrays.fill(arr, new double[4]);
该行使每一行都指向相同的内存块,即更改arr [1] [5]也会更改arr [100] [5]。 –
不要我们有时会希望能有一个<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);
}
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]);
}
}
我希望这会做好
使用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
在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][]);
但为什么不使用一个循环? –
@Caroline:如果你想用0初始化2d数组,你不需要这样做,因为当你分配数组时,它已经被初始化为0,并且你不能在没有使用循环的情况下初始化任何数组。你可以隐藏像Arrays.fill一样在函数中循环。 – Emil
嘿,大家现在不要夸大它。他所需要的只是Java API中的一些方法,可以在单步骤中将多维数组初始化为某个默认值。这就是他想要说的没有循环。 –