Daniel
Daniel

Reputation: 305

Java: deepcopy list entry without instancing a new list

I've got a little problem while doing my programming task. I want to read some lines from a file (no problem so far) and tokenize it. Every line has about 4 tokens and each of them should find a place in a list. In the end, every line should be in a list too.

A little example to clarify this:

File Content:

foo boo bar
bii buu baa

output:

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

And heres the code I'm dealing with

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

I guess there's a problem with the references, because the first iteration works well! But in the second iteration, it copies the actual second content also to the first (0) list position and so on.

Finally I got something like [[], [], [], []]

Upvotes: 3

Views: 420

Answers (2)

Vishal K
Vishal K

Reputation: 13066

In your code..Instead of creating new ArrayList for each iteration in loop: for(String line:lines) You are just adding the words (in nested loop) in the old object of ArrayList that you had used right from the first iteration of outer loop and storing that same reference value at all subsequent index of lexiconContent ArrayList.Also at the end of each iteration of outer loop you are clearing the linesList .So Finally you are remained with N number of entries in lexiconContent...Where the Element at each index of lexiconContent is nothing but the reference value of the single object of ArrayList(lineList) which is 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); 
}

Upvotes: 0

Rohit Jain
Rohit Jain

Reputation: 213321

The problem is that, you have created only one list, and adding a reference to that list to your outer list, by modifying it on each iteration. So, the final modification done to that list will be reflected for all the references.

You can solve this problem by creating a new linesList each time in the loop: -

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

And yes, you can also simplify your for loop to: -

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

This way, you don't have to iterate over your array, and add individual elements to your List. In fact, you don't need an intermediate list at all.

Upvotes: 3

Related Questions