我正在阅读CSV并将数据保存到对象(为每一行创建一个对象)。 CSV中的行按第一个元素(组号)分组 - 介于2-10行之间的某个行共享一个组号。数据集中有~180个组。为了更容易处理这些数据,我将数据存储到HashMaps中,其中键是组号,与键绑定的值是数据对象的ArrayList。
当我遍历CSV的行时,我将对象添加到HashMap,使用行的组号来指示放置新数据对象的位置。如果对象具有尚未输入CSV的组编号,则会创建一个新密钥(其组编号)和一个仅包含其自身的数据对象的ArrayList。
如果行的组号是HashMap中的一个键,它会将ArrayList绑定到组号,将新数据对象添加到它,并使用put函数重新添加新条目,使用更新的ArrayList(现在还有一个数据条目与共享组号绑定)。
代码示例:
ArrayList<CSVData> csvListNew = new ArrayList<CSVData>();
HashMap<Integer,ArrayList<CSVData>> CSVDataMapNew = new HashMap<Integer,ArrayList<CSVData>>();
while ((line = reader.readLine()) != null && !(line.contains(",,,,,,,,,")))
{
System.out.println(line);
String[] csvDataNew = line.split(",");
String currentGroup = csvDataNew[GroupIndex];
try {
currentGroupNumber = Integer.parseInt(currentGroup.replace("group", "").replace(" ", ""));
} catch (Exception ex) {
currentGroupNumber = previousGroupNumber;
}
String path = csvDataNew[PathIndex];
startLine = Integer.parseInt(csvDataNew[StartLineIndex]);
endLine = Integer.parseInt(csvDataNew[EndLineIndex]);
CSVData data = new CSVData(currentGroupNumber, path, startLine, endLine);
if (CSVDataMapNew.containsKey(currentGroupNumber)) { //if it does contain the current key, add the current object to the ArrayList tied to it.
csvListNew = CSVDataMapNew.get(currentGroupNumber);
csvListNew.add(clone);
CSVDataMapNew.put(currentGroupNumber, csvListNew);
} else { //if it doesnt contain the current key, make new entry
csvListNew.add(clone);
CSVDataMapNew.put(currentGroupNumber, csvListNew);
System.out.println(CSVDataMapNew.size());
System.out.println(CSVDataMapNew.get(currentGroupNumber).size());
}
csvListNew.clear(); //to make sure no excess objects are entered into the map.
previousGroupNumber = currentGroupNumber;
}
有适当的try-catches等,CSVDataTable在它自己的类中声明,静态引用。
问题是,当我在每一步添加print语句时,它就像每个循环结束时擦除HashMap中的每个ArrayList一样。因此,一旦CSV完成迭代,它就有每个键值,但与每个键绑定的ArrayLists都是空的。 (后来通过循环HashMap证明了这一点。)
如何解决这个问题,所以当我在ArrayList中输入一个值并重新放入&#39;关键并将更新后的ArrayList放入Map中,它会保留其数据吗?
答案 0 :(得分:2)
因此,一旦CSV完成迭代,它就会有每个键 值,但绑定到每个键的ArrayLists都是空的。 (
这个
ArrayList<CSVData> csvListNew = new ArrayList<CSVData>();
应调用并将其与地图的每个键相关联
但是,您使用ArrayList
的单个实例作为地图中每个键的值。
在您的方法结束时,您可以:
csvListNew.clear();
因此,您的地图所有值均为空ArrayList
,因为所有值均为ArrayList
。
要解决您的问题,如果地图中的密钥不存在,您应该创建一个新的ArrayList并将其与此密钥相关联:
ArrayList<CSVData> csvListNew = CSVDataMapNew.get(currentGroupNumber);
if (csvListNew == null)
csvListNew = new ArrayList<CSVData>();
CSVDataMapNew.put(csvListNew);
}
然后重用csvListNew
变量来添加元素:
csvListNew.add(clone);
它简化了具有不良重复的实际代码。
答案 1 :(得分:1)
您始终在python
中将相同的ArrayList
实例作为值。这是在循环之前创建的HashMap
实例,由ArrayList
变量引用。
这意味着当您致电csvListNew
时,您会清除csvListNew.clear()
的所有ArrayList
。
每次要在HashMap
中添加新条目时,都可以通过创建新ArrayList
来解决此问题:
HashMap
此外,请删除 if (CSVDataMapNew.containsKey(currentGroupNumber)) {
csvListNew = CSVDataMapNew.get(currentGroupNumber);
csvListNew.add(clone);
} else {
csvListNew = new ArrayList<>(); // that's the main required fix
csvListNew.add(clone);
CSVDataMapNew.put(currentGroupNumber, csvListNew);
System.out.println(CSVDataMapNew.size());
System.out.println(CSVDataMapNew.get(currentGroupNumber).size());
}
来电。
答案 2 :(得分:1)
当您从hashMap获取列表时,您将获得对该列表的引用。之后使用此列表执行的所有操作都将影响地图中的列表。这意味着两件事:
这应该解决它(也是一些调整后的代码风格):
Map<Integer,List<CSVData>> CSVDataMapNew = new HashMap<>();
while ((line = reader.readLine()) != null && !(line.contains(",,,,,,,,,")))
{
System.out.println(line);
String[] csvDataNew = line.split(",");
String currentGroup = csvDataNew[GroupIndex];
try {
currentGroupNumber = Integer.parseInt(currentGroup.replace("group", "").replace(" ", ""));
} catch (Exception ex) {
currentGroupNumber = previousGroupNumber;
}
String path = csvDataNew[PathIndex];
startLine = Integer.parseInt(csvDataNew[StartLineIndex]);
endLine = Integer.parseInt(csvDataNew[EndLineIndex]);
CSVData data = new CSVData(currentGroupNumber, path, startLine, endLine);
if (CSVDataMapNew.containsKey(currentGroupNumber)) {
CSVDataMapNew.get(currentGroupNumber).add(clone);
} else {
ArrayList<CSVData> csvListNew = new ArrayList<CSVData>();
CSVDataMapNew.put(currentGroupNumber, csvListNew);
csvListNew.add(clone);
}
previousGroupNumber = currentGroupNumber;
}