字符串计算的优雅解决方案?

时间:2014-03-24 16:28:32

标签: java

我遇到的问题是我经常看到的一个例子。我有一系列字符串(每行一个字符串,比方说)作为输入,我需要做的就是返回每个字符串出现的次数。在不使用特里结构或其他字符串特定结构的情况下,解决此问题的最优雅方法是什么?我过去使用的解决方案是使用哈希表式的自定义(String,整数)对象集合来实现Comparable以跟踪每个字符串出现的次数,但这种方法看起来很笨重有几个原因:

1)此方法需要创建一个与String' s.compareTo()相同的功能。

2)我得到的印象是我误用了TreeSet,这是我的选择。更新给定字符串的计数器需要检查对象是否在集合中,删除对象,更新对象,然后重新插入。这似乎不对。

有没有更聪明的方法来解决这个问题?也许有一个更好的Collections接口我可以用来解决这个问题?

感谢。

4 个答案:

答案 0 :(得分:1)

一个可能性可以是:

public class Counter {
    public int count = 1;
}

public void count(String[] values) {

    Map<String, Counter> stringMap = new HashMap<String, Counter>();

    for (String value : values) {
        Counter count = stringMap.get(value);
        if (count != null) {
            count.count++;
        } else {
            stringMap.put(value, new Counter());
        }
    }
}

这样你仍然需要保留一张地图,但至少你不需要在每次匹配一个新字符串时重新生成该条目,你可以访问Counter类,它是整数的包装并增加值为1,优化对数组的访问

答案 1 :(得分:0)

TreeMap对于这个问题要好得多,或者更好的是,番石榴Multiset

要使用TreeMap,您可以使用类似

的内容
Map<String, Integer> map = new TreeMap<>();
for (String word : words) {
   Integer count = map.get(word);
   if (count == null) {
     map.put(word, 1);
   } else {
     map.put(word, count + 1);
   }
}

// print out each word and each count:
for (Map.Entry<String, Integer> entry : map.entrySet()) {
  System.out.printf("Word: %s Count: %d%n", entry.getKey(), entry.getValue());
}
Integer theCount = map.get("the");
if (theCount == null) {
  theCount = 0;
}
System.out.println(theCount); // number of times "the" appeared, or null

Multiset会比这简单得多;你刚才写的

Multiset<String> multiset = TreeMultiset.create();
for (String word : words) { 
  multiset.add(word);
}
for (Multiset.Entry<String> entry : multiset.entrySet()) {
  System.out.printf("Word: %s Count: %d%n", entry.getElement(), entry.getCount());
}
System.out.println(multiset.count("the")); // number of times "the" appeared

答案 2 :(得分:0)

您可以使用哈希图(无需“创建类似的功能”):

Map<String,Integer> count(String[] strings)
{
    Map<String,Integer> map = new HashMap<String,Integer>();
    for (String key : strings)
    {
        Integer value = map.get(key);
        if (value == null)
            map.put(key,1);
        else
            map.put(key,value+1);
    }
    return map;
}

以下是如何使用此方法打印(例如)输入的字符串数:

Map<String,Integer> map = count(input);
for (String key : map.keySet())
    System.out.println(key+" "+map.get(key));

答案 3 :(得分:0)

您可以使用Apache Commons Collection中的Bag数据结构,例如HashBag

A Bag完全符合您的需求:它会跟踪元素添加到集合中的频率。

HashBag<String> bag = new HashBag<>();
bag.add("foo");
bag.add("foo");
bag.getCount("foo"); // 2