【问题标题】:How can I use a string array as key in hash map?如何使用字符串数组作为哈希映射中的键?
【发布时间】:2015-01-23 19:20:13
【问题描述】:

我已经从 .txt 中创建了一个字符串数组,现在想创建一个以该字符串为键的 HashMap。但我不想将字符串作为一个值的一个键,我希望将每个信息作为 HashMap 的一个新键。

private static String[] readAndConvertInputFile() {
String str = StdIn.readAll();
String conv = str.replaceAll("\'s", "").replaceAll("[;,?.:*/\\-_()\"\'\n]", " ").replaceAll(" {2,}", " ").toLowerCase();
return conv.split(" ");  }

所以字符串中的信息就像(“word”、“thing”、“etc.”、“pp.”、“thing”)。

我的值应该是单词在文本中出现的频率。因此,例如 key: "word" value: 1, key: "thing" value: 2 等等......我一无所知,如果有人能帮助我,我将不胜感激,至少用钥匙。 :)

【问题讨论】:

  • 您在寻找MultiMap吗?
  • @StackFlowed 可能想在那里扔一个右括号;)
  • 请提供一个示例,说明您希望在地图中映射到什么。如果您想对每个单词进行计数,请按此指定。
  • 您是否尝试过循环遍历数组元素,并为您看到的每个单词增加映射值?它没有工作吗?出了什么问题?

标签: java arrays string hashmap


【解决方案1】:

您可以创建一个Map,同时在每个array 索引处使用String 值作为键,并使用Integer 作为值来跟踪单词出现的次数。

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

那么当你想增加的时候,你可以检查Map是否已经包含了key,如果有,就增加1,否则,设置为1。

if (occurences.containsKey(word)) {
    occurences.put(word, occurences.get(word) + 1);
} else {
    occurences.put(word, 1);
}

因此,当您循环遍历字符串数组时,将 String 转换为小写(如果您想忽略单词出现的大小写),并使用上面的 if 语句递增映射。

for (String word : words) {
    word = word.toLowerCase(); // remove if you want case sensitivity
    if (occurences.containsKey(word)) {
        occurences.put(word, occurences.get(word) + 1);
    } else {
        occurences.put(word, 1);
    }
}

一个完整的例子如下所示。我在使用地图中的键时将单词转换为小写以忽略大小写,如果要保留大小写,请删除我将其转换为小写的行。

public static void main(String[] args) {

    String s = "This this the has dog cat fish the cat horse";
    String[] words = s.split(" ");
    Map<String, Integer> occurences = new HashMap<String, Integer>();

    for (String word : words) {
        word = word.toLowerCase(); // remove if you want case sensitivity
        if (occurences.containsKey(word)) {
            occurences.put(word, occurences.get(word) + 1);
        } else {
            occurences.put(word, 1);
        }
    }

    for(Entry<String,Integer> en : occurences.entrySet()){
        System.out.println("Word \"" + en.getKey() + "\" appeared " + en.getValue() + " times.");
    }

}

这会给我输出:

Word "cat" appeared 2 times.
Word "fish" appeared 1 times.
Word "horse" appeared 1 times.
Word "the" appeared 2 times.
Word "dog" appeared 1 times.
Word "this" appeared 2 times.
Word "has" appeared 1 times.

【讨论】:

    【解决方案2】:

    是的,您可以使用数组(无论元素类型如何)作为HashMap 键。

    不,不应该这样做。该行为不太可能是您想要的(通常)。

    在您的特定情况下,我不明白您为什么甚至建议首先使用数组作为键。您似乎希望从您的数组元素中抽取Strings 作为键。

    你可以像这样构造一个词频表:

    Map<String, Integer> computeFrequencies(String[] words) {
        Map<String, Integer> frequencies = new HashMap<String, Integer>();
    
        for (String word: words) {
            Integer wordFrequency = frequencies.get(word);
    
            frequencies.put(word,
                    (wordFrequency == null) ? 1 : (wordFrequency + 1));
        }
    
        return frequencies;
    }
    

    【讨论】:

    • 如果你真的很棘手,因为我们使用的是三元运算符,你可以在 for 循环中使用frequencies.put(word, (frequencies.containsKey(word)) ? frequencies.get(word) + 1 : 1);。当然,这会影响可读性。
    • @Compass,是的,您可以,但是您将在地图中进行三次查找,而不是两次查找每个单词的第二次和后续出现(containsKey()、get() 各一次)和put())。作为一般规则,如果您要跟进 get(),containsKey() 是浪费。
    • 除非,也就是说,您必须担心键实际上被映射到null。
    • 顺便说一句,诡计不是目标。我发现这个特定的代码比它的 if / else 类似代码更清晰。
    • 我知道。 :P 我只是喜欢找到真正让 Java 看起来很奇怪的方法。
    【解决方案3】:

    在 java 8 中使用流

    String[] array=new String[]{"a","b","c","a"};
    Map<String,Integer> map1=Arrays.stream(array).collect(Collectors.toMap(x->x,x->1,(key,value)->value+1));
    

    【讨论】:

      猜你喜欢
      • 2015-03-16
      • 2013-11-20
      • 1970-01-01
      • 2012-10-03
      • 2015-12-12
      • 1970-01-01
      • 1970-01-01
      • 2020-05-24
      • 1970-01-01
      相关资源
      最近更新 更多