Java Sorting: sort an array of objects by property, object not allowed to use Comparable

后端 未结 4 677
生来不讨喜
生来不讨喜 2020-12-01 11:30

I have a class, Library, that contains an array of Book objects, and I need to sort the array based off the properties of Book, either Title or PageNumber. The problem is im

相关标签:
4条回答
  • 2020-12-01 11:47

    If you can use Comparators, write one for each type of sorting you need, e.g., ascending for book title and descending for page number. The compare method of a Comparator must return positive if the first argument is larger than the second, negative if the first is smaller and zero if they are equal.

    import java.util.Comparator;
    import java.util.List;
    import java.util.Arrays;
    
    class Book{
        String title;
        int pageNumber;
    
        public Book(String title, int pageNumber){
            this.title = title;
            this.pageNumber = pageNumber;
        }
    
        String getTitle(){ return title; }
        int getPageNumber(){ return pageNumber; }
    
        public String toString(){
            return "(" + title + ", " + pageNumber + " pages)";
        }
    }
    
    public class Library{
    
        // These variables are static because you don't need multiple copies
        // for sorting, as they have no intrinsic state.
        static private Comparator<Book> ascTitle;
        static private Comparator<Book> descPageNumber;
    
        // We initialize static variables inside a static block.
        static {
            ascTitle = new Comparator<Book>(){
                @Override
                public int compare(Book b1, Book b2){
                    return b1.getTitle().compareTo(b2.getTitle());
                }
            };
    
            descPageNumber = new Comparator<Book>(){
                @Override
                public int compare(Book b1, Book b2){
                    // Java 7 has an Integer#compare function
                    return Integer.compare(b1.getPageNumber(), b2.getPageNumber());
                    // For Java < 7, use 
                    // Integer.valueOf(n1).compareTo(n2);
                    // DO NOT subtract numbers to make a comparison such as n2 - n1.
                    // This can cause a negative overflow if the difference is larger 
                    // than Integer.MAX_VALUE (e.g., n1 = 2^31 and n2 = -2^31)
                }
            };
        }
    
        private Book[] books;
        public Book[] getBooks(){ return books; }
    
        public void sortAscTitle(){
            Arrays.sort(books, ascTitle);
        }
    
        public void sortDescPageNumber(){
            Arrays.sort(books, descPageNumber);
        }
    
        public Library(Book[] books){
            this.books = books;
        }
    
        public static void main(String[] args){
            Library library = new Library( new Book[]{
                new Book("1984", 123), 
                new Book("I, Robot", 152), 
                new Book("Harry Potter and the Philosopher's Stone", 267),
                new Book("Harry Potter and the Goblet of Fire", 759),
                new Book("The Bible", 1623)
            });
    
            library.sortAscTitle();
            System.out.println(Arrays.toString(library.getBooks()));
    
            library.sortDescPageNumber();
            System.out.println(Arrays.toString(library.getBooks()));
        }
    }
    
    0 讨论(0)
  • 2020-12-01 11:54

    Expanding @PeterLawrey's answer to Java 8, you can now use a Lambda Expression instead of a Comparable<T> delegate:

    Collections.sort(books, (firstBook, secondBook -> b1 is greater return +1, 
                                                      if b2 is smaller return -1 otherwise 0));
    
    0 讨论(0)
  • 2020-12-01 12:01

    You can provide a Comparator for comparing any type you wish, Comparable or otherwise.

    For Arrays and Collections you use

    Arrays.sort(array, myComparator);
    Collections.sort(list, myComparator);
    

    Even sorted collections like TreeSet can take a custom Comparator

    e.g.

    Collections.sort(books, new Comparator<Book>() {
       public int compare(Book b1, Book b2) {
          return if b1 is greater return +1, if b2 is smaller return -1 otherwise 0
       }
    });
    
    0 讨论(0)
  • 2020-12-01 12:10

    Stick this in your Library:

    java.util.Collections.sort(bookList, bookComparator);
    
    0 讨论(0)
提交回复
热议问题