迭代multidimesionn ArrayList

时间:2014-10-25 11:59:35

标签: java arraylist iteration

我搜索了很多我的问题的答案,但到目前为止我什么也没找到。

我正在为矩阵上的一些操作实现一个类。一开始我使用了2x2数组,但它们工作正常,但现在对于其他一些方法,我决定切换到2x2 ArrayList,它们更加通用。

我曾经在这个网站上找到了一个用于向这些列表添加元素的类(link),为了安慰我添加了一些新方法:

import java.util.ArrayList;

public class TwoDimensionalArrayList<T> extends ArrayList<ArrayList<T>>
{
    private static final long serialVersionUID = 1L;

    public void addToInnerArray(int index, T element)
    {
        while (index >= this.size())
        {
            this.add(new ArrayList<T>());
        }
        this.get(index).add(element);
    }

    public void addToInnerArray(int index, int index2, T element)
    {
        while (index >= this.size())
        {
            this.add(new ArrayList<T>());
        }

        ArrayList<T> inner = this.get(index);
        while (index2 >= inner.size())
        {
            inner.add(null);
        }

        inner.set(index2, element);
    }

    public T getFromInnerArray(int index, int index2)
    {
        ArrayList<T> inner = this.get(index);
        return inner.get(index2);
    }

    public void removeFromInnerArray(int index, int index2)
    {
        ArrayList<T> inner = this.get(index);
        inner.remove(index2);
        this.remove(index);
        this.add(index, inner);
    }

    public void setToInnerArray(int index, int index2, T t)
    {
        this.removeFromInnerArray(index, index2);
        this.addToInnerArray(index, index2, t);
    }

    public final String repr()
    {
        StringBuffer str = new StringBuffer();
        int i = 0;
        int j = 0;

        while(i < this.size())
        {
            while(j < this.get(i).size())
            {
                str.append(String.valueOf(this.get(i).get(j)));
                str.append(" ");
                j += 1;
            }
            j = 0;
            str.append("\n");
            i += 1;
        }

        return str.toString();
    }
}

然后我的矩阵类是这样的:

import java.util.Scanner;
import java.util.Arrays;
import java.util.ArrayList;
import java.lang.reflect.Array;
import java.lang.Math;

import informatica.python.TwoDimensionalArrayList;

public final class Matrix
{
    private final int nrows;
    private final int ncolumns;
    public final TwoDimensionalArrayList<Double> matrix = new TwoDimensionalArrayList<Double>();
    //private final byte precision = 3;

    Matrix(int rows, int cols)
    {
        this.nrows = rows;
        this.ncolumns = cols;
        /*for(int i = 0; i < this.nrows; i++)
        {
            matrix.add(new ArrayList<Double>());
        }*/
    }

    public final void init()
    {
        Scanner sc = new Scanner(System.in);
        for(int i = 0; i < this.nrows; i++)
        {
            for(int j = 0; j < this.ncolumns; j++)
            {
                matrix.addToInnerArray(i, (Double) sc.nextDouble());
            }
        }
        //sc.close();
    }

    public final void setValue(int row, int col, Double val)
    {
        this.matrix.setToInnerArray(row, col, val);
    }

    public final void setValue(int row, ArrayList<Double> val)
    {
        this.matrix.set(row, val);
    }

    public final void setValue(ArrayList<ArrayList<Double>> val)
    {
        this.matrix.clear();
        for(ArrayList<Double> subList: val)
        {
            this.matrix.add(subList);
        }
    }

    public final Double getValue(int row, int col)
    {
        return this.matrix.getFromInnerArray(row, col);
    }

    public final ArrayList<Double> getValue(int row)
    {
        return this.matrix.get(row);
    }

    public final ArrayList<ArrayList<Double>> getValue()
    {
        return this.matrix;
    }

    /*public final int getPrecision()
    {
        return Math.pow(10,precision);
    }*/

    public final int[] getLength()
    {
        int[] len = new int[2];
        ArrayList<Double> subMatrix = this.matrix.get(0);

        len[0] = this.matrix.size();
        len[1] = subMatrix.size();

        return len;
    }

    public final String repr()
    {
        return this.matrix.repr();
    }

    public final void sum(Matrix b)
    {
        if(Arrays.equals(this.getLength(), b.getLength()))
        {
            for(int i = 0; i < this.nrows; i++)
            {
                for(int j = 0; j < this.ncolumns; j++)
                {
                    System.out.print(i + ", " + j + ": ");
                    System.out.print(this.getValue(i,j) + " + " + b.getValue(i,j) + " = ");
                    Double r = (Double) (double) Math.round((this.getValue(i,j) + b.getValue(i,j)) * 1000) / 1000;
                    System.out.println(r);
                    this.setValue(i, j, r);
                }
            }
        }
        else
        {
            System.err.println("Cannot sum two non-similar matrices.");
        }
    }
}

我写了更多的方法,但逻辑总是相同的(差异,标量产品等)。

这是要运行的应用程序:

import informatica.Matrix;
import informatica.python.TwoDimensionalArrayList;

import java.lang.reflect.Array;
import java.util.ArrayList;

class App
{
    public static void main(String[] args)
    {
        Matrix a = new Matrix(2,3);
        Matrix b = new Matrix(2,3);

        a.init();
        b.init();
        System.out.println(a.repr());
        System.out.println(b.repr());

        a.sum(b);
    }
}

我无法真诚地发现任何语义错误,但eclipse引发了这个错误:

//input
1 2 3
4 5 6
//two different matrices
7 8 9
10 11 12
//end input
1.0 2.0 3.0
4.0 5.0 6.0

7.0 8.0 9.0
10.0 11.0 12.0
Exception in thread "main"
0, 0: 1.0 + 7.0 = 8.0
0, 1: 3.0 + 8.0 = 11.0
0, 2: java.lang.IndexOutOfBoundsException: Index: 2, Size: 2
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at informatica.python.TwoDimensionalArrayList.getFromInnerArray(TwoDimensionalArrayList.java:37)
at informatica.Matrix.getValue(Matrix.java:62)
at informatica.Matrix.sum(Matrix.java:105)
at informatica.App.main(App.java:25)

据我所知,似乎索引依次存在,我无法理解为什么它增加2:1.0 + 7.0都是(0,0),但3.0 + 8.0分别是(0 ,2)和(0,1)。真诚地,我不知道为什么会这样。

提前致谢。

3 个答案:

答案 0 :(得分:1)

因为您缩小了列表并使用索引覆盖了值:

public void setToInnerArray(int index, int index2, T t)
{
    this.removeFromInnerArray(index, index2);//1
    this.addToInnerArray(index, index2, t);//2
}

如果我将index = 0和索引2传递给0并将值t传递给10并且我在arrayList中有[3,4],那么上面将会:

  1. 从索引0中删除3,在第0个索引
  2. 中留下带有[4]的arraylist
  3. 在索引0处设置10,这意味着您将[10]

答案 1 :(得分:1)

你的问题就在这里:

public void addToInnerArray(int index, int index2, T element) {
    while (index >= this.size()) {
        this.add(new ArrayList<T>());
    }

    ArrayList<T> inner = this.get(index);
    while (index2 >= inner.size()) {
        inner.add(null);
    }

    inner.set(index2, element); // <- this line
}

您使用setToInnerArrayremoveFromInnerArray从内部数组列表中删除旧元素,但不是添加新元素,而是覆盖现有元素。因此,内部列表保留在2而不是3元素。

将上述行更改为:

inner.add(index2, element); // "add" instead of "set"

您可能会尝试熟悉使用调试器,因为它们可以在这种情况下帮助您。

答案 2 :(得分:1)

问题是您在操作期间正在更改矩阵。你打电话

a.sum(b);

调用

for (int i = 0; i < this.nrows; i++) {
    for (int j = 0; j < this.ncolumns; j++) {
        System.out.print(i + ", " + j + ": ");
        System.out.print(this.getValue(i, j) + " + " + b.getValue(i, j) + " = ");
        Double r = (Double) (double) Math.round((this.getValue(i, j) + b.getValue(i, j)) * 1000) / 1000;
        System.out.println(r);
        this.setValue(i, j, r);
    }
}

最后一行this中的this.setValue(i, j, r)引用a(调用实例)。你正在做的是将结果设置到调用操作的矩阵中,而不是将结果设置为新的矩阵。

你会做得更好的是sum static Matrix方法Matrix result = Matrix.sum(a, b); 返回一个新矩阵并使用

addToInnerArray

编辑如其他答案中所述,导致问题的确切行是在this.setValue内调用的sum方法。但是,当你想要进行多次重复使用索引时,你无法获得正确的结果(异常与否),因为你正在动态地改变你的输入。使用静态方法作为操作(scalarProductvectorProd,{{1}}等)的设计将确保这不会成为问题。