5

I am stuck in that I have an Object Book that got three variables

String title
int Year
String authorName

I must sort the books by one, two or all three of the variables in ascending or descending order, I implemented the title ordering but I am stuck as to what to do when people choose more than one variable to order.

Here is some of my code:

Book Class:

import java.util.ArrayList;


public class Book{

String title;
String authorName;
int editionYear;

public Book(String title, String authorName, int editionYear){
    this.title = title;
    this.authorName = authorName;
    this.editionYear = editionYear;

}

public String getBookInfo(){

    ArrayList bookInfo = new ArrayList();
    bookInfo.add(this.title);
    bookInfo.add(this.authorName);
    bookInfo.add(this.editionYear);
    return bookInfo.toString();
}

}

BookSorter Class:

import java.util.Arrays;
import java.util.Comparator;

public class BookSorter{

private String sortkey;
private String order;
Book[] Books;

public BookSorter(Book Book1, Book Book2, Book Book3, Book Book4){
    this.Books = new Book[] {Book1, Book2, Book3, Book4};
}

public Book[] sortByTitle(boolean sortorder){
    Comparator<Book> byTitle = new TitleComparator(sortorder);
    Arrays.sort(Books, byTitle);
    for(int i=0;i<4;i++) System.out.println(Books[i].title);
    return Books;
}
}

TitleComparator:

import java.util.Comparator;

class TitleComparator implements Comparator<Book> {

boolean ascending;

public TitleComparator(boolean ascending){
    this.ascending = ascending;
}

public int compare(Book Book1, Book Book2){
    if(ascending == true){
        if(Book1.title.compareToIgnoreCase(Book2.title) > 0) return 1;
        else if(Book1.title.compareToIgnoreCase(Book2.title) < 0) return -1;
        else return 0;
    }else{
        if(Book2.title.compareToIgnoreCase(Book1.title) < 0) return -1;
        else if(Book2.title.compareToIgnoreCase(Book1.title) > 0) return 1;
        else return 0;
    }
}
}

I though I could work a little more on the comparator but I am really stuck on how to model such a thing, Thanks in advance

6
  • Is this homework? If so please tag it as such. Commented Jan 22, 2011 at 21:45
  • This is no homework, I'm studying to an assessment ;D Commented Jan 22, 2011 at 22:26
  • @CoolBeans: please do not suggest meta-tagging. Commented Jan 22, 2011 at 22:57
  • Thanks Matt. I was not aware of it. Commented Jan 22, 2011 at 23:12
  • The fate of [homework] is still not definite: meta.stackexchange.com/questions/60422/is-homework-an-exception/… Commented Jan 22, 2011 at 23:55

4 Answers 4

3

Write 3 comparator classes that each compare a specific attribute and then an overall comparator class that takes an ordered list of comparators.

Or use some a convenience class from a library like org.apache.commons.collections.comparators.ComparatorChain.

Edit:

OP asks:

how could I write that overall comparator:

Something like:

// private List<Comparator<?>> comparators;  // initialized in constructor

// compare method(book1, book2):
//     note that while result == 0, books have had equal attributes so far
//     once result is != 0, the books are now ordered - no need to compare further
//     if we run out of comparators and result still == 0, books are equal.

//     initialize iterator to list of comparators
//     int result = 0;
//     while result == 0 && still more comparators
//         get current comparator from iterator
//         result = comparator.compare(book1, book2); // compare current attribute
//     end-while
//     return result
Sign up to request clarification or add additional context in comments.

2 Comments

how could I write that overall comparator, in order to preserve the ordering done in the previous comparators?
I am not comfortable using java yet, how do I add the apache common comparator chain to my program?
2

This sounds like a homework problem. So I am going to provide you with some hints.

1. First see if Title1==Title2.
    1.1 if YES then see if year1==year2
            1.1.1 if YES then see if authorName1==authorName2
              1.1.1.1 If YES then they are equal (return 0)
              1.1.1.2 else if NO compare author1 and author2 (return 1 or -1)
     1.2 else if NO then compare year1 and year2 (return 1 or -1)
2. else if NO then compare title1 and title2 (return 1 or -1)

3 Comments

The biggest problem is that people can Choose any order, they could choose author ascending, year descending and then title ascending, or the other way, an IF chain for each possibility look a little too much
Well as I said I am giving you the basic idea on how to sort on more than one field. So to answer your question what you should do is have a compare method for each field and then based on the user selected order call them in that order in the main comparator class.
For example on how to chain multiple comparators ... take a look at this link java2s.com/Code/Java/Collections-Data-Structure/… .
2

The ascending/descending can be implemented much easier, because it simple "inverts" the compare result. And you can "reuse" the results from the compareToIgnoreCase methods:

public int compare(Book book1, Book book2) {       
   int result = book1.title.compareToIgnoreCase(book2.title);
   return ascending ? result : result * -1;
}

The other comparators are pretty similiar (limiting the samples to the compare method):

public int compare(Book book1, Book book2) {       
   int result = book1.author.compareToIgnoreCase(book2.author);
   return ascending ? result : result * -1;
}

public int compare(Book book1, Book book2) {
   Integer year1 = book1.year;   
   Integer year2 = book2.year;
   int result = year1.compareTo(year2);
   return ascending ? result : result * -1;
}

1 Comment

Can I put all those comparators in a single class?
1

The Group Comparator allows you to sort on multiple properties. You can also use the Bean Comparator so you don't have to keep writing custom Comparators.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.