Java:深度复制列表条目,不实例化新列表

时间:2013-01-30 19:56:08

标签: java list reference copy deep-copy

我在完成编程任务时遇到了一些问题。我想从文件中读取一些行(到目前为止没问题)并将其标记化。每一行都有大约4个令牌,每个令牌应该在列表中找到一个位置。最后,每一行也应该在列表中。

澄清这一点的一个小例子:

文件内容:

  

foo boo bar
bii buu baa

输出:

  

[[foo,boo,bar],[bii,buu,baa]]

继承我正在处理的代码

String fileContent = fileloader(file.toString());
List<String> linesList = new ArrayList<String>();
String[] lines = fileContent.split("\n"); 
for(String line:lines){
  String[] splittedLine = line.split("\t");
  for(String words:splittedLine){
    linesList.add(words);
  }
  lexiconContent.add(linesList); 
  linesList.removeAll(linesList);
}

我猜参考文献存在问题,因为第一次迭代效果很好!但在第二次迭代中,它将实际第二内容也复制到第一个(0)列表位置,依此类推。

最后我得到了类似[[], [], [], []]

的内容

2 个答案:

答案 0 :(得分:3)

问题在于,您只创建了一个列表,并通过在每次迭代时修改该列表,将该列表的引用添加到外部列表中。因此,对该列表进行的最终修改将反映在所有参考文献中。

您可以通过在循环中每次创建一个新linesList来解决此问题: -

List<String> linesList = null;  // Don't initialize here
String[] lines = fileContent.split("\n"); 

for(String line:lines){
    String[] splittedLine = line.split("\t");
    linesList = new ArrayList<String>(); // Initialize a new list everytime.

    for(String words:splittedLine){
        linesList.add(words);
    }
    lexiconContent.add(linesList); 
}

是的,您还可以将for循环简化为: -

for(String line:lines){
    String[] splittedLine = line.split("\t");
    lexiconContent.add(new ArrayList<String>(Arrays.asList(splittedLine))); 
}

这样,您不必遍历数组,并将单个元素添加到List中。实际上,您根本不需要中间列表。

答案 1 :(得分:0)

在你的代码中......而不是为循环中的每次迭代创建新的ArrayList:for(String line:lines)你只是在你使用过的ArrayList的旧对象中添加单词(在嵌套循环中)从外部循环的第一次迭代开始,并在lexiconContent ArrayList的所有后续索引处存储相同的参考值。在外部循环的每次迭代结束时,您正在清除linesList。所以最后您将保留在lexiconContent中有N个条目......其中lexiconContent的每个索引处的元素只是ArrayList(lineList)的单个对象的参考值,它是空的!

You should use following code instead:
String fileContent = fileloader(file.toString());
List<String> linesList = null;
String[] lines = fileContent.split("\n"); 
for(String line:lines){
  List<String> linesList = new ArrayList<String>();
  String[] splittedLine = line.split("\t");
  for(String words:splittedLine){
    linesList.add(words);
  }
  lexiconContent.add(linesList); 
}