【问题标题】:Java: deepcopy list entry without instancing a new listJava:无需实例化新列表的深层复制列表条目
【发布时间】:2013-01-30 19:56:07
【问题描述】:

我在执行编程任务时遇到了一个小问题。我想从文件中读取一些行(到目前为止没问题)并对其进行标记。每行大约有 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) 列表位置,依此类推。

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

【问题讨论】:

  • linesList.clear() 可能更快/更好地获得下一次迭代的干净列表。根据您对 lexiconContent 所做的操作,请考虑使用 lexiconContent.addAll(linesList)。它将每个列表元素添加到 lexiconContent,而不是添加列表本身;但我认为这就是你所要求的。
  • 如果你确实想要列表列表,你会想要使用复制构造函数,或者Collections.copy() api

标签: java list reference copy deep-copy


【解决方案1】:

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

你可以通过在循环中每次创建一个新的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))); 
}

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

【讨论】:

  • 我做到了!如您所见,我是新来的。一直在阅读,从未质疑过(:
  • @Daniello。你会逐渐熟悉整个 SO 的东西。当然,阅读 SO 上的答案会让您感觉良好。享受编码。 :)
【解决方案2】:

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

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); 
}

【讨论】:

    猜你喜欢
    • 2011-01-10
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 2019-12-04
    • 1970-01-01
    • 1970-01-01
    • 2020-02-07
    • 1970-01-01
    相关资源
    最近更新 更多