如何在HashMaps中处理相同的密钥?

时间:2018-05-17 15:32:46

标签: java hashmap

你好士兵们。

显然,哈希图中的键是唯一。但是,我一直在尝试编写一个读取csv文件的代码,然后将键和值放在映射中。但是,有相同的键(每个键在csv文件中是15次)。在这种情况下,它应该使值的总和,并只返回一次键。 怎么做?我现在的代码如下。

BufferedReader br = null;
String line;



    try {
        br = new BufferedReader(new FileReader(filepath)); 

    } catch (FileNotFoundException fnfex) {

        System.out.println(fnfex.getMessage() + "Bestand niet gevonden!");
        System.exit(0);
    }

    //this is where we read lines
    try {
        while((line = br.readLine()) != null) {
            String[] splitter = line.split(cvsSplitBy);

            if(splitter[0] != "Voertuig") {

                alldataMap.put(splitter[0], splitter[8]);

        }


            //MIGHT BE JUNK, DONT KNOW YET
            /*if((splitter[0].toLowerCase()).contains("1")){
                double valuekm = Double.parseDouble(splitter[8]);
                license1 += valuekm;
                System.out.println(license1);
            }
            else {
                System.out.println("not found");
            }*/


        }
        System.out.println(alldataMap);
        TextOutput();
    } catch (IOException ioex) {
        System.out.println(ioex.getMessage() + " Error 1");
    } finally {
        System.exit(0);
    }

所以,如果我有以下信息(在这种情况下,它的第0和第8个字读取csv文件中的每一行)

Apples; 299,9
Bananas; 300,23
Apples; 3912,1
Bananas;342
Bananas;343

它应该返回

Apples;Total
Bananas;Total

5 个答案:

答案 0 :(得分:3)

尝试以下方法:

if( alldataMap.containsKey(splitter[0]) ) { 
  Double sum = alldataMap.remove(splitter[0]) + Double.parseDouble(splitter[8]);
  allDataMap.put(splitter[0], sum );
} else {
  alldataMap.put(splitter[0], Double.valueOf(splitter[8]) );
}

答案 1 :(得分:2)

自Java 8以来,您可以使用putIfAbsentcompute

Map<String, Integer> myMap = new HashMap<>();

//...

String fruitName = /*whatever*/;
int qty = /*whatever*/;

myMap.putIfAbsent(fruitName, 0);
myMap.compute(fruitName, (k, oldQty) -> oldQty + qty);

答案 2 :(得分:1)

您可以使用Map#containsKey()检查现有映射,然后是否有一个使用Map#get()来检索值并添加新值,最后Map#put()来存储总和:

if(map.containsKey(key))
    map.put(key, map.get(key)+value);
else
    map.put(key, value);

有关这些方法的文档,请参阅here

答案 3 :(得分:1)

我会将merge用于地图:

alldataMap.merge(splitter[0], Double.valueOf(splitter[8]), (oldVal, newVal) -> oldVal + newVal);

来自doc

  

如果指定的键尚未与值关联或与null关联,则将其与给定的非空值关联。否则,将相关值替换为给定重映射函数的结果,或者如果结果为null则删除。当组合密钥的多个映射值时,该方法可以是有用的。例如,要创建或附加String msg到值映射:

答案 4 :(得分:1)

我不会在循环中建议它的方式,因为已经完成了,但我建议使用唯一Streams解决方案>行:

Map<String, Double> alldataMap = new HashMap<>();
try {
    alldataMap =
            Files.lines(Paths.get("", filepath))
                    .map(str -> str.split(cvsSplitBy))
                    .filter(splitte -> !splitte[0].equals("Voertuig"))
                    .collect(Collectors.toMap(sp -> sp[0],
                            sp -> Double.parseDouble(sp[8].replaceAll(",", ".")),
                            (i1, i2) -> i1 + i2));
} catch (IOException e) {
    e.printStackTrace();
}

System.out.println(alldataMap); // {Apples=4212.0, Bananas=985.23}

步骤相同:

  • 迭代
  • 拆分cvsSplitBy
  • 删除以Voertuig开头的行(使用.equals()而不是!=
  • 按照3条规则构建地图:
    • 密钥是第一个String
    • 该值为String解析为Double
    • 的第二个.getOrDefault()
    • 如果需要合并:两者兼并

编辑,因为没有人建议使用while ((line = br.readLine()) != null) { String[] splitter = line.split(cvsSplitBy); if (!splitter[0].equals("Voertuig")) { alldataMap.put(splitter[0], alldataMap.getOrDefault(splitter[0], 0.0) + Double.parseDouble(splitter[8].replaceAll(",", "."))); } } 我给它

window.location.href

如果tke键已经存在,那么它总和,它的密钥不存在它会将值与0相加