I am trying to read a table from a csv text file and generate a table (List
of Hashmap
s) 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:
You're not closing the stream, always use try with resources to make sure that resources would be properly closed.
Don't throw from the
main()
, it's not a good practice;Write your code against interfaces What does it mean to "program to an interface"?
Since Java 7 we can use diamond and since Java 10
var
to reduce verbosity of 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]);
}
}