这是我的代码。我想从文件加载数据并在代码中处理它。我在输出中感到困惑。数据可以自行改变。这是主类中的主要方法。有代码打印(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中打印的输出有什么区别?为什么数据会自行改变,它必须相同,请帮助...
答案 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])