Home > database >  Adding Maps to a List results in adding the same Map multiple times
Adding Maps to a List results in adding the same Map multiple times

Time:06-20

I am trying to read a table from a csv text file and generate a table (List of Hashmaps) in java.

For which I'm reading each line of text file, constructing a Hashmap<String, String> record out of the line and appending it to a ArrayList at the end of each iteration.

I am expecting a single instance of each line from text file to appear only once in the List, but all getting is the last row from text file appearing n 1 times, n being the last row number.

Here's the code:

public static void main(String[] args) throws IOException {
    
    FileReader filObj = null;
    try {
        filObj = new FileReader(new File(System.getProperty("user.home")   "\\Desktop\\testData.txt"));
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }
    
    BufferedReader br = new BufferedReader(filObj);
    
    List<String> headers = new ArrayList<String>();
    List<HashMap<String, String>> myTable = new ArrayList<HashMap<String, String>>();
    HashMap<String, String> myRecord = new HashMap<String, String>();
    
    String line = null;
    int ext = 0;
    while ((line = br.readLine()) != null) {
        //System.out.println(line);
        if (ext == 0) {
            headers = Arrays.asList(line.split(","));
        } else {
            int index = 0;
            for (String each : line.split(",")) {
                myRecord.put(headers.get(index), each);
                index  ;
            }
            System.out.println("myrecord:"   myRecord);
        }
        myTable.add(myRecord);
        ext  ;
        System.out.println("My Table:"   myTable);
    }
}

the testData.txt file contents are as below

TransactionNumber,TransactionType,Amount,TransactionDate,TransactionRemarks
123456,Credit,4000,07/10/2021,Salary Credited
123333,Debit,7000,05/10/2021,Fuel
123446,Credit,3000,01/10/2021,Refund

and the console output is as below:

My Table:[{}]
myrecord:{TransactionType=Credit, TransactionNumber=123456, Amount=4000, TransactionRemarks=Salary Credited, TransactionDate=07/10/2021}
My Table:[{TransactionType=Credit, TransactionNumber=123456, Amount=4000, TransactionRemarks=Salary Credited, TransactionDate=07/10/2021}, {TransactionType=Credit, TransactionNumber=123456, Amount=4000, TransactionRemarks=Salary Credited, TransactionDate=07/10/2021}]
myrecord:{TransactionType=Debit, TransactionNumber=123333, Amount=7000, TransactionRemarks=Fuel, TransactionDate=05/10/2021}
My Table:[{TransactionType=Debit, TransactionNumber=123333, Amount=7000, TransactionRemarks=Fuel, TransactionDate=05/10/2021}, {TransactionType=Debit, TransactionNumber=123333, Amount=7000, TransactionRemarks=Fuel, TransactionDate=05/10/2021}, {TransactionType=Debit, TransactionNumber=123333, Amount=7000, TransactionRemarks=Fuel, TransactionDate=05/10/2021}]
myrecord:{TransactionType=Credit, TransactionNumber=123446, Amount=3000, TransactionRemarks=Refund, TransactionDate=01/10/2021}
My Table:[{TransactionType=Credit, TransactionNumber=123446, Amount=3000, TransactionRemarks=Refund, TransactionDate=01/10/2021}, {TransactionType=Credit, TransactionNumber=123446, Amount=3000, TransactionRemarks=Refund, TransactionDate=01/10/2021}, {TransactionType=Credit, TransactionNumber=123446, Amount=3000, TransactionRemarks=Refund, TransactionDate=01/10/2021}, {TransactionType=Credit, TransactionNumber=123446, Amount=3000, TransactionRemarks=Refund, TransactionDate=01/10/2021}]

CodePudding user response:

You're adding the same instance of the map to the list at each iteration step. And this map gets added to the list n 1 times because the line myTable.add(myRecord); gets executed after reading the headers (I guess that wasn't your intention).

Instead, you need to move the creation of the map into the while loop, to instantiate a new map for every line of text.

There are few more issues in your code:

Your code might be rewritten like that:

public static void main(String[] args) {
    
    List<Map<String, String>> myTable = new ArrayList<>();
    
    try (var reader = new BufferedReader(new FileReader(System.getProperty("user.home")   "\\Desktop\\testData.txt"))) {
        List<String> headers = new ArrayList<>();
        
        String line = null;
        int ext = 0;

        while ((line = reader.readLine()) != null) {
            //System.out.println(line);
            if (ext == 0) {
                headers = Arrays.asList(line.split(","));
                ext  ;
                continue;
            }
            
            Map<String, String> myRecord = new HashMap<>();

            int index = 0;
            for (String each : line.split(",")) {
                myRecord.put(headers.get(index), each);
                index  ;
            }
            
            myTable.add(myRecord);
            ext  ;

            System.out.println("myrecord:"   myRecord);
            System.out.println("My Table:"   myTable);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

CodePudding user response:

Your structures are wrong: you add the same HashMap to the list myTable over and over.

Instead of a list of hashmaps you probably would need a map of lists:

Map<String, List<String>> mytable = new HashMap<>();

This way you can store multiple values for each header (the header is still the key of the map).

The order of values is still preserved as the order of rows.

When you read in the headers, you can also initialize the map:

if (ext == 0){
    headers = Arrays.asList(line.split(","));
    for (String header : headers) {
    myList.put(header, new List<String>());
}

To add a value you then have to fetch the list according to the header and add a value to its end:

else {
    String[] values = line.split(",");
    for (int index = 0; index < values.length; index  ) {
        myTable.get(headers.get(index)).add(values[index]);
    }
}
  • Related