【问题标题】:How to correctly initialize a Comparator?如何正确初始化比较器?
【发布时间】:2014-04-03 18:31:18
【问题描述】:

我需要在 MinTester 类中编写一个静态方法来计算“最小”字符串 从使用比较器对象的 ArrayList 集合中:

public static String min(ArrayList<String> list, Comparator<String> comp)

我无法使用 Collections 类来计算最小值。

这是我目前所拥有的。

public class MinTester 
{
    public static String min(ArrayList<String> list, Comparator<String> comp)
    {
        String shortest = list.get(0);

        for(String str : list) {
            if ( comp.compare(str, shortest) < 0) {
                shortest = str;
            }
        }
        return shortest;
    }
}

我没有从该方法中得到任何错误,因此我尝试使用此方法在 Main 中对其进行测试。 尝试传递 comp 时出现此错误:变量 comp 可能尚未初始化

public static void main(String[] args)
{
    // TODO code application logic here

    MinTester s = new MinTester();
    Comparator<String> comp;
    ArrayList<String> list = new ArrayList<>();

    list.add("a");
    list.add("ab");
    list.add("abc");
    list.add("abcd");

    String a = s.min(list,comp);//Error: Variable comp may not have been initialized

    System.out.println(a);
}

这是我遇到问题的地方。

我试试

Comparator<String> comp = new Comparator<>();//Error:Comparator is abstract, cannot be instantiated
Comparator<String> comp = new MinTester();//Error: MinTester cannot be converted to Comparator<String>

谁能告诉我处理这个比较器的正确方法?我不确定我是否只是尝试不正确地初始化它,或者我的 MinTester 类中是否缺少某些内容。

【问题讨论】:

  • 你可以阅读我关于这个的文章(应该很快更新)codeproject.com/Articles/703185/…
  • 您还没有定义“最小”的含义。您在代码中暗示您的意思是“最短”,但我怀疑定义有点复杂,如“最短但在出现平局时,根据字符排序顺序排序(即按字母顺序排列字母)”。一旦你知道了,就实现Comparator&lt;String&gt;

标签: java string initialization comparator


【解决方案1】:

Comparator是一个接口;不同的类可以以不同的方式实现它以执行不同类型的比较。您的方法采用Comparator 的原因是调用者可以选择如何比较字符串。传入一个 Comparator 来进行词法(又名字母)比较,你会得到按词法顺序排列的第一个字符串。传入一个查看字符串长度的Comparator,你会得到最短的字符串。

由于String 类已经实现了Comparable 接口——一种类似于Comparator 的兄弟,它允许一个类定义它自己的比较方法——这里有一个方便的泛型类,它可以让你通过Comparator接口:

public final class ComparableComparator<T extends Comparable<T>> implements Comparator<T> {
    @Override
    public int compare(final T a, final T b) {
        return a.compareTo(b);
    }
}

将其中一个传递给您的方法,它会使用String 类自己的compareTo 方法比较字符串。

编辑:在 Java 8 或更高版本中,Comparator.naturalOrder() 方法为您提供相同的功能,因此您无需编写上面的类。

【讨论】:

    【解决方案2】:

    您应该为此编写一个实现Comparator&lt;String&gt; 的类。使用anonymous class 的快速方法:

    String a = s.min(list, new Comparator<String>() {
        @Override
        public int compare(String s1, String s2) {
            return s1.compareTo(s2);
        }
    });
    

    由于需要根据String长度进行比较,只需在compare方法中更改比较逻辑即可:

    String a = s.min(list, new Comparator<String>() {
        @Override
        public int compare(String s1, String s2) {
            return (s1.length() > s2.length()) ? 1 : (s1.length() < s2.length()) ? -1 : 0;
        }
    });
    

    如果你碰巧使用 Java 7,那么使用Integer#compare

    String a = s.min(list, new Comparator<String>() {
        @Override
        public int compare(String s1, String s2) {
            return Integer.compare(s1.length(), s2.length());
        }
    });
    

    如果您使用 Java 8,则可以使用 lambda 表达式:

    String a = s.min(list, (s1, s2) -> Integer.compare(s1.length(), s2.length()));
    

    【讨论】:

    • Comparator 是一个接口。它应该“实现”而不是扩展。
    • @LuiggiMendoza 我试过了,我的 a 输出似乎是按字母顺序排列的,而不是比较长度。如果我有“b”和“abc”,a 将 = abc,因为 a 在 b 之前。我会尝试编辑它,但我不确定这个匿名方法如何与我的 MinTester 类中的方法一起使用
    • 然后用比较字符串长度的代码替换 compare 方法的主体。不应超过 1 行。
    • @user3345200 你只需要用这个替换你有String a = s.min(list, comp);的那一行。如果需要按字符串长度进行比较,则更改实现。
    • @LuiggiMendoza: return Integer.compare(s1.length(), s2.length());
    【解决方案3】:

    您不需要使用Comparator,至少不需要,除非您想修改字符串比较的自然顺序。请改用String 类的compareTo() 方法。

    if (str.compareTo(shortest) < 0) {
         shortest = str;
    }
    

    如果您想修改自然排序,您可以创建一个实现Comparator 接口的类,然后将此类的一个实例传递给compare() 方法。您还可以为比较定义自己的逻辑。

    public class StringDescComparator implements Comparator<String> {
        @Override
        public int compare(String str1, String str2) {
            // return str1.compareTo(str2);      // For natural ordering
            return -1 * str1.compareTo(str2);    // For reversed ordering
        }
    }
    

    然后您可以使用上述类的实例按降序进行比较,这样:"b" &lt; "a"

    Comparator comp = new StringDescComparator();
    

    【讨论】:

    • 如果我正确理解了这个问题,使用Comparator 是一项要求。 (这听起来像是学校作业。)
    • 哦!然后您可以在我的答案中使用Comparator 类,返回语句为return str1.compareTo(str2); 以保持自然顺序
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-01
    • 2010-11-11
    • 2010-11-12
    • 2021-09-07
    相关资源
    最近更新 更多