2011-01-22 19 views
5

siedzę na tym, że mam obiektu Book że dostał trzy zmienneJava Complex Sortowanie

String title 
int Year 
String authorName 

muszę uporządkować książki przez jednego, dwóch lub wszystkich trzech zmiennych w porządku rosnącym lub malejącym, I wdrożone tytuł zamówienia, ale utknąłem, co zrobić, gdy ludzie wybierają więcej niż jedną zmienną do zamówienia.

Oto niektóre z moich kodu:

Book Klasa:

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 Klasa:

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 chociaż mogę pracować mały mor e na komparatorze, ale naprawdę utknąłem na tym, jak modelować takie rzeczy, Z góry dzięki

+0

Czy to zadanie domowe? Jeśli tak, proszę oznaczyć go jako taki. – CoolBeans

+0

To nie jest praca domowa, studiuję do oceny; D – bwagner

+0

@CoolBeans: proszę [nie sugeruj meta-tagowania] (http://meta.stackexchange.com/questions/10811/how-to-ask-and -answer-homework-questions). –

Odpowiedz

2

brzmi to jak praca domowa problem. Mam zamiar przekazać ci kilka wskazówek.

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) 
+1

Największym problemem jest to, że ludzie mogą wybrać dowolne zamówienie, mogą wybrać autora rosnąco, rok zstępujący, a następnie tytuł rosnąco, lub w inny sposób, łańcuch IF dla każdej możliwości wygląda trochę za dużo – bwagner

+0

Tak jak powiedziałem, że daję ci podstawowa idea sortowania na więcej niż jednym polu. Aby odpowiedzieć na pytanie, co należy zrobić, należy zastosować metodę porównania dla każdego pola, a następnie na podstawie wybranego przez użytkownika porządku, wywołać je w tej kolejności w głównej klasie komparatora. – CoolBeans

+0

Na przykład, jak powiązać wiele komparatorów ... spójrz na ten link http://www.java2s.com/Code/Java/Collections-Data-Structure/ListandComparators.htm. – CoolBeans

2

Wznoszenie/opadanie może być realizowane znacznie łatwiej, ponieważ proste "odwraca" wynik porównania. I można "ponowne użycie" wyniki z metod compareToIgnoreCase:

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

Pozostałe komparatory są dość podobna (ograniczenie próbek do metody porównania):

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; 
} 
+0

Dzięki, pomogło to w wyczyszczeniu kodu. – bwagner

+0

Czy mogę umieścić wszystkie te komparatory w jednej klasie? – bwagner

2

zapisu 3 klasy komparatorów, z których każda porównuje określony atrybut, a następnie ogólną klasę komparatora, która pobiera uporządkowaną listę komparatorów.

Lub użyj pewnej klasy wygody z biblioteki takiej jak org.apache.commons.collections.comparators.ComparatorChain.

Edit:

OP pyta:

jak mógłbym napisać, że ogólny komparatora:

coś takiego:

// 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 
+0

jak napisać ten ogólny komparator, aby zachować porządek wykonany w poprzednich komparatorach? – bwagner

+0

@bwgpro - patrz edytuj –

+0

Nie czuję się komfortowo przy użyciu języka Java, jak dodać do mojego programu popularny łańcuch porównawczy Apache? – bwagner