Foro de elhacker.net

Programación => Java => Mensaje iniciado por: kikian94 en 8 Marzo 2015, 13:33 pm



Título: Utilizacion de CompareTo en objetos dentro de un Set
Publicado por: kikian94 en 8 Marzo 2015, 13:33 pm
Hola, tengo que hacer una practica de un almacen de poblaciones, en el cual, las poblaciones se almacenan en un set el cual esta asociado a un string que es la provincia a la que pertenecen, todo se guarda en un mapa en el que el string de la provincia es la clave y el Set es el valor, he codificado todos los metodos, para añadir poblaciones, quitarlas, guardarlo en un archivo, leerlo etc, pero ahora tengo este metodo:

Código
  1. public boolean ordenarPor(String provincia, int ordenarPor)

al cual se le pueden pasar 2 constantes para ordenar por habitantes o por nombre de poblacion, llevo esto codificado:

Código
  1. public boolean ordenarPor(String provincia, int ordenarPor) {
  2. if(provincia != null || ordenarPor != ORDENARPORNOMBRE || ordenarPor != ORDENARPORHABITANTES ){
  3. if(ordenarPor == ORDENARPORNOMBRE){
  4. Set<IPoblacion> spoblacion = Aprovincias.get(provincia);
  5. System.out.println(spoblacion);
  6. }else if(ordenarPor == ORDENARPORHABITANTES){
  7.  
  8.  
  9. }
  10.  
  11.  
  12.  
  13. return true;
  14. }
  15. return false;
  16. }

por defecto todas las poblaciones hacen uso del metodo CompareTo en el que digo que deben de ordenar las poblaciones por el valor nombre de cada una, pero lo que no se es como ordenarlas por otro valor, me he quedado otra clase en la que tambien implemento la interfaz compareTo y sobreescribo el metodo para ordenar por habitantes, pero no se utilizarlo



Título: Re: Utilizacion de CompareTo en objetos dentro de un Set
Publicado por: Usuario Invitado en 9 Marzo 2015, 16:09 pm
Aquí te muestro una forma de ordenar por nombre de provincias. Los pasos a realizar son los siguientes:

  • Extraer las provincias solamente (nombres).
  • Extraer las poblaciones solamente (sets).
  • Ordenar el nombre de las provincias. Para ello hacemos uso de Collections.sort(List<T> list), que ordena una lista en forma ascendente.
  • Recorremos las provincias ordenadas e internamente recorremos la lista de poblaciones.
  • Comparamos el nombre de la provincia actual por cada nombre de provincia del objeto Población de cada Set (en mi caso getStateName()).

Por ejemplo, la problación Leganes tiene la siguiente estructura:

Nombre de provincia: Leganes
Número de ? (no sé que significa ese número): 345
Nombre de estado: Madrid (éste viene a ser la provincia madre) -> getStateName().

  • En caso haya coincidencia agrega ese Set a una nueva lista de Set que estará ordenada gracias a la lista de provincias ordenadas.
  • Por ultimo, cuando ya tenemos las listas de provincias y la lista de Set poblaciones ya ordenadas, las agregamos a un nuevo Map y lo retornamos.


NOTA: Se hace uso de la implementación de Map LinkedHashMap ya que HashMap no respeta el orden de inserción. Por el contrario, LinkedHashMap sí respeta.

Solo colocaré los nuevos métodos.

Código
  1. public Map<String, Set<Population>> sortBy(int sortType) {
  2. Map<String, Set<Population>> sortedProvincesAndPopulations = null;
  3. if(sortType == SORT_BY_NAME) {
  4. List<String> sortedProvinces = new ArrayList<>();
  5. List<Set<Population>> populations = new ArrayList<>();
  6. List<Set<Population>> sortedPopulations = new ArrayList<>();
  7. sortedProvincesAndPopulations = new LinkedHashMap<>();
  8.  
  9. populations = getPopulations();
  10. sortedProvinces = getProvinces(populations);
  11.  
  12. Collections.sort(sortedProvinces);
  13.  
  14. /* Compara el nombre de la provincia de la lista ya ordenada con la
  15. * lista de poblaciones. Si coinciden se agrega este Set poblacion a la lista
  16. * de poblaciones ordenada.
  17. * getStateName() : devuelve el nombre de la provincia que alberga esa poblacion */
  18. for(String provinceName : sortedProvinces) {
  19. for (Set<Population> population : populations) {
  20. sortPopulations(population, provinceName, sortedPopulations);
  21. }
  22. }
  23.  
  24. fillNewSortedProvincesAndPopulations(sortedProvincesAndPopulations, sortedProvinces, sortedPopulations);
  25.  
  26. } else {
  27. // el otro tipo de ordenamiento
  28. }
  29. return sortedProvincesAndPopulations;
  30. }

Métodos de ayuda:

Código
  1. private List<Set<Population>> getPopulations() {
  2. List<Set<Population>> populations = new ArrayList<>();
  3. for(Map.Entry<String, Set<Population>> entry : provincesAndPopulations.entrySet()) {
  4. populations.add(entry.getValue());
  5. }
  6. return populations;
  7. }
  8.  
  9. private List<String> getProvinces(List<Set<Population>> populations) {
  10. List<String> provinces = new ArrayList<>();
  11. for(Set<Population> population : populations) {
  12. provinces.add(getKeyOfValue(population));
  13. }
  14. return provinces;
  15. }
  16.  
  17. private String getKeyOfValue(Set<Population> population) {
  18. String key = null;
  19. for(Map.Entry<String, Set<Population>> entry : provincesAndPopulations.entrySet()) {
  20. if(population.equals(entry.getValue()))
  21. key = entry.getKey();
  22. }
  23. return key;
  24. }
  25.  
  26. private void sortPopulations(Set<Population> population, String provinceName, List<Set<Population>> sortedPopulations) {
  27. for (Population objPopulation : population) {
  28. if (objPopulation.getStateName().equals(provinceName)) {
  29. sortedPopulations.add(population);
  30. break;
  31. }
  32. }
  33. }
  34.  
  35. private void fillNewSortedProvincesAndPopulations(Map<String, Set<Population>> map,
  36. List<String> provinces, List<Set<Population>> populations) {
  37. for(byte i=0; i<provinces.size(); i++) {
  38. map.put(provinces.get(i), populations.get(i));
  39. }
  40. }


El método getKeyOfValue recibe un valor del Map y devuelve la llave (nombre de la provincia) asociada a dicho valor (Set<Population>). Aquí hacemos uso de equals() para comparar objetos.

Como comentario interesante, el método sort() de la clase Collections hace uso internamente de compareTo(). A éste método también le puedes pasar un objeto que implemente la interface Comparator<T> y que sobreescriba el método compare(), para que sort() ordene los elementos de la colección de acuerdo al método compare sobreescrito.



Prueba:

Código
  1. public static void main(String[] args) {
  2. PopulationService populationService = new PopulationService();
  3.  
  4. Population population = new PopulationImp("Leganes", 345, "Madrid");
  5. populationService.addProvinceAndPopulation("Madrid", population);
  6.  
  7. population = new PopulationImp("Ciutat Vella", 0, "Barcelona");
  8. populationService.addProvinceAndPopulation("Barcelona", population);
  9.  
  10. population = new PopulationImp("El ensanche", 0, "Barcelona");
  11. populationService.addPopulation("Barcelona", population);
  12.  
  13. population = new PopulationImp("La Zaidía", 345, "Valencia");
  14. populationService.addProvinceAndPopulation("Valencia", population);
  15.  
  16. population = new PopulationImp("Castilleja de campo", 120, "Sevilla");
  17. populationService.addProvinceAndPopulation("Sevilla", population);
  18.  
  19. System.out.println("\n*** Mostrando todas las provincias y sus poblaciones ***\n");
  20. populationService.showAll();
  21.  
  22. System.out.println("\n*** Mostrando lista después de ordenar... ***\n");
  23. Map<String, Set<Population>> sortedPopulations = populationService.sortBy(0);
  24. for(Map.Entry<String, Set<Population>> entry : sortedPopulations.entrySet()) {
  25. System.out.println("Provincia: "+entry.getKey()+"\n");
  26. for(Population pop : entry.getValue())
  27. System.out.println(pop);
  28. }
  29.  
  30. }

Resultado de ejecución:

Citar
*** Mostrando todas las provincias y sus poblaciones ***

Poblaciones del estado Sevilla:

Castilleja de campo
120
Sevilla


Poblaciones del estado Barcelona:

El ensanche
0
Barcelona

Ciutat Vella
0
Barcelona


Poblaciones del estado Madrid:

Leganes
345
Madrid


Poblaciones del estado Valencia:

La Zaidía
345
Valencia



*** Mostrando lista después de ordenar... ***

Provincia: Barcelona

Provincia interna: El ensanche
Something: 0
Estado: Barcelona

Provincia interna: Ciutat Vella
Something: 0
Estado: Barcelona

Provincia: Madrid

Provincia interna: Leganes
Something: 345
Estado: Madrid

Provincia: Sevilla

Provincia interna: Castilleja de campo
Something: 120
Estado: Sevilla

Provincia: Valencia

Provincia interna: La Zaidía
Something: 345
Estado: Valencia



El otro tipo de ordenar te lo dejo a ti. Por cierto, marca el otro tema como Solucionado para evitar confusiones. (http://i.imgur.com/oizldtf.png)

Salu2.


Título: Re: Utilizacion de CompareTo en objetos dentro de un Set
Publicado por: kikian94 en 12 Marzo 2015, 19:14 pm
muchas gracias, ya termine la primera practica ;)