我有从XML文件中读取的代码。它有五个字符串(groupId,groupType,filePath,author和lineNo),它首先将它们保存在一个字符串数组中。然后,String Array保存在ArrayList中。最后,最后一个“for”显示ArrayList的内容。
当我想显示内容时,我只得到最后添加的字符串数组。以下是代码和输出。任何人都可以找出问题所在?
ArrayList<String[]> developerTypes = new ArrayList<String[]>();
String[] developerInfo = {null, null, null, null, null};
String[] developerInfoR = {null, null, null, null, null};
String groupId;
String groupType;
String filePath;
String author;
String lineNo;
SAXBuilder builder = new SAXBuilder();
Document doc = (Document) builder.build("A.xml");
Element clones = doc.getRootElement();
// Loop of clones' children (clone_group)
List<Element> parentElements = clones.getChildren();
for(Element parentElement:parentElements){
// Loop of clone_group's children (clone_fragment)
List<Element> elements = parentElement.getChildren();
for(Element element:elements){
// Loop of clone_fragment's children (blameInfo)
List<Element> childelements = element.getChildren();
for(Element childElement:childelements){
groupId = parentElement.getAttributeValue("groupid");
groupType = parentElement.getAttributeValue("type");
filePath = element.getAttributeValue("file");
author = childElement.getAttributeValue("author");
lineNo = childElement.getAttributeValue("lineNo");
//System.out.print(groupId + " - ");
//System.out.print(groupType + " - ");
//System.out.print(file + " - ");
//System.out.println(author);
developerInfo[0] = groupId;
developerInfo[1] = groupType;
developerInfo[2] = filePath.substring(1, filePath.lastIndexOf("."));;
developerInfo[3] = author;
developerInfo[4] = lineNo;
developerTypes.add(developerInfo);
}// for (blameInfo)
}// for (clone_fragment)
}// for (clone_group)
// Display the content of the Arraylist
for(int i = 0; i< developerTypes.size(); ++i){
developerInfoR = developerTypes.get(i);
for(int j = 0; j< developerInfoR.length; ++j){
System.out.print(developerInfoR[j] + " ");
}
System.out.print("\n");
}
输出:
309 Type-3 builtin/update-index.c Jonathan Nieder 704
309 Type-3 builtin/update-index.c Jonathan Nieder 704
309 Type-3 builtin/update-index.c Jonathan Nieder 704
309 Type-3 builtin/update-index.c Jonathan Nieder 704
309 Type-3 builtin/update-index.c Jonathan Nieder 704
309 Type-3 builtin/update-index.c Jonathan Nieder 704
309 Type-3 builtin/update-index.c Jonathan Nieder 704
309 Type-3 builtin/update-index.c Jonathan Nieder 704
309 Type-3 builtin/update-index.c Jonathan Nieder 704
309 Type-3 builtin/update-index.c Jonathan Nieder 704
309 Type-3 builtin/update-index.c Jonathan Nieder 704
309 Type-3 builtin/update-index.c Jonathan Nieder 704
...
答案 0 :(得分:3)
当我想显示内容时,我只得到最后添加的字符串数组。
不,您发现相同的字符串数组有许多引用...因为这就是您添加的内容。你只有一个字符串数组 object ; developerInfo
只是对该数组的引用。当您致电developerTypes.add(developerInfo)
并将参考文献复制到ArrayList
时,您可以多次获得相同的参考。
您应该将developerInfo
的声明和实例化引入循环:
String[] developerInfo = {
groupId,
groupType,
filePath.substring(1, filePath.lastIndexOf(".")),
author,
lineNo
};
developerTypes.add(developerInfo);
同样,如果您在使用之前未声明developerInfoR
,则您的代码会更清晰:
for(int i = 0; i< developerTypes.size(); ++i){
String[] developerInfoR = developerTypes.get(i);
for(int j = 0; j< developerInfoR.length; ++j){
System.out.print(developerInfoR[j] + " ");
}
System.out.print("\n");
}
甚至更好,使用增强型for循环:
for (String[] developerInfoR : developerTypes) {
for (String info : developerInfoR) {
System.out.print(info + " ");
}
System.out.print("\n");
}
通常,你应该尽可能晚地声明具有最小范围的局部变量,理想情况下在声明点分配一个值。声明方法顶部的所有变量确实会损害可读性。
答案 1 :(得分:2)
您只有一个developerInfo
数组的实例,您可以在循环中反复添加。您需要在每个循环步骤中创建一个新数组。
您似乎对正在使用的contsructs的语义有一些误解。我从前面初始化developerInfoR
的方式推断出,但从不使用该值。数组变量只包含对数组的引用,因此每次分配给它时,之前引用的数组都会被遗忘并丢弃。所以,不要预先初始化developerInfo
。事实上,您甚至不需要在使用它之前声明它。
还有一种更简单的方法来打印数组的内容:只需调用System.out.println(Arrays.toString(developerInfoR))
即可。这样你甚至不需要打印代码中的内循环。
您不需要任何变量groupId,groupType,filePath,author,lineNo。只需编写例如developerInfo[0] = parentElement.getAttributeValue("groupid");
和类似的内容。这使得代码更加明显。但是使用完整对象而不是String []可能是有意义的。有许多字段,每个字段的含义都落后于整数索引。
总而言之,根据这些建议加上一些额外的建议,您的代码可以重写为:
final String path = filePath.substring(1, filePath.lastIndexOf("."));
final Document doc = (Document) new SAXBuilder().build("A.xml");
final List<DeveloperInfo> developers = new ArrayList<String[]>();
for (Element parentElement : doc.getRootElement().getChildren())
for (Element element : parentElement.getChildren())
for (Element childElement : element.getChildren())
developers.add(new DeveloperInfo(
parentElement.getAttributeValue("groupid"),
parentElement.getAttributeValue("type"),
element.getAttributeValue("file"),
path,
childElement.getAttributeValue("author"),
childElement.getAttributeValue("lineNo"),
));
for (DeveloperInfo d : developerTypes) System.out.println(d);
DeveloperInfo类:
class DeveloperInfo {
public final String groupId, groupType, filePath, author, lineNo;
public DeveloperInfo(
String groupId, String groupType, String filePath,
String author, String lineNo)
{
this.groupId = groupId; this.groupType = groupType; this.filePath = filePath;
this.author = author; this.lineNo = lineNo;
}
public String toString() {
return "DeveloperInfo [groupId=" + groupId + ", groupType=" + groupType +
", filePath=" + filePath + ", author=" + author + ", lineNo=" + lineNo + "]";
}
答案 2 :(得分:0)
每次将其添加到ArrayList
时,都会引用相同的数组。
而不是声明此String[] developerInfo = {null, null, null, null, null};
一开始。每次循环时创建一个新数组。
String[] developerInfo = new String[5];