简体   繁体   English

如何实现 Comparable 接口?

[英]How to implement the Comparable interface?

We have written the following Movie class below, and we want to be able to use the Collections.sort method to sort an ArrayList<Movie> .我们在下面编写了以下Movie class,我们希望能够使用Collections.sort方法对ArrayList<Movie>进行排序。 We want to sort by the title instance variable, and we want to break ties by the year instance variable.我们想要按title实例变量排序,并且我们想要按year实例变量打破平局。 However, our code doesn't work, and we have no idea why.但是,我们的代码不起作用,我们也不知道为什么。

Example例子

ArrayList<Movie> movies = new ArrayList<>();
movies.add(new Movie("Good Burger", 1997));
movies.add(new Movie("The Lord of the Rings: The Fellowship of the Ring", 2001));
movies.add(new Movie("Fast Five", 2011));

Collections.sort(movies);

for (Movie m : movies) {
    System.out.println(m);
}

will print the following:将打印以下内容:

(Fast Five, 2011)
(Good Burger, 1997)
(The Lord of the Rings: The Fellowship of the Ring, 2001)

This is the Movie class:这是Movie class:

class Movie implements Comparable<Movie> {

    private final String title;
    private final int year;

    public Movie(String t, int y) {
        this.title = t;
        this.year = y;
    }

    public String toString() {
        return "(" + this.title + ", " + this.year + ")";
    }

    public boolean equals(Object o) {
        return (o instanceof Movie) &&              // check if o is a Movie
               this.year == ((Movie)o).year &&      // check years for equality
               this.title.equals(((Movie)o).title); // check titles for equality
    }

    @Override
    public int compareTo(Movie m) {
        return Integer.compare(this.year, m.year);
    }
}

How does one implement the Comparable interface?如何实现Comparable接口?

One way to do this is to use the Comparator<T> interface:一种方法是使用Comparator<T>接口:

return Comparator.comparing(Movie::title)
                 .thenComparingInt(Movie::year)
                 .compare(this, m);

You want to sort by the title , but you have used year in your compareTo method as follows:您想按title排序,但您在compareTo方法中使用了year ,如下所示:

@Override
public int compareTo(Movie m) {
    return Integer.compare(m1.getYear(), m2.getYear());
}

Change it to将其更改为

@Override
public int compareTo(Movie m) {
    int c;
    if(this.title!=null && m!=null && m.getTitle()!=null){  
        c = this.title.compareTo(m.getTitle());
        if (c == 0)
            c = Integer.compare(this.year, m.getYear());            
    }
    return c;
}

For more flexibility, you can use Comparator instead of Comparable as discussed at Java: Comparable vs Comparator为了获得更大的灵活性,您可以使用Comparator而不是Comparable ,如Java 中所述:Comparable vs Comparator

Update: I just went through your question again and realized that first, you want to compare the title and then in case of a tie, you want to compare on year.更新:我刚刚再次查看了您的问题,并意识到首先,您想比较标题,然后在平局的情况下,您想比较年份。 I have updated the code given above.我已经更新了上面给出的代码。 Additionally, I have provided another approach (using Comparator) below:此外,我在下面提供了另一种方法(使用 Comparator):

public class MovieCompartor implements Comparator<Movie>{
    public int compare(Movie m1, Movie m2) {
        int c;
        if(m!=null && m2!=null){
            if(m1.getTitle()!=null && m2.getTitle()!=null)
                c = m1.getTitle().compareTo(m2.getTitle());
            if (c == 0)
                c = Integer.compare(m1.getYear(), m2.getYear());            
        }
        return c;
    }
}

Then you use Collections.sort(movies, new MovieCompartor()) instead of Collections.sort(movies) .然后你使用Collections.sort(movies, new MovieCompartor())而不是Collections.sort(movies)

You have to first sort by title, then sort by year:您必须首先按标题排序,然后按年份排序:

@Override
public int compareTo(Movie m){
    if (this.title.equals(m.title)){         //if titles are same
        return this.year - m.year;           //compare years
    }
    return this.title.compareTo(m.title);    //else just compare titles
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM