【问题标题】:Sort list of strings by multiple parameters按多个参数对字符串列表进行排序
【发布时间】:2020-05-15 08:50:50
【问题描述】:

我正在考虑如何使用两个参数对 ArrayList 进行排序。首先是字符串中某些字符的出现,然后是自然顺序。代码如下:

  ArrayList<String> words;
    words=getWords(sentence);//return all words from sentence
    words.sort(Comparator.comparing(o -> countChar(c,  o))
                     .thenComparing(Comparator::naturalOrder));

方法getWords(sentence) 返回来自sentence 的单词ArrayList&lt;String&gt;

方法countChar(c,o) 计算字o 中字符c 的数量。

添加.thenComparing(Comparator::naturalOrder)) 时,IDE 显示o 应转换为String,并且无法解析方法thenComparing()

可能是什么问题?

【问题讨论】:

标签: java sorting lambda


【解决方案1】:

您的代码中有两个错误。

  1. 您需要向comparing 提供通用参数
  2. naturalOrder 返回一个比较器;调用它,而不是传递引用

试试:

        words.sort(Comparator.<String, Integer>comparing(o -> countChar(c,  o))
                         .thenComparing(Comparator.naturalOrder()));

【讨论】:

  • 它编译得很好。你能告诉我为什么我们提供Comparator.&lt;&gt; 而不是Comparator&lt;&gt;.。我在泛型方面很差:(
  • 很好的答案!添加了.reversed() 作为出现字符c 的元素应该排在第一位,然后按自然顺序排列:words.sort(Comparator.&lt;String, Integer&gt;comparing(o -&gt; countChar(c, o)).reversed().thenComparing(Comparator.naturalOrder()));
【解决方案2】:

我的解决方案是使用 count(c) 添加一个对象并实现 Comparable。

class StringWithChar implements Comparable<StringWithChar> {
    private String s;
    private char c;
    private long count;
    public StringWithChar(String s, char c) {
         this.s = s;
         this.c = c;
         count = s.chars().filter(ch -> ch == c).count();
     }

     public String getS() {
         return s;
     }

     public void setS(String s) {
         this.s = s;
     }

     public char getC() {
         return c;
     }

     public void setC(char c) {
         this.c = c;
     }

     public long getCount() {
         return count;
     }

     public void setCount(long count) {
         this.count = count;
     }

     @Override
     public int compareTo(StringWithChar s2) {
         int res = Long.compare(this.getCount(), s2.getCount());
         if (res == 0) {
             return this.getS().compareTo(s2.getS());
         }
         return res;
     }
 }

// then you can easier stream 
words.stream().map(s -> new StringWithChar(s, c)).sort().collect(Collectors.toList());

希望对你有帮助!

【讨论】:

【解决方案3】:

我对这种方法唯一担心的是潜在的性能瓶颈,因为它可能会遍历所有元素以按第一个比较器排序,然后再次循环以按第二个比较器排序。
也许尝试创建一个同时进行比较并使用它的比较器?

【讨论】:

  • 列表将按单个组合比较器排序。无需担心列表被遍历两次...
  • 这种方法有效,但我预计使用 Java 8 会使其看起来更好:) words.sort((s1, s2) -&gt; { int charCount; charCount = Integer.compare(countChar(c, s2), countChar(c, s1)); if (charCount != 0) { return charCount; } return s1.compareTo(s2); });
猜你喜欢
  • 2021-06-10
  • 2012-04-03
  • 2015-05-31
  • 2018-04-07
  • 2020-06-02
  • 2021-12-14
  • 2018-07-02
  • 2014-04-15
  • 1970-01-01
相关资源
最近更新 更多