0

I want to make each line read from the csv as a sub_list and add such sub_list to a master_list.

enter image description here

so it would be something like:

[[line 1] [line 2] ....[last line]]

How to make sure the sub_list added in the master_list is not affected by the changes in the original sub_list. I understand it's something to do with shallow vs deep copy. What is the correct way to do it. The reason for doing in this way is because I might use the sublist for other different operations elsewhere. once I need to do so, I need to clear the content inside it as an empty list. Hence I want to maintain the use of the same list for different tasks.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class CSVReader {

    public static void main(String[] args) {

        String csvFile = "E:\\country.csv";
        String line = "";
        String cvsSplitBy = ",";
        List<String> sub = new ArrayList<String>();
        List<List> master = new ArrayList<List>();

        try (BufferedReader br = new BufferedReader(new FileReader(csvFile))) {

            while ((line = br.readLine()) != null) {

                // use comma as separator
                String[] country = line.split(cvsSplitBy);
                sub.add(line);
                master.add(sub);
//              System.out.println(sub);
                sub.remove(0);

//                System.out.println("Country [code= " + country[4] + " , name=" + country[5] + "]");

            }

        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println(master);

    }

}

this prints out empty list "[]".

Jack
  • 1,339
  • 1
  • 12
  • 31
  • 2
    Can you take a step back and first tell us what this code is supposed to be doing? – Tim Biegeleisen Sep 29 '19 at 06:29
  • You can always put `List sub = new ArrayList();` inside the `while` loop and remove the call to `sub.remove(0);` – Anoop R Desai Sep 29 '19 at 06:32
  • please see my update on the question. thanks – Jack Sep 29 '19 at 06:33
  • @ Anoop R Desai your method will certainly works but I every time when looping i have to create a new list. i prefer a strategy like: set sublist = current line -> add sublist to the master_list -> set sublist [] as empty for next time looping. how to do it? – Jack Sep 29 '19 at 06:37
  • Why do you want to make sublist empty at the end? In any case, creating a new sublist every at every iteration does not imply you have many lists in memory - they get garbage collected anyway. – Anoop R Desai Sep 29 '19 at 06:40
  • because I might use sublist for other different operations elsewhere. once I need to do so, I need to clear the content inside it as an empty list. Hence I want to maintain the use of the same list for different tasks. – Jack Sep 29 '19 at 06:42
  • 1
    Each sublist inside the master list needs to be a different list because it has different content. Trying to reuse the same sublist is just causing you problems. – khelwood Sep 29 '19 at 06:47
  • In that case, you can create a clone of sublist inside the loop, add the cloned list to the `master_list` and then empty the sublist. To create a clone, have a look [here](https://stackoverflow.com/a/6536128/1898437). But as @TimBiegeleisen mentioned, you might want to take a step back and review. – Anoop R Desai Sep 29 '19 at 06:47
  • if you don't like working with `List>`, you can use two dimention array `String[][]` – Eugen Sep 29 '19 at 06:48
  • @ Anoop R Desai I think the clone method should be 95% similar to my desired strategy. I tried this: new_sub = sub.clone() but it would work. what is a correct way for using clone() method? – Jack Sep 29 '19 at 07:29

3 Answers3

1

Try move declaration of sub variable onto the while block.

    String csvFile = "E:\\country.csv";
        String line = "";
        String cvsSplitBy = ",";
        List<List> master = new ArrayList<List>();

        try (BufferedReader br = new BufferedReader(new FileReader(csvFile))) {

            while ((line = br.readLine()) != null) {

                // use comma as separator
                String[] country = line.split(cvsSplitBy);
                List<String> sub = new ArrayList<String>();
                sub.add(line);
                master.add(sub);
//              System.out.println(sub);
//              sub.remove(0);

//                System.out.println("Country [code= " + country[4] + " , name=" + country[5] + "]");

            }

        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println(master);
Eugen
  • 877
  • 6
  • 16
  • your method will certainly works but I every time when looping i have to create a new list. i prefer a strategy like: set sublist = current line -> add sublist to the master_list -> set sublist [] as empty for next time looping. how to do it? – Jack Sep 29 '19 at 06:38
1

Two Points:-

1 - Change your master list as below. you should not create generic list (Raw type). If you create list as raw type, You will be able to enter any data type input. It will create issue as there can be multi data type list.

2 - when you enter in while loop, create/assign new reference to sub list and then add it to master.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class CSVReader {

    public static void main(String[] args) {

        String csvFile = "E:\\country.csv";
        String line = "";
        String cvsSplitBy = ",";
        List<String> sub = new ArrayList<String>();
        List<List<String>> master = new ArrayList<>();

        try (BufferedReader br = new BufferedReader(new FileReader(csvFile))) {

            while ((line = br.readLine()) != null) {

                // use comma as separator
                String[] country = line.split(cvsSplitBy);
                sub = new ArrayList<String>();
                sub.add(line);
                master.add(new ArrayList<String>(sub));
//              System.out.println(sub);
                sub.remove(0);

//                System.out.println("Country [code= " + country[4] + " , name=" + country[5] + "]");

            }

        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println(master);

    }

}
SSP
  • 2,650
  • 5
  • 31
  • 49
  • does this method empty the existing sub? is this equal to "set current sub as []" ? – Jack Sep 29 '19 at 06:47
  • what will happen to the old sub? does it override the old sub, which is equal to set old sub as empty list? – Jack Sep 29 '19 at 06:52
  • first old sub will be stored in master. we are using new operator while saving in master so it will create a deep copy of sub while storing in master. then whie loop will empty it. run the code in debug mode you can check it. – SSP Sep 29 '19 at 06:55
  • yes. this partially solve the problem. But please take a look at my original question. I simply want to use and update one single sublist without constantly creating new different lists. I want to make a deep copy of the current sub into the master, then reset it to empty at the end of the while loop for next looping. – Jack Sep 29 '19 at 07:00
0

You can do this

public static List<String[]> getTestData(String fileName) {
    List<String[]> records = new ArrayList<String[]>();
    try {
        String record;
        BufferedReader file = new BufferedReader(new InputStreamReader(new FileInputStream(fileName), "UTF-8"));
        while ((record = file.readLine()) != null) {
            System.out.println(record);
            String fields[] = record.split(",");
            records.add(fields);
        }
        file.close();
        return records;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}
jack
  • 26
  • 3