如何使用 Map 按字符串中出现的次数对字符进行排序?

How to sort a character by number of occurrences in a String using a Map?

我编写了代码来计算给定字符串中每个字符的频率并显示它:

Map<Character, Integer> occurrences = new HashMap<>();
char[] chars = str2.toCharArray();
for (char character : chars) {
    Integer integer = occurrences.get(character);
    occurrences.put(character, integer);
    if (integer == null) {
        occurrences.put(character, 1);
    } else {
        occurrences.put(character, integer + 1);
    }
}
System.out.println(occurrences);

现在我想修改我的代码,让它显示按频率排序的字符。从出现频率最高的字符开始,然后是出现频率第二高的字符,然后是出现频率第三的字符,依此类推。

例如字符串 Java 应按以下顺序显示为字符频率:a=2, j=1, v=1.

如果您使用 Java 的 TreeMap Map 实现,它将保持您的 values 排序通过 .

还有一个构造函数,如果您需要自己的排序方式,您可以在其中传递 Comparator 的自定义实现。

考虑使用 TreeMap ( https://docs.oracle.com/javase/7/docs/api/java/util/TreeMap.html )

TreeMap is a map implementation that keeps its entries sorted according to the natural ordering of its keys.

您可以参考以下代码参考。

import java.util.Map;
import java.util.TreeMap; 

class Test { 
    static void characterCount(String inputString) 
    { 
        TreeMap<Character, Integer> charCountMap = new TreeMap<Character, Integer>(); 
        char[] strArray = inputString.toCharArray(); 
        for (char c : strArray) { 
            if (charCountMap.containsKey(c)) { 
                charCountMap.put(c, charCountMap.get(c) + 1); 
            } 
            else { 
                charCountMap.put(c, 1); 
            } 
        } 
        for (Map.Entry entry : charCountMap.entrySet()) { 
            System.out.println(entry.getKey() + "=" + entry.getValue()); 
        } 
    } 

    public static void main(String[] args) 
    { 
        String str = "welcometoWhosebug"; 
        characterCount(str); 
    } 
} 

输出 :

a=1
c=2
e=3
f=1
k=1
l=2
m=1
o=4
r=1
s=1
t=2
v=1
w=2

像这样尝试。

String str = "To be or not to be, that is the question";
  • 根据字符和计数流式传输字符和组。
  • 然后重新流式传输条目集以按
  • 排序
  • 指定 LinkedHashMap 以保留排序顺序。

条目首先按值(计数)排序。如果计数等于它们,则按键排序。

Map<Character, Long> map = str.chars()
        .mapToObj(c -> Character.valueOf((char) c))
        .collect(Collectors
                .groupingBy(c -> c, Collectors.counting()))
        .entrySet().stream()
        .sorted(Entry.<Character, Long>comparingByValue()
                .reversed().thenComparing(Entry.comparingByKey()))
        .collect(Collectors.toMap(Entry::getKey,
                Entry::getValue, (a, b) -> a,
                LinkedHashMap::new));

map.entrySet().forEach(System.out::println);

版画

 =9
t=6
o=5
e=4
b=2
h=2
i=2
n=2
s=2
,=1
T=1
a=1
q=1
r=1
u=1

您可以收集两张地图:第一张汇总数量的地图,然后对其进行排序并收集第二张排序后的地图。在这种情况下,如果数量相等,则使用遇到顺序

String str = "JavaProgrammingLanguage";

Map<Character, Integer> occurrences = str.codePoints()
        // Stream<Character>
        .mapToObj(ch -> (char) ch)
        // collect to a map in insertion
        // order, summing up the quantities
        .collect(Collectors.toMap(
                // key - lowercase character
                Character::toLowerCase,
                // value - quantity '1'
                ch -> 1,
                // summing quantities
                Integer::sum,
                // insertion order
                LinkedHashMap::new))
        // Stream<Map.Entry<Character,Integer>>
        .entrySet().stream()
        // sort by quantity in reverse order
        .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
        // collect into a sorted map
        .collect(LinkedHashMap::new,
                (map, entry) -> map.put(entry.getKey(), entry.getValue()),
                HashMap::putAll);

// output
System.out.println(occurrences);
// {a=5, g=4, r=2, m=2, n=2, j=1, v=1, p=1, o=1, i=1, l=1, u=1, e=1}

另请参阅:The intersection of all combinations of n sets