Count occurrences in string and output sorted result by ocuurence_count desc, name

huangapple go评论66阅读模式
英文:

Count occurrences in string and output sorted result by ocuurence_count desc, name

问题

Here's a more concise solution using Java Stream API to achieve the same result:

String str = "Charlie Jennifer Charlie Bob Charlie Charlie Bob Jennifer Alice Alice";

Arrays.stream(str.split(" "))
        .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
        .entrySet().stream()
        .sorted(Map.Entry.<String, Long>comparingByValue()
                .reversed()
                .thenComparing(Map.Entry.comparingByKey()))
        .forEach(System.out::println);

This solution follows the same logic as your original code but uses Collectors.groupingBy and Collectors.counting() directly within the collect method, which makes the code more concise.

英文:

Given a string:

String str = &quot;Charlie Jennifer Charlie Bob Charlie Charlie Bob Jennifer Alice Alice&quot;;

Need to count name occurrences in the given string and output sorted result by occurrence count (desc), then by name.
Here is my solution:

Arrays.stream(str.split(&quot; &quot;))
        .collect(groupingBy(identity(), counting())).entrySet().stream()
        .sorted(Map.Entry.&lt;String, Long&gt;comparingByValue()
                .reversed()
                .thenComparing(Map.Entry.comparingByKey()))
        .forEach(System.out::println);

My question is: do you know more elegant solution using Java Stream API ?

答案1

得分: 2

按照评论中所述,这里实际上没有太多可以改进的地方。

可能的改进是,你可以将结果收集到TreeMap中,并使用 lambda 表达式按值进行比较,而无需调用 reversed()

Arrays.stream(str.split(" "))
      .collect(groupingBy(w -> w, TreeMap::new, counting()))
      .entrySet().stream()
      .sorted((a, b) -> b.getValue().compareTo(a.getValue()))
      .forEach(System.out::println);

类似地,可以使用 toMap 收集器替代 groupingBycounting

Arrays.stream(str.split(" "))
       .collect(toMap(w -> w, x -> 1, Long::sum, TreeMap::new))
       .entrySet().stream()
       .sorted((a, b) -> b.getValue().compareTo(a.getValue()))
       .forEach(System.out::println);
英文:

As mentioned in the comments, there's not really much to improve here.

Possibly, you could collect the results into a TreeMap and use lambda to compare by values without calling reversed():

Arrays.stream(str.split(&quot; &quot;))
      .collect(groupingBy(w -&gt; w, TreeMap::new, counting()))
      .entrySet().stream()
      .sorted((a, b) -&gt; b.getValue().compareTo(a.getValue()))
      .forEach(System.out::println);

Similarly, toMap collector could be used instead of groupingBy and counting:

 Arrays.stream(str.split(&quot; &quot;))
       .collect(toMap(w -&gt; w, x -&gt; 1, Long::sum, TreeMap::new))
       .entrySet().stream()
       .sorted((a, b) -&gt; b.getValue().compareTo(a.getValue()))
       .forEach(System.out::println);

答案2

得分: 1

可能不使用流会稍微不那么冗长,但是仍然需要先进行分组,然后再进行排序:

Map<String, Long> map = new HashMap<>();
for (String s : str.split(" ")) map.merge(s, 1L, Long::sum);

在这里,我使用了 Map.merge 方法按频率对单词进行分组。现在我们需要从条目中创建一个列表,然后进行排序:

List<Map.Entry<String, Long>> list = new ArrayList<>(map.entrySet());
list.sort(Map.Entry.comparingByValue()
             .reversed()
             .thenComparing(Map.Entry.comparingByKey()));

现在我们有一个按照您的要求排序的 Map.Entry 列表。

如果您需要从这些条目创建一个映射,它应该是一个 LinkedHashMap,以保留插入顺序

Map<String, Long> sortedByValue = new LinkedHashMap<>();
list.forEach(e -> sortedByValue.put(e.getKey(), e.getValue()));
英文:

Maybe not using streams is a little bit less verbose but, still, you need to group first and then sort:

Map&lt;String, Long&gt; map = new HashMap&lt;&gt;();
for (String s : str.split(&quot; &quot;)) map.merge(s, 1L, Long::sum);

Here I'm using the Map.merge method to group words by frequency. Now we need to create a list from the entries and sort it:

List&lt;Map.Entry&lt;String, Long&gt;&gt; list = new ArrayList&lt;&gt;(map.entrySet());
list.sort(Map.Entry.comparingByValue()
             .reversed()
             .thenComparing(Map.Entry.comparingByKey()));

And now we have a list of Map.Entry in list, sorted as per your requirements.

If you need to create a map from these entries, it should be a LinkedHashMap, to preserve insertion order:

Map&lt;String, Long&gt; sortedByValue = new LinkedHashMap&lt;&gt;();
list.forEach(e -&gt; sortedByValue.put(e.getKey(), e.getValue()));

huangapple
  • 本文由 发表于 2020年10月1日 04:40:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/64145418.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定