使用hashmap将所有子字符串作为键及其出现作为值

时间:2017-06-12 18:18:51

标签: java string hashmap

问题:在给定字符串的情况下,我希望使用length = k获取Hash Map的所有子字符串。

所以我声明了public static function getHistogram返回Map<String,Integer>并且我正在尝试使用HashMap获取该给定字符串的所有子字符串(作为键),以及每个子字符串已经出现在字符串中,我想增加其键中的值(将是计数器)。

这是我到目前为止所做的: Currenet输出:输出不如预期。

  import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Iterator;
import java.util.Set;

public class Main2{

    public static void main(String[] args) throws InvalidValueException{
        // Get a set of the entries
          Set set = Main2.getHistogram("ababaca", 5).entrySet();

          // Get an iterator
          Iterator i = set.iterator();

          // Display elements
          while(i.hasNext()) {
             Map.Entry me = (Map.Entry)i.next();
             System.out.print(me.getKey() + ": ");
             System.out.println(me.getValue());
          }
          System.out.println();
    }

    public static Map<String,Integer> getHistogram(String str, int k)
        throws InvalidValueException
    {
        int i,j;
        String tempStr;

        Map<String, Integer> hmap = new HashMap<String, Integer>();
        for(i = 0; i < str.length(); i++)
          {
            for(j=i; j < str.length(); j++){
                tempStr = str.substring(i, j);
                int count = hmap.containsKey(tempStr) ? hmap.get(tempStr) : 0;
                hmap.put(tempStr, count + 1);
            }

          }
        return hmap;    
    }
}

编辑:必须使用count + 1而不是count ++,但仍然没有完全修复。

输出:

: 7
a: 3
ab: 2
aba: 2
b: 2
bab: 1
ac: 1
c: 1
bac: 1
abac: 1
abab: 1
baba: 1
babac: 1
ababa: 1
ababac: 1
ba: 2

2 个答案:

答案 0 :(得分:2)

public class Substr {
    public static void main(String[] args) {
        System.out.println(getHistogram("ababaca", 5));
        System.out.println(getHistogram("ababaca", 4));
        System.out.println(getHistogram("ababaca", 3));
        System.out.println(getHistogram("ababaca", 2));
        System.out.println(getHistogram("ababaca", 1));
    }

    public static Map<String, Integer> getHistogram(String str, int k) {
        Map<String, Integer> hmap = new HashMap<>();
        for (int start = 0; start < str.length() - k + 1; start++) {
            String substring = str.substring(start, start + k);
            int count = hmap.containsKey(substring) ? hmap.get(substring) : 0;
            hmap.put(substring, count + 1);
        }
        return hmap;
    }    
}

这似乎产生了正确的结果。

如果k已修复,则您不需要两个循环,只需一个循环。它只是贯穿可能的子串的开始索引。然后我们采用子字符串并按照您最初的建议计算子字符串的数量。

答案 1 :(得分:1)

使用Java 8,您可以直接的方式执行此操作:

public static Map<String, Long> getHistogram(String string, int k) {
    return 
        k > string.length() ? Collections.emptyMap() :
        k == string.length() ? Collections.singletonMap(string, 1L) :
            IntStream.range(0, string.length() - k + 1)
                .mapToObj(i -> string.substring(i, i + k))
                .collect(Collectors.groupingBy(
                    Function.identity(),
                    Collectors.counting()));
}

首先检查k是否大于给定string的长度。如果k更大,则返回空地图(您也可以抛出IllegalArgumentException)。

然后,它会检查k是否等于给定string的长度,在这种情况下,会返回包含string1L的单例地图。< / p>

最后,如果k < string.length(),我们会创建一系列整数,从0(包括)到string.length() - k + 1(不包括)。然后,这些整数中的每一个都转换为一个子串,该子串从i的{​​{1}}位置开始,始终string个字符。 (这与您的实现不同,在第一次迭代中,您采用k个字符,第二次采用0等。如果我正确理解了您的问题,则您必须始终使用1个字符,直至到达k的结尾。

然后,所有这些子串通过string收集器收集到Map,该收集器需要一个函数将流的每个元素(这些是你的情况下的子串)映射到键的地图。因为我们希望实际的子串是地图的键,所以我使用了身份功能。 Collectors.groupingBy只是将每个子字符串的计数作为值。

如果您希望子字符串以Collectors.counting的相同顺序显示,则可以使用接受地图供应商的string版本,并告诉它使用Collectors.grouping 1}},保留插入顺序:

LinkedHashMap