I have the following CSV file and I would like to create a hashmap which the unique key should be the first value of each row and value should be an arraylist
containing the information of each line under the first value of this row. Example CSV as below:
1,0
1,1
1,2
1,3
1,4
2,0
2,1
2,2
4,0
10,0
10,1
10,2
10,3
10,4
10,5
So ideally, I would like the final ArrayList to be something like:
{1=[1,0, 1,1, 1,2, 1,3, 1,4], 2=[2,0, 2,1, 2,2], 4=[4,0], 10=[10,0, 10,1, 10,2, 10,3, 10,4, 10, 5]}
Below is the code I used trying to solve this problem by a while loop
public static void main(String[] args) {
int activityRecord = 1;
String activitiesFile = "scenarios/BrusselsPopulationFromR/BrusselsActivities.csv";
HashMap<Integer, ArrayList<String>> idAndAllActivities = new HashMap<>();
try {
BufferedReader activityReader = new BufferedReader(new FileReader(activitiesFile));
String agentActivity = null;
ArrayList activities = new ArrayList();
while ((agentActivity = activityReader.readLine()) != null){
String activityWithAllInfo = agentActivity;
String[] activitySpilted = agentActivity.split(",");
int activityAgentID = Integer.parseInt(activitySpilted[0]);
if (activityAgentID == activityRecord){
activities.add(activityWithAllInfo);
} else if (activityAgentID != activityRecord){
idAndAllActivities.put(activityRecord, activities);
activityRecord = activityAgentID;
activities.clear();
activities.add(activityWithAllInfo);
}
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(idAndAllActivities);
}
Basically, I try to justify whether activityAgentID == activityRecord
(originally to be 1), and if it's different, I will add the <K,V> to the hashmap and clear the activities
arrayList. However, the output of this program is something like:
{1=[10,0, 10,1, 10,2, 10,3, 10,4, 10,5], 2=[10,0, 10,1, 10,2, 10,3, 10,4, 10,5], 4=[10,0, 10,1, 10,2, 10,3, 10,4, 10,5]}
This is not what I want, and I tried to debug this but I cannot find the reason for this as I am really new to Java... I am wondering if you know how to solve this? Any hints will be much appreciated!
Thanks!
CodePudding user response:
The problem in your code is that you reuse the activities
array. The activities array and the ones assigned in the HashMap
all point to the same reference, so if you update the activities
array, all the entries in the map will be updated as well.
Assuming the file has the keys ordered, you can tweak your code a little like this
HashMap<Integer, ArrayList<String>> idAndAllActivities = new HashMap<>();
try {
BufferedReader activityReader = new BufferedReader(new FileReader(activitiesFile));
String agentActivity = null;
ArrayList<String> activities = new ArrayList<>();
while ((agentActivity = activityReader.readLine()) != null){
String[] activitySpilted = agentActivity.split(",");
int activityAgentID = Integer.parseInt(activitySpilted[0]);
if (activityAgentID == activityRecord){
activities.add(agentActivity);
} else {
idAndAllActivities.put(activityRecord, activities);
activityRecord = activityAgentID;
activities = new ArrayList<>();
activities.add(agentActivity);
}
}
idAndAllActivities.put(activityRecord, activities);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(idAndAllActivities);
Note that you don't need this: String activityWithAllInfo = agentActivity;
because String
is immutable in Java
CodePudding user response:
Assuming you are using Java 8 or higher, the task could be greatly simplified and the code made more readable with the help of Files.lines
and Collectors.groupingBy
:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Example {
public static void main(String[] args) {
String activitiesFile = "scenarios/BrusselsPopulationFromR/BrusselsActivities.csv";
Map<Integer,List<String>> idAndAllActivities = null;
try (Stream<String> content = Files.lines(Paths.get(activitiesFile))) {
idAndAllActivities = content.collect(Collectors.groupingBy(row -> Integer.parseInt(row.split(",")[0])));
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(idAndAllActivities);
}
}
CodePudding user response:
You could do it in another way. A way that does not break if the order of the CSV file changes as follows:
1,0
1,1
2,0
1,2
10,0
10,1
10,2
1,3
1,4
2,1
2,2
4,0
10,3
10,4
10,5
With this CSV your code will fail because you are relying on the CSV file to have all 1
activity records together. In order to cope with this, try the following (notice that you are no longer relying on activityRecord
):
public static void main(String[] args) {
String activitiesFile = "scenarios/BrusselsPopulationFromR/BrusselsActivities.csv";
HashMap<Integer, ArrayList<String>> idAndAllActivities = new HashMap<>();
try {
BufferedReader activityReader = new BufferedReader(new FileReader(activitiesFile));
String agentActivity = null;
while ((agentActivity = activityReader.readLine()) != null){
String activityWithAllInfo = agentActivity;
String[] activitySpilted = agentActivity.split(",");
int activityAgentID = Integer.parseInt(activitySpilted[0]);
if (idAndAllActivities.containsKey(activityAgentID)){
ArrayList existentActivities = idAndAllActivities.get(activityAgentID);
existentActivities.add(activityWithAllInfo);
} else {
ArrayList activities = new ArrayList();
activities.add(activityWithAllInfo);
idAndAllActivities.put(activityAgentID, activities);
}
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(idAndAllActivities);
}