2011-01-22 25 views
5

estoy atascado en que tengo un libro objeto que tiene tres variablesJava Complejo Clasificación

String title 
int Year 
String authorName 

debo ordenar los libros por uno, dos o los tres de las variables en orden ascendente o descendente, implementé el orden del título, pero estoy atascado en cuanto a qué hacer cuando las personas eligen más de una variable para ordenar.

Aquí es parte de mi código:

Clase del libro:

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

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 aunque podría funcionar una poco más e en el comparador pero estoy realmente atascado en cómo modelar tal cosa, gracias de antemano

+0

¿Es esta tarea? Si es así, márquelo como tal. – CoolBeans

+0

Esto no es tarea, estoy estudiando para una evaluación; D – bwagner

+0

@CoolBeans: por favor [no sugiera meta-etiquetado] (http://meta.stackexchange.com/questions/10811/how-to-ask-and -answer-tarea-preguntas). –

Respuesta

2

Esto suena como una tarea problema. Así que les voy a dar algunos consejos.

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

El mayor problema es que las personas pueden elegir cualquier orden, pueden elegir autor ascendente, año descendiente y luego título ascendente, o de otra manera, una cadena IF para cada posibilidad parece un poco demasiado – bwagner

+0

Bueno, como dije, te doy la idea básica de cómo ordenar en más de un campo. Entonces, para responder a su pregunta, lo que debe hacer es tener un método de comparación para cada campo y luego, según el orden seleccionado por el usuario, llamarlos en ese orden en la clase principal del comparador. – CoolBeans

+0

Por ejemplo, sobre cómo encadenar comparadores múltiples ... eche un vistazo a este enlace http://www.java2s.com/Code/Java/Collections-Data-Structure/ListandComparators.htm. – CoolBeans

2

El ascenso/descenso puede implementarse mucho más fácilmente, porque simplemente "invierte" el resultado de la comparación. Y se puede "reutilizar" los resultados de los métodos compareToIgnoreCase:

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

Los otros comparadores son bastante similar (limitación de las muestras en el método de comparación):

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

Gracias, ayudó a limpiar el código mucho – bwagner

+0

¿Puedo poner todos esos comparadores en una sola clase? – bwagner

2

escritura 3 clases de comparación que comparan un atributo específico y luego una clase comparativa global que toma una lista ordenada de comparadores.

O utilice algunos una clase de conveniencia de una biblioteca como org.apache.commons.collections.comparators.ComparatorChain.

Editar:

OP pregunta:

cómo podría escribir que comparador general:

Algo así como:

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

¿cómo podría escribir ese comparador general, para preservar el orden hecho en los comparadores anteriores? – bwagner

+0

@bwgpro - ver edición –

+0

No me siento cómodo usando Java todavía, ¿cómo agrego la cadena de comparación común de Apache a mi programa? – bwagner