Estoy tratando de resolver dos ArrayLists diferentes de objetos por un atributo específico (objetos 'estudiante' por "programa" y objetos 'profesor' por "facultad"). Ambas clases se extienden mi clase abstracta 'persona'.
public abstract class Person implements Comparable<Person>{
private String name;
private String adress;
//getters, setters, etc., all works properly
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public int compareTo(String string) {
return name.compareTo(string);
}
}
Entonces, cuando se crea un conjunto de objetos al azar 1000000 'persona' que pueden ser estudiantes o profesores, decido ordenarla alfabéticamente por su nombre como esto (que funciona correctamente).
Person personByName[] = arrayPersonas.clone();
Arrays.sort(personByName);
Entonces, divido la matriz persona original en dos ArrayLists, uno para objetos Student y otro para el profesor objetos:
ArrayList<Student> studentsByProgram = new ArrayList();
ArrayList<Professor> professorsByFaculty = new ArrayList();
for (int i = 0; i < 1000000; i++) {
if (arrayPersonas[i] instanceof Student) {
studentsByProgram.add((Student)arrayPersonas[i]);
} else {
professorsByFaculty.add((Professor)arrayPersonas[i]);
}
}
El problema viene cuando intento ordenar cada ArrayList alfabéticamente por el atributo que quiera, ya que mantiene la clasificación por el nombre de la persona:
Collections.sort(studentsByProgram);
Collections.sort(professorsByFaculty);
Aquí les dejo mis clases de estudiantes y profesores:
public class Student extends Person {
private String program;
private int year;
private double fee;
//constructor, setters, getters, toString, equals
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public int compareTo(String string) {
return program.compareTo(string);
}
@Override
public int compareTo(Person t) {
return super.compareTo(t.getName());
}
}
clase Profesor:
public class Professor extends Person {
private String faculty;
private double salary;
//constructor, setters, getters, toString, equals
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public int compareTo(String string) {
return faculty.compareTo(string);
}
@Override
public int compareTo(Person t) {
return super.compareTo(t.getName());
}
}
¿Qué estoy haciendo mal? Pensé que si yo llamo "Collections.sort ()" en un ArrayList de objetos Student sería utilizar el método "compareTo ()" de mi clase del estudiante, que utiliza el atributo "programa". Todavía estoy aprendiendo a trabajar con estos métodos por lo que no es algo que yo no recibo.
Los problemas
- Que no define cómo
Person
se deben comparar objetos. - Usted definidos de forma incorrecta la forma
Student
yProfessor
los casos se debe comparar. - Usted escribió métodos sobrecargados
compareTo(String)
que son engañosos.
Las soluciones
Definir
Person#compareTo
correctamente, retire sucompareTo(String)
:public int compareTo(Person p) { return getName().compareTo(p.getName()); }
Definir
Student#compareTo
yProfessor#compareTo
correctamente, retire sucompareTo(String)
. Aquí está un ejemplo de cómoStudent#compareTo
se podría escribir:@Override public int compareTo(Person t) { final int personComparisonResult = super.compareTo(t); if (personComparisonResult == 0) { return program.compareTo(((Student) t).program); } return personComparisonResult; }
Dice que "comparar como
Person
s primeros; si son iguales (en este caso, tener el mismo nombre), ellos se compara comoStudent
s (en este caso, por el programa del estudiante)".Me gustaría eliminar estos métodos. No vale la pena tener un método diferente para una simple línea de código que no encaja en el dominio de clase.