fundamentals\java\java8新特性-DefaultMethod(译自oracle官网)

Default Methods

目录

默认方法:Default Methods

标准接口与问题的提出:industry-standard interfaces of computer-controlled cars

标准接口的扩展-默认方法:Extending Interfaces That Contain Default Methods

标准接口的扩展-静态方法:Static Methods

栗举JAVA8系统库新增静态方法的综合应用:Integrating Default Methods into Existing Libraries


industry-standard interfaces of computer-controlled cars

public interface OperateCar {

 

   // constant declarations, if any

   // method signatures

   // An enum with values RIGHT, LEFT

   int turn(Direction direction,

            double radius,

            double startSpeed,

            double endSpeed);

   int changeLanes(Direction direction,

                   double startSpeed,

                   double endSpeed);

   int signalTurn(Direction direction,

                  boolean signalOn);

   int getRadarFront(double distanceToCar,

                     double speedOfCar);

   int getRadarRear(double distanceToCar,

                    double speedOfCar);

         ......

   // more method signatures

}

 

 

The section Interfaces describes an example that involves manufacturers of computer-controlled cars who publish industry-standard interfaces that describe which methods can be invoked to operate their cars. What if those computer-controlled car manufacturers add new functionality, such as flight, to their cars? These manufacturers would need to specify new methods to enable other companies (such as electronic guidance instrument manufacturers) to adapt their software to flying cars. Where would these car manufacturers declare these new flight-related methods? If they add them to their original interfaces, then programmers who have implemented those interfaces would have to rewrite their implementations. If they add them as static methods, then programmers would regard them as utility methods, not as essential, core methods.

Interface章节描述了一个例子,它涉及到计算机控制的汽车制造商,他们发布行业标准接口,描述可以调用哪些方法来操作他们的汽车。

如果那些电脑控制的汽车制造商给他们的汽车增加了新的功能,比如飞行,那该怎么办?这些制造商需要指定新的方法,使其他公司(如电子制导仪器制造商)能够使他们的软件适应飞行汽车。这些汽车制造商将在哪里定义这些新的飞行相关方法?

如果他们把它们加到原来的地方,那么,实现这些接口的程序员将不得不重写他们的实现。如果他们把它们作为静态方法添加,那么程序员就会将它们视为公用方法,而不是核心成员方法。

 

Default methods enable you to add new functionality to the interfaces of your libraries and ensure binary compatibility with code written for older versions of those interfaces

默认方法使您能够向库函数接口添加新的功能接口,并确保与为旧版本的接口编写的代码的兼容性。

// interface, TimeClient:

public interface TimeClient {

    /***

     * 设置时间

     */

    void setTime(int hour, int minute, int second);

    /***

     * 设置日期

     */

    void setDate(int day, int month, int year);

    /***

     * 设置日期时间

     */

    void setDateAndTime(int day, int month, int year,

                               int hour, int minute, int second);

    /***

     * 获取日期时间

     */

    LocalDateTime getLocalDateTime();

}

 

//  implements of TimeClient:

public class SimpleTimeClient implements TimeClient {

   

    private LocalDateTime dateAndTime;

   

    public SimpleTimeClient() {

        dateAndTime = LocalDateTime.now();

    }

   

    public void setTime(int hour, int minute, int second) {

        LocalDate currentDate = LocalDate.from(dateAndTime);

        LocalTime timeToSet = LocalTime.of(hour, minute, second);

        dateAndTime = LocalDateTime.of(currentDate, timeToSet);

    }

   

    public void setDate(int day, int month, int year) {

        LocalDate dateToSet = LocalDate.of(day, month, year);

        LocalTime currentTime = LocalTime.from(dateAndTime);

        dateAndTime = LocalDateTime.of(dateToSet, currentTime);

    }

   

    public void setDateAndTime(int day, int month, int year,

                               int hour, int minute, int second) {

        LocalDate dateToSet = LocalDate.of(day, month, year);

        LocalTime timeToSet = LocalTime.of(hour, minute, second);

        dateAndTime = LocalDateTime.of(dateToSet, timeToSet);

    }

   

    public LocalDateTime getLocalDateTime() {

        return dateAndTime;

    }

   

    public String toString() {

        return dateAndTime.toString();

    }

   

    public static void main(String... args) {

        TimeClient myTimeClient = new SimpleTimeClient();

        System.out.println(myTimeClient.toString());

    }

}

 

// Suppose that you want to add new functionality such as the ability to specify a time zone

// 假设你想添加新功能,比如时区

public interface TimeClient {

    void setTime(int hour, int minute, int second);

    void setDate(int day, int month, int year);

    void setDateAndTime(int day, int month, int year,

        int hour, int minute, int second);

    LocalDateTime getLocalDateTime();

    /***

     * 获取指定时区的日期时间

     */

    ZonedDateTime getZonedDateTime(String zoneString);

}

 

// Following this modification to the TimeClient interface,

// you would also have to modify the class SimpleTimeClient and implement the method getZonedDateTime.

// However, rather than leaving getZonedDateTime as abstract (as in the previous example),

// you can instead define a default implementation.

// (Remember that an abstract method is a method declared without an implementation.)

// 在对TimeClient接口进行修改之后,你需要继续修改SimpleTimeClient实现getZonedDateTime方法

// 但是,你可以使用JAVA8新特性 定义 一个默认实现

public interface TimeClient {

    void setTime(int hour, int minute, int second);

    void setDate(int day, int month, int year);

    void setDateAndTime(int day, int month, int year,

                               int hour, int minute, int second);

    LocalDateTime getLocalDateTime();

   

    // static block definition

    static ZoneId getZoneId (String zoneString) {

        try {

            return ZoneId.of(zoneString);

        } catch (DateTimeException e) {

            System.err.println("Invalid time zone: " + zoneString +

                "; using default time zone instead.");

            return ZoneId.systemDefault();

        }

    }

   

    // 使用default关键字的标识默认方法

    // All method declarations in an interface, including default methods, are implicitly public, so you can omit the public modifier.

    // 接口中的方法隐式公开,可以省略public修饰符

    default ZonedDateTime getZonedDateTime(String zoneString) {

        return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString));

    }

}

 

// With this interface, you do not have to modify the class SimpleTimeClient,

// and this class (and any class that implements the interface TimeClient),

// will have the method getZonedDateTime already defined. The following example,

// TestSimpleTimeClient, invokes the method getZonedDateTime from an instance of SimpleTimeClient:

// 你现在不需要修改SimpleTimeClient类,就可以使用新的getZonedDateTime接口了。

public class TestSimpleTimeClient {

    public static void main(String... args) {

        TimeClient myTimeClient = new SimpleTimeClient();

        System.out.println("Current time: " + myTimeClient.toString());

        System.out.println("Time in California: " +

            myTimeClient.getZonedDateTime("Blah blah").toString());

    }

}

 

 

Extending Interfaces That Contain Default Methods

When you extend an interface that contains a default method, you can do the following:

  • Not mention the default method at all, which lets your extended interface inherit the default method.
  • Redeclare the default method, which makes it abstract.
  • Redefine the default method, which overrides it.

如果你想要继承一个含有默认实现的接口,您可以遵循以下原则:

  1. 不需要添加默认的方法,您的子接口将继承父接口默认方法。
  2. 重新声明一遍默认方法,不实现,这将使子类的默认方法变成abstract
  3. 重新定义默认的方法,并覆盖父接口定义。

 

// Any class that implements the interface AbstractZoneTimeClient will have to implement the method getZonedDateTime;

// this method is an abstract method like all other nondefault (and nonstatic) methods

// 就像父类没有定义默认实现一样,所有的实现类需要重新实现getZonedDateTime方法

public interface AbstractZoneTimeClient extends TimeClient {

    public ZonedDateTime getZonedDateTime(String zoneString);

}

// Any class that implements the interface HandleInvalidTimeZoneClient will use the implementation of getZonedDateTime specified by this interface

// 重写getZonedDateTime,所有的HandleInvalidTimeZoneClient将使用子类的getZonedDateTime而不是父类的实现

public interface HandleInvalidTimeZoneClient extends TimeClient {

    default public ZonedDateTime getZonedDateTime(String zoneString) {

        try {

            return ZonedDateTime.of(getLocalDateTime(),ZoneId.of(zoneString));

        } catch (DateTimeException e) {

            System.err.println("Invalid zone ID: " + zoneString +

                "; using the default time zone instead.");

            return ZonedDateTime.of(getLocalDateTime(),ZoneId.systemDefault());

        }

    }

}

 

 

Static Methods

In addition to default methods, you can define static methods in interfaces. (A static method is a method that is associated with the class in which it is defined rather than with any object. Every instance of the class shares its static methods.) This makes it easier for you to organize helper methods in your libraries; you can keep static methods specific to an interface in the same interface rather than in a separate class. The following example defines a static method that retrieves a ZoneId object corresponding to a time zone identifier; it uses the system default time zone if there is no ZoneId object corresponding to the given identifier. (As a result, you can simplify the method getZonedDateTime):

除了默认的方法之外,您还可以在接口中定义静态方法。(静态方法是类相关的方法,而不是与任何对象相关。该类的每个实例都共享其静态方法。)

这使得您可以更轻松地在库中组织helper方法;您可以使得特定接口的静态方法集中在接口中,而不是分散在单独的类中。

下面的例子定义了一个静态方法,它检索与时区标识符对应的ZoneId对象;如果没有,它使用系统默认时区。

// 使用static修饰符,接口中的方法,包括static方法隐式public,你可以省略public修饰符

public interface TimeClient {

    // ...

    static public ZoneId getZoneId (String zoneString) {

        try {

            return ZoneId.of(zoneString);

        } catch (DateTimeException e) {

            System.err.println("Invalid time zone: " + zoneString +

                "; using default time zone instead.");

            return ZoneId.systemDefault();

        }

    }

 

    default public ZonedDateTime getZonedDateTime(String zoneString) {

        return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString));

    }   

}

 

 

Integrating Default Methods into Existing Libraries

Default methods enable you to add new functionality to existing interfaces and ensure binary compatibility with code written for older versions of those interfaces. In particular, default methods enable you to add methods that accept lambda expressions as parameters to existing interfaces. This section demonstrates how the Comparator interface has been enhanced with default and static methods.

默认的方法使您能够向现有接口添加新的功能,并确保新旧版本代码相兼容。

特别是,默认方法能够接受参数为lambda表达式的方法。

本节演示java8如何使用默认方法和静态方法增强了Comparator接口

Consider the Card and Deck classes as described in Questions and Exercises: Classes. This example rewrites the Card and Deck classes as interfaces. The Card interface contains two enum types (Suit and Rank) and two abstract methods (getSuit and getRank):

考虑练习中所描述的CardDeck类。

这个例子将卡片和Deck类作为接口重新编写。

// 卡片接口包含两个enum类型(Suit花色和Rank数字)和两个抽象方法(getSuitgetRank

public interface Card extends Comparable<Card> {

   

    public enum Suit {

        DIAMONDS (1, "Diamonds"),

        CLUBS    (2, "Clubs"   ),

        HEARTS   (3, "Hearts"  ),

        SPADES   (4, "Spades"  );

       

        private final int value;

        private final String text;

        Suit(int value, String text) {

            this.value = value;

            this.text = text;

        }

        public int value() {return value;}

        public String text() {return text;}

    }

   

    public enum Rank {

        DEUCE  (2 , "Two"  ),

        THREE  (3 , "Three"),

        FOUR   (4 , "Four" ),

        FIVE   (5 , "Five" ),

        SIX    (6 , "Six"  ),

        SEVEN  (7 , "Seven"),

        EIGHT  (8 , "Eight"),

        NINE   (9 , "Nine" ),

        TEN    (10, "Ten"  ),

        JACK   (11, "Jack" ),

        QUEEN  (12, "Queen"),

        KING   (13, "King" ),

        ACE    (14, "Ace"  );

        private final int value;

        private final String text;

        Rank(int value, String text) {

            this.value = value;

            this.text = text;

        }

        public int value() {return value;}

        public String text() {return text;}

    }

   

    public Card.Suit getSuit();

    public Card.Rank getRank();

}

 

// The Deck interface contains various methods that manipulate cards in a deck:

// Deck接口包含许多方法,可以操作牌桌上的卡片

public interface Deck {

   

    List<Card> getCards();

    Deck deckFactory();

    int size();

    void addCard(Card card);    // 添加牌

    void addCards(List<Card> cards);

    void addDeck(Deck deck);    // 添加牌桌

    void shuffle(); // 洗牌

    void sort();    // 排序

    void sort(Comparator<Card> c);  //

    String deckToString();  // 序列化

 

    Map<Integer, Deck> deal(int players, int numberOfCards)

        throws IllegalArgumentException;    // 打牌?

 

}

 

// The class StandardDeck implements the abstract method Deck.sort as follows:

// StandardDeck实现Desk接口,给出了sort的一种实现

public class StandardDeck implements Deck {

   

    private List<Card> entireDeck;

   

    // ...

    // The method Collections.sort sorts an instance of List whose element type implements the interface Comparable.

    // Collections.sort()可以排序所有实现的Comparable()接口的List实例

    public void sort() {

        Collections.sort(entireDeck);

    }

   

    // ...

}

 

// The class PlayingCard implements the Comparable.compareTo method as follows

// entireDeck中的元素PlayingCardComparable.compareTo()接口实现如下:

public class PlayingCard implements Card {

   

    // ...

   

    public int hashCode() {

        return ((suit.value()-1)*13)+rank.value();

    }

 

    // The method compareTo causes the method StandardDeck.sort() to sort the deck of cards first by suit, and then by rank.

    // compareTo()方法使得StandardDeck.sort()按照先花色后数字的顺序排列cards

    public int compareTo(Card o) {

        return this.hashCode() - o.hashCode();

    }

   

    // ...

}

 

// What if you want to sort the deck first by rank, then by suit?

// You would need to implement the Comparator interface to specify new sorting criteria,

// and use the method sort(List<T> list, Comparator<? super T> c)

// (the version of the sort method that includes a Comparator parameter).

// You can define the following method in the class StandardDeck:

// 如果你想先按数字排序,然后排序花色呢?

// 您需要实现Comparator接口来指定新的排序标准

// 使用重载的sort(List<T> list, Comparator<? super T> c)方法

// 您可以在StandardDeck类中定义下列方法:

public void sort(Comparator<Card> c) {

    Collections.sort(entireDeck, c);

}

 

// With this method, you can specify how the method Collections.sort sorts instances of the Card class.

// One way to do this is to implement the Comparator interface to specify how you want the cards sorted.

// The example SortByRankThenSuit does this:

// 通过这个方法实现,您可以干预Collections.sort排序card的方式。

// 其中一种干预方式是通过实现Comparator接口,来指定card的比较接口。

// 下栗通过SortByRankThenSuit指定cardscompare接口:

public class SortByRankThenSuit implements Comparator<Card> {

    public int compare(Card firstCard, Card secondCard) {

        int compVal =

            firstCard.getRank().value() - secondCard.getRank().value();

        if (compVal != 0)

            return compVal;

        else

            return firstCard.getSuit().value() - secondCard.getSuit().value();

    }

}

 

// The following invocation sorts the deck of playing cards first by rank, then by suit:

// 下面的调用首先按数字排序扑克牌,然后按花色排序

StandardDeck myDeck = new StandardDeck();

myDeck.shuffle();

myDeck.sort(new SortByRankThenSuit());

However, this approach is too verbose; it would be better if you could specify what you want to sort, not how you want to sort. Suppose that you are the developer who wrote the Comparator interface. What default or static methods could you add to the Comparator interface to enable other developers to more easily specify sort criteria?

然而,这种方法太过冗长;如果你能指定想要排序的对象,而不是你想要排序的方式,那就更好了。

假设您是编写比较器接口的开发人员。

您可以将哪些缺省或静态方法添加到Comparator接口中,以使其他开发人员更容易地指定排序标准?

// To start, suppose that you want to sort the deck of playing cards by rank, regardless of suit.

// You can invoke the StandardDeck.sort method as follows:

// 首先,假设你想要对牌桌上的的牌按数字进行排序,不管花色

// 您可以调用StandardDeck.sort()方法如下:

StandardDeck myDeck = new StandardDeck();

myDeck.shuffle();   // 洗牌

// Because the interface Comparator is a functional interface, you can use a lambda expression as an argument for the sort method.

// Comparator是一个功能接口,你可以在参数中使用lambda表达式排序(比较两个整数的大小)

myDeck.sort(

    (firstCard, secondCard) ->

        firstCard.getRank().value() - secondCard.getRank().value()

);

 

// It would be simpler for your developers if they could create a Comparator instance by invoking the method only.

// In particular, it would be helpful if your developers could create a Comparator instance

// that compares any object that can return a numerical value from a method such as getValue or hashCode.

// The Comparator interface has been enhanced with this ability with the static method comparing:

// 如果开发人员可以通过调用方法Card.getRank()创建一个Comparator比较器实例,那样不是更简单么。

// 特别地,如果开发人员可以创建一个比较器实例

// 这个比较器可以用来比较任何(从诸如getValuehashCode之类的方法返回数值)返回数值的对象,这将是很有帮助的。

// 下面,通过静态方法增强Comparator口:

myDeck.sort(Comparator.comparing((card) -> card.getRank()));

// In this example, you can use a method reference instead:

// 在本栗中,你可以是用方法引用:

myDeck.sort(Comparator.comparing(Card::getRank));

 

// This invocation better demonstrates what to sort rather than how to do it.

// 这种调用更好的指定了排序对象,而不是如何去排序。

// The Comparator interface has been enhanced with other versions of the static method comparing

// such as comparingDouble and comparingLong that enable you to create Comparator instances that compare other data types.

// 新版本的Comparator接口已经使用静态方法进行了增强,例如比较doublelong类型,

// 使您的比较器实例能比较其他数据类型。

public interface 博主举手并提问_所以你的新版使用静态方法的Comparator接口的_代码呢{}

 

// Suppose that your developers would like to create a Comparator instance that could compare objects with more than one criteria.

// For example, how would you sort the deck of playing cards first by rank, and then by suit?

// As before, you could use a lambda expression to specify these sort criteria:

// 假设开发人员想要创建一个比较器实例,它可以使用多个条件对对象进行比较。

// 栗如,你想要首先按数字排序扑克牌,然后按花色排序?

// 和以前一样,您可以使用lambda表达式来指定这些排序标准:

StandardDeck myDeck = new StandardDeck();

myDeck.shuffle();

myDeck.sort(

    (firstCard, secondCard) -> {

        int compare =

            firstCard.getRank().value() - secondCard.getRank().value();

        if (compare != 0)

            return compare;

        else

            return firstCard.getSuit().value() - secondCard.getSuit().value();

    }     

);

 

// It would be simpler for your developers if they could build a Comparator instance from a series of Comparator instances.

// The Comparator interface has been enhanced with this ability with the default method :

// 如果开发人员可以通过一系列比较器实例构建一个组合的Comparator实例,那将会更简单。

// Comparator接口已经使用默认方法得到了增强,并实现了这种thenComparing能力:

myDeck.sort(

    Comparator

        .comparing(Card::getRank)

        .thenComparing(Comparator.comparing(Card::getSuit)));

       

public interface 博主举手并提问_所以你的新版使用静态方法thenComparingComparator接口的_代码呢{}

 

// The Comparator interface has been enhanced with other versions of the default method thenComparing

// (such as thenComparingDouble and thenComparingLong) that enable you to build Comparator instances that compare other data types.

// 最新版本Comparator接口已经加入了其他thenComparing默认方法(如:thenComparingDouble),并进一步增强了。

// 这使您能够构建比较其他数据类型的比较器实例

public interface 博主举爪并提问_所以您的新版使用静态方法thenComparingDoubleComparator接口的_代码呢{}

 

// Suppose that your developers would like to create a Comparator instance that enables them to sort a collection of objects in reverse order.

// For example, how would you sort the deck of playing cards first by descending order of rank, from Ace to Two (instead of from Two to Ace)?

// As before, you could specify another lambda expression.

// However, it would be simpler for your developers if they could reverse an existing Comparator by invoking a method.

// The Comparator interface has been enhanced with this ability with the default method reversed:

// 假设开发人员想要创建一个比较器实例,使他们能够实现reverse功能

// 比如想要:从A2而不是从2A

// 和以前一样,您可以指定另一个lambda表达式。

// 但是如果可以使用方法引用来代替lambda表达式,代码看上去会更加整洁。

// Comparator接口已经加入了reversed默认方法,并被增强了。

myDeck.sort(

    Comparator.comparing(Card::getRank)

        .reversed()

        .thenComparing(Comparator.comparing(Card::getSuit)));

 

// This example demonstrates how the Comparator interface has been enhanced with default methods, static methods, lambda expressions, and method references

// to create more expressive library methods whose functionality programmers can quickly deduce by looking at how they are invoked.

// Use these constructs to enhance the interfaces in your libraries.

// 这个例子演示了如何使用默认方法、静态方法、lambda表达式和方法引用来增强比较器接口,以创建更富有的库方法,

// 程序员可以快速地推断出它们的功能。并使用这些结构来增强库中的接口。

public interface 博主举双爪并提问_所以您的新版富有的的Comparator接口的_代码呢{}

 

最后通过博主举双爪吱吱不倦,不吃晚饭的的努力,发现这货是java8增强的一个接口(难怪小标题叫做库方法的综合运用),在java.utils包下,以下是源码及其翻译:

/**

 * A comparison function, which imposes a <i>total ordering</i> on some

 * collection of objects.  Comparators can be passed to a sort method (such

 * as {@link Collections#sort(List,Comparator) Collections.sort} or {@link

 * Arrays#sort(Object[],Comparator) Arrays.sort}) to allow precise control

 * over the sort order.  Comparators can also be used to control the order of

 * certain data structures (such as {@link SortedSet sorted sets} or {@link

 * SortedMap sorted maps}), or to provide an ordering for collections of

 * objects that don't have a {@link Comparable natural ordering}.<p>

 *

 * 一个比较函数,加在对象的集合上,对对象进行排序。Comparators比较器可以

 * 通过一个比较方法传入如:sort(Object[],Comparator),以控制得到指定的排列顺序。

 * Comparators比较器还可以用来控制一定的数据结构如{set,map}的顺序,或者为那些没有

 * 顺序的集合提供排序?

 * (住:翻译可能不准确,自个看英文)

 *

 * The ordering imposed by a comparator <tt>c</tt> on a set of elements

 * <tt>S</tt> is said to be <i>consistent with equals</i> if and only if

 * <tt>c.compare(e1, e2)==0</tt> has the same boolean value as

 * <tt>e1.equals(e2)</tt> for every <tt>e1</tt> and <tt>e2</tt> in

 * <tt>S</tt>.<p>

 *

 * 由比较器在一组元素上施加的排序

 * 应该和equals是一致的,也就是说:当且仅当S中的任意e1e2

 * c.compare(e1, e2)==0e1.equals(e2),具有相同的布尔值。

 * (住:翻译可能不准确,自个看英文)

 *

 * Caution should be exercised when using a comparator capable of imposing an

 * ordering inconsistent with equals to order a sorted set (or sorted map).

 * Suppose a sorted set (or sorted map) with an explicit comparator <tt>c</tt>

 * is used with elements (or keys) drawn from a set <tt>S</tt>.  If the

 * ordering imposed by <tt>c</tt> on <tt>S</tt> is inconsistent with equals,

 * the sorted set (or sorted map) will behave "strangely."  In particular the

 * sorted set (or sorted map) will violate the general contract for set (or

 * map), which is defined in terms of <tt>equals</tt>.<p>

 *

 * 当使用一个比较器comparator得到的顺序和使用equals来排序setmap,排序不一致时,应该小心谨慎。

 * 假设一个已排序的集合(或已排序的map)与一个指定的比较器c

 * 同时作用在一个集合S的元素(或keys键)上。如果

 * 使用equals和使用comparator排序后结果不一致,将造成奇怪的结果。

 * 特别是这个集合排序结果将和使用一般的equals定义的排序结果不同。

 *(住:翻译可能不准确,自个看英文)

 *

 * For example, suppose one adds two elements {@code a} and {@code b} such that

 * {@code (a.equals(b) && c.compare(a, b) != 0)}

 * to an empty {@code TreeSet} with comparator {@code c}.

 * The second {@code add} operation will return

 * true (and the size of the tree set will increase) because {@code a} and

 * {@code b} are not equivalent from the tree set's perspective, even though

 * this is contrary to the specification of the

 * {@link Set#add Set.add} method.<p>

 *

 * 举个栗子:假设S是一个TreeSet,S={a, b} a.equals(b) 但是 c.compare(a, b) != 0

 * 因为comparator不相等,tree将会增加节点,tree将会认为ab不是equivalent相等的

 * 这和a.equals(b)是相反的。

 * (住:翻译可能不准确,自个看英文)

 *

 * Note: It is generally a good idea for comparators to also implement

 * <tt>java.io.Serializable</tt>, as they may be used as ordering methods in

 * serializable data structures (like {@link TreeSet}, {@link TreeMap}).  In

 * order for the data structure to serialize successfully, the comparator (if

 * provided) must implement <tt>Serializable</tt>.<p>

 *

 * 注意:对于比较器来说,comparators实现序列化接口,这通常是一个好主意。

 * 可序列化的,因为它们可能在序列化的数据结构上被用作排序方法

 * 就像treeSet,treeMap.为了能让他么成功的序列化,比较器comparator必须实现Serializable

 * (住:翻译可能不准确,自个看英文)

 *

 * For the mathematically inclined, the <i>relation</i> that defines the

 * <i>imposed ordering</i> that a given comparator <tt>c</tt> imposes on a

 * given set of objects <tt>S</tt> is:<pre>

 *       {(x, y) such that c.compare(x, y) &lt;= 0}.

 * </pre> The <i>quotient</i> for this total order is:<pre>

 *       {(x, y) such that c.compare(x, y) == 0}.

 * </pre>

 *

 * 对于数学上的倾向,关系 的定义了 强制要求一个给定的比较器对a进行排序

 * 关系表达式:{(x, y) such that c.compare(x, y) <= 0}中强制使用比较器?

 * (住:翻译可能不准确,自个看英文)

 *

 * It follows immediately from the contract for <tt>compare</tt> that the

 * quotient is an <i>equivalence relation</i> on <tt>S</tt>, and that the

 * imposed ordering is a <i>total order</i> on <tt>S</tt>.  When we say that

 * the ordering imposed by <tt>c</tt> on <tt>S</tt> is <i>consistent with

 * equals</i>, we mean that the quotient for the ordering is the equivalence

 * relation defined by the objects' {@link Object#equals(Object)

 * equals(Object)} method(s):<pre>

 *     {(x, y) such that x.equals(y)}. </pre>

 *

 * 这是在定义中紧密相连的,比较是一种等价关系,而

 * 强加的顺序完全是一种秩序。当我们说

 * 比较器c上的顺序是与之一致的

 * 等于,我们的意思是,排序的结果等价的

 * (住:翻译可能不准确,自个看英文)

 *

 * <p>Unlike {@code Comparable}, a comparator may optionally permit

 * comparison of null arguments, while maintaining the requirements for

 * an equivalence relation.

 *

 * Comparable不一样,一个比较器可能接受空参数,同时保持判空的需求

 * (住:翻译可能不准确,自个看英文)

 *

 * <p>This interface is a member of the

 * <a href="{@docRoot}/../technotes/guides/collections/index.html">

 * Java Collections Framework</a>.

 *

 * @param <T> the type of objects that may be compared by this comparator

 *

 * @author  Josh Bloch

 * @author  Neal Gafter

 * @see Comparable

 * @see java.io.Serializable

 * @since 1.2

 */

@FunctionalInterface

public interface Comparator<T> {

       

    int compare(T o1, T o2);

    boolean equals(Object obj);

    /**

     * Returns a comparator that imposes the reverse ordering of this

     * comparator.

     *

     * @return a comparator that imposes the reverse ordering of this

     *         comparator.

     * @since 1.8

     */

    default Comparator<T> reversed() {

        return Collections.reverseOrder(this);

    }

    /**

     * Returns a lexicographic-order comparator with another comparator.

     * If this {@code Comparator} considers two elements equal, i.e.

     * {@code compare(a, b) == 0}, {@code other} is used to determine the order.

     *

     * <p>The returned comparator is serializable if the specified comparator

     * is also serializable.

     *

     * 返回的比较器是可序列化的,如果指定的比较器是可序列化的

     *

     * @apiNote

     * For example, to sort a collection of {@code String} based on the length

     * and then case-insensitive natural ordering, the comparator can be

     * composed using following code,

     *

     * <pre>{@code

     *     Comparator<String> cmp = Comparator.comparingInt(String::length)

     *             .thenComparing(String.CASE_INSENSITIVE_ORDER);

     * }</pre>

     *

     * @param  other the other comparator to be used when this comparator

     *         compares two objects that are equal.

     * @return a lexicographic-order comparator composed of this and then the

     *         other comparator

     * @throws NullPointerException if the argument is null.

     * @since 1.8

     */

    default Comparator<T> thenComparing(Comparator<? super T> other) {

        Objects.requireNonNull(other);

        return (Comparator<T> & Serializable) (c1, c2) -> {

            int res = compare(c1, c2);

            return (res != 0) ? res : other.compare(c1, c2);

        };

    }

   

    // ...

   

     public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() {

        return (Comparator<T>) Comparators.NaturalOrderComparator.INSTANCE;

    }

   

    // ...

    // nullsFirst

    // nullsLast

    // comparing

    // comparing

    // ...

}

 

猜你喜欢

转载自blog.csdn.net/u012296499/article/details/81747620
今日推荐