Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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 not allowed to use the Comparable class with Book. How would you recommend I sort the array of Books in library? Write my own sort? Or is there an easier way? If you need snippets of code, just ask!

like image 779
samuraiseoul Avatar asked Sep 16 '12 19:09

samuraiseoul


2 Answers

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
   }
});
like image 158
Peter Lawrey Avatar answered Oct 05 '22 20:10

Peter Lawrey


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()));
    }
}
like image 39
Bruno Kim Avatar answered Oct 05 '22 20:10

Bruno Kim