4

通过 docjar for String,我碰巧看到了以下代码:

public static final Comparator<String> CASE_INSENSITIVE_ORDER
                                         = new CaseInsensitiveComparator();

private static class CaseInsensitiveComparator
                       implements Comparator<String>, java.io.Serializable {
    // use serialVersionUID from JDK 1.2.2 for interoperability
    private static final long serialVersionUID = 8575799808933029326L;

    public int compare(String s1, String s2) {
        // ...
    }
}

我的问题是,为什么我们不能只实现Comparator, likeComparable并使用私有方法而不是嵌套类?

另外在旁注中,为什么没有Comparator类似于compareToin的单个参数的方法Comparable

4

6 回答 6

6

因为 aString 不是a Comparator。当然,它们确实是Comparable,但它们本身并不是“比较函数” 1String :拥有implement是没有意义的Comparator

另一方面,CaseInsensitiveComparator 一个特定的比较函数,只与字符串有关。因此,它被声明为static嵌套类。


1Comparator

于 2013-07-09T03:14:30.170 回答
2

我的问题是为什么我们不能只实现比较器,就像可比较并使用私有函数而不是内部类?

好吧(几乎)接口的全部意义在于Comparator接口的实现是与被比较对象的类分开的类。

理论上你可以按照你的建议去做,但最终结果是违反直觉的

public class MyKey implements Comparator<MyKey> {
    private String field;

    public boolean compare(MyKey m1, MyKey m2) {
        // We must ignore this.field!  We are comparing m1 and m2 ...
        return m1.field.compareTo(m2.field);
    }
}

MyKey[] keys = ...
Arrays.sort(keys, new MyKey());  // Note we have to pass an instance
                                 // to provide the Comparator.

除了有点违反直觉之外,您的想法在MyKey只能以这种方式“提供”一个比较器的意义上受到限制。

坦率地说,如果您要这样做,那么具有实施更有意义MyKeyComparable<MyKey>


假设他们已经String按照您提出的方式实施了。那么这...

   String[] strings = new String[]{"a", "c", "B"};
   Arrays.sort(strings);

... 表示区分大小写,但是 ...

   String[] strings = new String[]{"a", "c", "B"};
   Arrays.sort(strings, "weasel");

... 意味着排序不区分大小写。这真的让你觉得这是个好主意吗? 真的吗?

于 2013-07-09T03:26:53.977 回答
1

您只能实现一个相同类型的接口。String 已经实现了 Comparable 用于字典比较:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence
{

但它需要更多的compareTo方法(例如:执行不区分大小写的比较)。以下会给你编译器错误:

public final class String
    implements java.io.Serializable, Comparable<String>, Comparable<String>, CharSequence
{

因此,这可能是它具有额外比较器的原因之一。

比较器的思想是提供两个项目之间的比较服务的对象,而不是一个可以与另一个进行比较的合同(可比较接口)

在 String 上实现 Comparator 将编译,但这在语义上是错误的

public final class String
    implements java.io.Serializable, Comparable<String>, Comparator<String>, CharSequence
{
于 2013-07-09T03:13:19.987 回答
0

让它成为一个类而不是一个函数允许我们多态地将不同的比较策略应用于集合(或可能执行比较的其他类)。这样,使用比较器的方法不需要知道它是区分大小写的比较器还是不区分大小写的比较器或其他东西;它只是执行比较。然而,如果这是一个函数,那么这种多态性将不适用。执行比较的方法要么必须使用“the”比较方法,要么必须知道正在执行哪种比较,以便选择正确的方法。

拥有两个参数而不是将第一个参数绑定到一个特定的字符串允许我们在任意数量的字符串上使用相同的比较器。否则,在处理大型集合时,我们必须跟踪很多比较器。它还允许将此比较器与左侧或右侧(或两者)的子类一起使用;只有一个参数就不会有这种灵活性。

于 2013-07-09T03:31:45.553 回答
0

主要原因是为了暴露Comparator对象,比如TreeMapsString可以用作键,或者其他可以使用排序或不同类型的相等性的对象。它不能是static方法,因为Comparator接口不能指定static方法,并且Comparator必须是实现要在类中使用的接口的对象,例如TreeMap. 我们需要一个单独的不区分大小写的,因为默认比较(由Comparable's 方法实现)已经被区分大小写的比较所采用。

于 2013-07-09T03:34:56.330 回答
0

为什么我们不能只实现比较器,就像可比较并使用私有函数而不是内部类

String 类实现Comparable<String>了接口,用于按字典顺序比较两个字符串,这是比较两个字符串的一种非常常见的方法。

但是,有时您需要以不同的方式比较两个字符串,例如在比较它们时忽略区分大小写。Comparator接口提供了一种以不同方式比较两个对象的方法。在这种情况下,CaseInsensitiveComparator实现提供此功能并在String.compareToIgnoreCase()方法中使用。

于 2013-07-09T03:44:10.967 回答