【问题标题】:Comparing letter occurrence with comparator将字母出现与比较器进行比较
【发布时间】:2020-02-10 11:03:02
【问题描述】:

我在对字符串数组 [] 进行排序时遇到问题,根据其中包含最多字母“p”的字符串,即 s1 (apple) 将在 s2 (ape)... 之前

我正在学习如何实现 Comparator 来执行此操作,然后使用 s1.compareTo(s2) 和 lambda。最大的问题是,我不能以某种方式使用流来做到这一点吗?

这就是我在反向字母排序中为字符串数组 COUNTRIES 所做的操作

Comparator<String> reverseAlphabetic = (s1,s2) -> -s1.compareToIgnoreCase(s2);   

Arrays.sort(COUNTRIES,reverseAlphabetic);
System.out.println("\nCountries in reverse alphabetic order");
for (int i=0; i<10;i++)
    System.out.println("\t"+COUNTRIES[i]);

【问题讨论】:

  • 简短的回答是——是的,你可以
  • 切勿在比较器中使用减号。当compareToIgnoreCase 恰好返回Integer.MIN_VALUE 时,尝试翻转符号将溢出并再次以Integer.MIN_VALUE 结束。当您想颠倒顺序时,只需使用s2.compareToIgnoreCase(s1)。或者使用已经存在的比较器:Comparator&lt;String&gt; reverseAlphabetic = String.CASE_INSENSITIVE_ORDER.reversed();

标签: sorting java-8 java-stream comparator


【解决方案1】:

Y̶o̶u̶̶c̶a̶n̶̶d̶o̶̶s̶o̶m̶e̶t̶h̶i̶n̶g̶̶l̶i̶k̶e̶̶t̶h̶i̶s̶̶:̶

Comparator<String> comparator = (str1, str2) ->
        ((str1.length() - str1.replaceAll("p", "").length()) -
         (str2.length() - str2.replaceAll("p", "").length()));
List<String> list = Arrays.asList("ape", "apple", "appple");
list.sort(comparator);

实际上,我的解决方案存在根本性错误。 @Holger 在我删除的答案中评论了一个解决方案。

list.sort(Comparator
         .comparingLong((String s) -> s.chars().filter(c -> c == 'p').count()).reversed());

@Holger评论

您的第一个变体也被破坏了,因为a - b - c - da - b - (c - d) 不同。它只是偶然产生了预期的结果;不同的原始顺序会导致不同的结果。另一个不使用减号的理由,例如, Integer.compare(…, …)。一个正确且高效的比较器可以像 Comparator.comparingLong(s -&gt; s.chars().filter(c -&gt; c=='p').count()) 一样简单(或者首先出现最多,Comparator.comparingLong((String s) -&gt; s.chars().filter(c -&gt; c=='p').count()).reversed()),尽管老式的计数循环会更好

【讨论】:

  • 插入括号后,第一个变体是正确的,但必须强调的是,使用减号仅适用于此处,因为我们可以排除字符串长度为负数或出现p ,所以两个计数之间的距离永远不会溢出。一般来说,这不是比较合适的工具。
  • @Holger 感谢您对小事的关注。
猜你喜欢
  • 2011-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-15
  • 1970-01-01
相关资源
最近更新 更多