为什么输出有差异?为什么数据可以自行改变?

时间:2013-12-31 17:33:33

标签: java

这是我的代码。我想从文件加载数据并在代码中处理它。我在输出中感到困惑。数据可以自行改变。这是主类中的主要方法。有代码打印(i);这段代码输错了。

public static void main(String[] args) {

    ArrayList<Integer> ar = new ArrayList();
    ar.add(0);
    ar.add(2);
    ar.add(4);

    Data ds = new Data();
    ds.loadDataSet(new Loader(), ar);
    System.out.println("in main class");
    for (int i = 0; i < ds.size(); i++) {
        ds.print(i);   //give wrong output
    }
 }

主要方法调用 data.class 。这个类是处理和安排数据。在方法loadDataSet()中有一个代码打印(i);这是真正的输出。

public class Data {

private String[] attributeName;
private Instance[] setOfInstance;

public void loadDataSet(Loader loader, ArrayList<Integer> attributeIndex) {  

    System.out.println("inside data.class");     

    setOfInstance = new Instance[loader.dataSize()];
    double[] value = new double[attributeIndex.size()];
    for (int i = 0; i < setOfInstance.length; i++) {
        for (int j = 0; j < value.length; j++) {
            value[j] = loader.getValue(i, attributeIndex.get(j));
        }
        setOfInstance[i] = new Instance(loader.getTupleName(i), value);

        print(i);   //give true output
    }
}

public void print(int i) {
    double db[] = getInstance(i).getAllAttributeValue();
    System.out.print(getInstance(i).getInstaceName()+ "--");
    for (int j =0; j < db.length; j++) {
        System.out.print(db[j]+" ");
    }
    System.out.println();
}

public Instance getInstance(int index) {
    return setOfInstance[index];
}

public int size() {
    return setOfInstance.length;
}
}

Instance.class 用于处理实例数据。

public class Instance {

private String name;
private double[] attributeValue;

public Instance(String name, double[] attributeValue) {
    this.name = name;
    this.attributeValue = attributeValue;
}

public String getInstaceName() {
    return name;
}

public double[] getAllAttributeValue() {
    return attributeValue;
}

}

那是 loader.class 。数据来自的类。这只是一个例子。在我的真实代码中从csv文件加载的数据。这不是问题。

public class Loader {

private String[] name;
private double[][] value;

public Loader() {
    name = new String[] {"A", "B", "C", "D", "E"};
    value = new double[][] {{1, 2, 3, 4, 5}, {4, 5, 6, 7, 8}, {7, 8, 9, 10, 11}, {10, 11, 12, 13, 14}, {13, 14, 15, 16, 17}};
}

public String getTupleName(int index) {
    return name[index];        
}

public double getValue(int indexTuple, int indexAttribute) {
    return value[indexTuple][indexAttribute];
}

public int dataSize() {
    return value.length;
}
}

这是输出

inside data.class
A--1.0 3.0 5.0 
B--4.0 6.0 8.0 
C--7.0 9.0 11.0 
D--10.0 12.0 14.0 
E--13.0 15.0 17.0 
in main class
A--13.0 15.0 17.0 
B--13.0 15.0 17.0 
C--13.0 15.0 17.0 
D--13.0 15.0 17.0 
E--13.0 15.0 17.0 

为什么在方法中打印的输出主要与Data.class中打印的输出有什么区别?为什么数据会自行改变,它必须相同,请帮助...

2 个答案:

答案 0 :(得分:4)

TL;博士。你有一道代码,可以更好地将代码数量减少到可以重现问题的最小的示例。

然而,从输出中我可以肯定地说,你正在创建一个单行实例,操纵其中的值,并多次添加对单行的引用。相反,您需要为每行创建一个新对象并单独填充它们。这样,A,B,C,D,E行中的每一行都指向不同的行对象。


您遇到的问题可以使用以下伪代码进行演示:

ArrayList<Foo> list = new ArrayList();
Foo aFoo = new Foo();
aFoo.Bar = 2;
list.Add(aFoo);
aFoo.Bar = 3;
list.Add(aFoo);

foreach(x in list):
    print(x);

两次输出3

将此代码更改为以下内容将解决此问题:

ArrayList<Foo> list = new ArrayList();
Foo aFoo = new Foo();
aFoo.Bar = 2;
list.Add(aFoo);
aFoo = new Foo(); //note we are creating a *new* object here
aFoo.Bar = 3;
list.Add(aFoo);

foreach(x in list):
    print(x);

答案 1 :(得分:2)

double[] value在循环外定义,因此它是相同的数组,并在循环中覆盖它的值。

快速修复:

for (int i = 0; i < setOfInstance.length; i++) {
    double[] value = new double[attributeIndex.size()];
    for (int j = 0; j < value.length; j++) {
        value[j] = loader.getValue(i, attributeIndex.get(j));
    }
    setOfInstance[i] = new Instance(loader.getTupleName(i), value);

    print(i);   //give true output
}

另请注意,print(i);在此块中可能应为print(setOfInstance[i])