将2D ArrayList转换为2D数组

3

我已经查看了几个答案,但是我发现这些答案都有错误。我正在尝试将一个Double[]的ArrayList转换为普通的双精度浮点型2D数组。我的代码如下:

    public ArrayList<Double[]>  ec;
    public double[][]           ei;
    ...
    encogCorpus = new ArrayList<Double[]>();
    ...
    ec.add(inputs);
    ...
    ei = new double[ec.size()][];

    for (int i = 0; i < ec.size(); i++) {
        ArrayList<Double> row = ec.get(i);
        ei[i] = row.toArray(new double[row.size()]);
    }

我收到了以下错误信息:

类型不匹配:无法将Double[]转换为ArrayList

以及

类型ArrayList中的toArray(T[])方法不适用于参数(double[])

4个回答

4

问题

  1. 首先,这里的 ec 是类型为 ArrayList<Double[]> 的,这意味着 ec.get(i) 应该返回 Double[] 而不是 ArrayList<Double>
  2. 其次,doubleDouble 是完全不同的类型。在您的代码中不能简单地使用 row.toArray(new double[row.size()])

解决方案

1.

如果您想要一个真正的二维 ArrayList,其中包含 Doubles,那么 ec 应该是 ArrayList<ArrayList<Double>> 类型。但由于我们不能使用 toArray(),所以我们手动循环。

public ArrayList<ArrayList<Double>> ec;  // line changed here
public double[][]                   ei;
...
encogCorpus = new ArrayList<ArrayList<Double>>(); // and here also
...
ec.add(inputs); // `inputs` here should be of type `ArrayList<Double>`
...
ei = new double[ec.size()][];

for (int i = 0; i < ec.size(); i++) {
    ArrayList<Double> row = ec.get(i);

    // Perform equivalent `toArray` operation
    double[] copy = new double[row.size()];
    for (int j = 0; j < row.size(); j++) {
        // Manually loop and set individually
        copy[j] = row.get(j);
    }

    ei[i] = copy;
}

2.

如果您坚持要使用ArrayList<Double[]>,我们只需要更改主要部分:

public ArrayList<Double[]>  ec;
public double[][]           ei;
...
encogCorpus = new ArrayList<Double[]>();
...
ec.add(inputs);
...
ei = new double[ec.size()][];

for (int i = 0; i < ec.size(); i++) {
    // Changes are only below here

    Double[] row = ec.get(i);
    double[] copy = new double[row.length];

    // Still, manually loop...
    for (int j = 0; j < row.length; j++) {
        copy[j] = row[j];
    }

    ei[i] = copy;
}

3.

最后,如果您可以将Double[]更改为double[],解决方案2将变为:

public ArrayList<double[]>  ec; // Changed type
public double[][]           ei;
...
...
for (int i = 0; i < ec.size(); i++) {
    // Simpler changes here
    ei[i] = ec.get(i).clone();
}
...

我将ec更改为public ArrayList<double[]>,并且ec.add(inputs)似乎可以工作,但是'// Changes are only below here'就无法工作了。 - jonbon
@jonbon,我的错误,出现了一个奇怪的错别字! - Jason Sparc
1
@jonbon,我已经编辑了我的答案!但是,我仍然无法相信我没有看到那个问题,也没有其他人看到。 - Jason Sparc
我可以将Double[]更改为double[]。我只需要使用一个for循环并使用clone()吗? - jonbon
@jonbon 我推荐使用 clone,它更快,无论是在输入还是运行时都如此 :) - Jason Sparc
显示剩余3条评论

3
基本上你只需要这样做:
for (int i = 0; i < ec.size(); i++) {
    Double[] boxedRow = ec.get(i);
    double[] unboxedRow = new double[boxedRow.length];
    for (int j = 0; j < boxedRow.length; j++)
        unboxedRow[j] = boxedRow[j];
    ei[i] = unboxedRow;
}

您遇到了因装箱和拆箱而引起的问题。手动将 Doubles 拆箱为 doubles,可以使我们将数组转换为正确的类型。

另一种解决方案是:

public ArrayList<Double[]>  ec;
public Double[][]           ei; // no need to unbox

// ...

for (int i = 0; i < ec.size(); i++) {
    ei[i] = ec.get(i);
}

我要补充的是,你现在的解决方案不是一个二维 ArrayList;它是一个由 Double 数组组成的 ArrayList。看起来你可能想做的是这样:

public ArrayList<ArrayList<Double>>  ec;
public double[][]                    ei;

// ...

for (int i = 0; i < ec.size(); i++) {
    ArrayList<Double> row = ec.get(i);
    Double[] rowArray = row.toArray(new Double[row.size()]);
    double[] unboxedRow = new double[rowArray.length];
    for (int j = 0; j < rowArray.length; j++)
        unboxedRow[j] = rowArray[j];
    ei[i] = unboxedRow;
}

这可能是这样的:

public ArrayList<ArrayList<Double>>  ec;
public Double[][]                    ei;

// ...

for (int i = 0; i < ec.size(); i++) {
    ArrayList<Double> row = ec.get(i);
    ei[i] = row.toArray(new Double[row.size()]);
}

最后,请注意当你实例化新的 Double[] 时,数组会初始化为 null 而不是 0。如果你尝试以下操作,你将会得到一个 NullPointerException,尽管它会编译通过。

Double[] boxedArray = new Double[1];
double unboxed = boxedArray[0]; // equiv to "double unboxed = null;"

你需要小心拆包,并确保正确处理空值。

非常棒的答案,非常感谢。当我将类型更改为ArrayList<ArrayList<Double>>时,如果item是double[],我就不能再使用ec.add(item)了吗? - jonbon
这很棘手,因为 Double[] 实际上是指向 Double(或 null)的指针数组。而 double[] 是一个 double 数组,所以实际的值存储在数组中,而不仅仅是指针。这就是为什么 double[] 永远不包含 null。这使得我们必须手动将我们的 doubles 装箱成一个指向 Double 引用的数组。Java 不能隐式地将 double[] 转换为 Double[] - Joseph Nields
1
另一个解决方案,如果可能的话,是简单地使用 double[] 而不是 Double[]。这样就可以进行简单的 clone() 操作。 - Jason Sparc

2
List<double[]> list = Arrays.asList(new double[]{1.1, 2.0}, new double[]{3.0, 5.8});
double[][] res = list.toArray(new double[list.size()][]);
// System.out.println(Arrays.deepToString(res));

将ArrayList转换为2d int数组的方法相同。

0

错误在以下行:

for (int i = 0; i < ec.size(); i++) {
    ArrayList<Double> row = ec.get(i);
    ei[i] = row.toArray(new double[row.size()]);
}

第一个错误将通过用Double[]替换ArrayList<Double>来解决:

for (int i = 0; i < ec.size(); i++) {
    Double[] row = ec.get(i);
    ei[i] = row.toArray(new double[row.size()]);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接