2010-09-13 8 views
7

Tengo una lista de matriz que contiene objetos Citar. Quiero poder ordenar alfabéticamente por nombre, por cambio y por cambio de porcentaje. ¿Cómo puedo ordenar mi lista de arrays?¿Cómo ordenar un ArrayList usando múltiples criterios de clasificación?

package org.stocktwits.model; 

import java.io.Serializable; 
import java.text.DecimalFormat; 

    public class Quote implements Serializable { 

     private static final long serialVersionUID = 1L; 

     public String symbol; 
     public String name; 
     public String change; 
     public String percentChange; 
     public String open; 
     public String daysHigh; 
     public String daysLow; 
     public String dividendYield; 
     public String volume; 
     public String averageDailyVolume; 
     public String peRatio; 
     public String marketCapitalization; 
     public String yearHigh; 
     public String yearLow; 
     public String lastTradePriceOnly; 
     public DecimalFormat df = new DecimalFormat("#,###,###,###,###,##0.00"); 
     public DecimalFormat vf = new DecimalFormat("#,###,###,###,###,##0"); 

     public String getSymbol() { 
      return symbol; 
     } 
     public void setSymbol(String symbol) { 
      this.symbol = symbol; 
     } 
     public String getName() { 
      return name; 
     } 
     public void setName(String name) { 
      this.name = name; 
     } 
     public String getChange() { 
      return change; 
     } 
     public void setChange(String change) { 
      if(change.equals("null")){ 
       this.change = "N/A"; 
      } 
      else{ 
       float floatedChange = Float.valueOf(change); 
       this.change = (df.format(floatedChange)); 
      } 
     } 
     public String getPercentChange() { 
      return percentChange; 
     } 
     public void setPercentChange(String percentChange) { 
      if(percentChange.equals("null")) 
       percentChange = "N/A"; 
      else 
       this.percentChange = percentChange; 
     } 
     public String getOpen() { 
      return open; 
     } 
     public void setOpen(String open) { 
      if(open.equals("null")) 
       this.open = "N/A"; 
      else 
       this.open = open; 
     } 
     public String getDaysHigh() { 
      return daysHigh; 
     } 
     public void setDaysHigh(String daysHigh) { 
      if(daysHigh.equals("null")) 
       this.daysHigh = "N/A"; 
      else{ 
       float floatedDaysHigh = Float.valueOf(daysHigh); 
       this.daysHigh = (df.format(floatedDaysHigh)); 
      } 
     } 
     public String getDaysLow() { 
      return daysLow; 
     } 
     public void setDaysLow(String daysLow) { 
      if(daysLow.equals("null")) 
       this.daysLow = "N/A"; 
      else{ 
       float floatedDaysLow = Float.valueOf(daysLow); 
       this.daysLow = (df.format(floatedDaysLow)); 
      } 
     } 
     public String getVolume() { 
      return volume; 
     } 
     public void setVolume(String volume) { 
      if(volume.equals("null")){ 
       this.volume = "N/A"; 
      } 
      else{ 
       float floatedVolume = Float.valueOf(volume); 
       this.volume = (vf.format(floatedVolume)); 
      } 
     } 
     public String getDividendYield() { 
      return dividendYield; 
     } 
     public void setDividendYield(String dividendYield) { 
      if(dividendYield.equals("null")) 
       this.dividendYield = "N/A"; 
      else 
       this.dividendYield = dividendYield; 
     } 
     public String getAverageDailyVolume() { 
      return averageDailyVolume; 
     } 
     public void setAverageDailyVolume(String averageDailyVolume) { 
      if(averageDailyVolume.equals("null")){ 
       this.averageDailyVolume = "N/A"; 
      } 
      else{ 
       float floatedAverageDailyVolume = Float.valueOf(averageDailyVolume); 
       this.averageDailyVolume = (vf.format(floatedAverageDailyVolume)); 
      } 
     } 
     public String getPeRatio() { 
      return peRatio; 
     } 
     public void setPeRatio(String peRatio) { 
      if(peRatio.equals("null")) 
       this.peRatio = "N/A"; 
       else 
      this.peRatio = peRatio; 
     } 
     public String getMarketCapitalization() { 
      return marketCapitalization; 
     } 
     public void setMarketCapitalization(String marketCapitalization) { 
      if(marketCapitalization.equals("null")) 
       this.marketCapitalization = "N/A"; 
      else 
       this.marketCapitalization = marketCapitalization; 
     } 
     public String getYearHigh() { 
      return yearHigh; 
     } 
     public void setYearHigh(String yearHigh) { 
      if(yearHigh.equals("null")) 
       this.yearHigh = "N/A"; 
      else 
       this.yearHigh = yearHigh; 
     } 
     public String getYearLow() { 
      return yearLow; 
     } 
     public void setYearLow(String yearLow) { 
      if(yearLow.equals("null")) 
       this.yearLow = "N/A"; 
      else 
       this.yearLow = yearLow; 
     } 

     public String getLastTradePriceOnly() { 
      return lastTradePriceOnly; 
     } 

     public void setLastTradePriceOnly(String lastTradePriceOnly) { 
      if(lastTradePriceOnly.equals("null")){ 
       this.lastTradePriceOnly = "N/A"; 
      } 
      else{ 
       float floatedLastTradePriceOnly = Float.valueOf(lastTradePriceOnly); 
       this.lastTradePriceOnly = (df.format(floatedLastTradePriceOnly)); 
      } 
     } 

     @Override 
     public int hashCode() { 
      final int prime = 31; 
      int result = 1; 
      result = prime * result + ((change == null) ? 0 : change.hashCode()); 
      result = prime * result 
        + ((daysHigh == null) ? 0 : daysHigh.hashCode()); 
      result = prime * result + ((daysLow == null) ? 0 : daysLow.hashCode()); 
      result = prime 
        * result 
        + ((lastTradePriceOnly == null) ? 0 : lastTradePriceOnly 
          .hashCode()); 
      result = prime 
        * result 
        + ((marketCapitalization == null) ? 0 : marketCapitalization 
          .hashCode()); 
      result = prime * result + ((name == null) ? 0 : name.hashCode()); 
      result = prime * result + ((open == null) ? 0 : open.hashCode()); 
      result = prime * result + ((peRatio == null) ? 0 : peRatio.hashCode()); 
      result = prime * result 
        + ((percentChange == null) ? 0 : percentChange.hashCode()); 
      result = prime * result + ((symbol == null) ? 0 : symbol.hashCode()); 
      result = prime * result + ((volume == null) ? 0 : volume.hashCode()); 
      result = prime * result 
        + ((yearHigh == null) ? 0 : yearHigh.hashCode()); 
      result = prime * result + ((yearLow == null) ? 0 : yearLow.hashCode()); 
      return result; 
     } 
     @Override 
     public boolean equals(Object obj) { 
      if (this == obj) 
       return true; 
      if (obj == null) 
       return false; 
      if (getClass() != obj.getClass()) 
       return false; 
      Quote other = (Quote) obj; 
      if (change == null) { 
       if (other.change != null) 
        return false; 
      } else if (!change.equals(other.change)) 
       return false; 
      if (daysHigh == null) { 
       if (other.daysHigh != null) 
        return false; 
      } else if (!daysHigh.equals(other.daysHigh)) 
       return false; 
      if (daysLow == null) { 
       if (other.daysLow != null) 
        return false; 
      } else if (!daysLow.equals(other.daysLow)) 
       return false; 
      if (lastTradePriceOnly == null) { 
       if (other.lastTradePriceOnly != null) 
        return false; 
      } else if (!lastTradePriceOnly.equals(other.lastTradePriceOnly)) 
       return false; 
      if (marketCapitalization == null) { 
       if (other.marketCapitalization != null) 
        return false; 
      } else if (!marketCapitalization.equals(other.marketCapitalization)) 
       return false; 
      if (name == null) { 
       if (other.name != null) 
        return false; 
      } else if (!name.equals(other.name)) 
       return false; 
      if (open == null) { 
       if (other.open != null) 
        return false; 
      } else if (!open.equals(other.open)) 
       return false; 
      if (peRatio == null) { 
       if (other.peRatio != null) 
        return false; 
      } else if (!peRatio.equals(other.peRatio)) 
       return false; 
      if (percentChange == null) { 
       if (other.percentChange != null) 
        return false; 
      } else if (!percentChange.equals(other.percentChange)) 
       return false; 
      if (symbol == null) { 
       if (other.symbol != null) 
        return false; 
      } else if (!symbol.equals(other.symbol)) 
       return false; 
      if (volume == null) { 
       if (other.volume != null) 
        return false; 
      } else if (!volume.equals(other.volume)) 
       return false; 
      if (yearHigh == null) { 
       if (other.yearHigh != null) 
        return false; 
      } else if (!yearHigh.equals(other.yearHigh)) 
       return false; 
      if (yearLow == null) { 
       if (other.yearLow != null) 
        return false; 
      } else if (!yearLow.equals(other.yearLow)) 
       return false; 
      return true; 
     } 
    } 
+0

Realmente odio clases como esta. Las clases deben tener una lógica comercial real que valga la pena. Prefiero usar algo como el hash para cosas como esta. A la larga, usar una clase como una bolsa de atributos simplemente se vuelve molesto. La repetición debería mostrar que obviamente está mal. Algunas personas toman esto como una falla de Java, tiendo a pensar que es más culpa de los programadores no estar dispuestos a diversificarse. Hice esto de forma que permitió la validación, el tipo de seguridad y muchos otros trucos. No hay un código repetitivo, pero fue mucho trabajo, aunque vale la pena, la repetición es una mierda. –

+6

no estoy seguro Estoy completamente de acuerdo, pero una cosa me destaca: ¡existen todos estos métodos setter y getter, pero los campos que obtienen/configuran son todos públicos! Esos deben ser privados. –

Respuesta

9

Cree un apropiado Comparator que comparará dos elementos de acuerdo con sus criterios deseados. Luego use Collections.sort() en su ArrayList.

Si más tarde desea ordenar por diferentes criterios, llame de nuevo Collections.sort() con un Comparator diferente.

+0

¿Puede darnos un ejemplo de cómo puede ser mi método compare()? –

+0

@Sheehan La documentación explica el contrato. Depende de usted determinar el orden. Piense que es como buscar un libro en la biblioteca, p. primero vaya a la sección "Ficción" o "No Ficción", luego busque el número completo, luego la parte después del decimal ... p. primero se comparan las cosas "más importantes" y se siguen estrechando.Si una parte más significativa es más que otra, entonces eso termina el pedido (ya que ya ha encontrado el mejor pedido). –

+0

Esta respuesta no funciona para mí, tengo dos columnas, en primer lugar me gustaría clase ArrayList basado en columnas, una tras lo que me gustaría especie de columnas dos, pero no es el trabajo correctamente y mi ArrayList ordenados en columnas de dos Totaly! –

2

Consulte Collections.sort con un comparador explícito (o el tipo Collections.sort que requiere la entrada para implementar Comparable, si lo prefiere).

28

Si (casi) siempre quiere usar ese orden, puede agregar la interfaz Comparable para Citar e implementar un método compareTo.

public int compareTo(Quote quote) { 
    int result = this.getName().compareTo(quote.getName()); 
    if (result == 0) { 
     result = this.getChange().compareTo(quote.getChange()); 
    } 
    if (result == 0) { 
     result = this.getPercentChange().compareTo(quote.getPercentChange()); 
    } 
    return result; 
} 

Luego use una colección ordenada, ordene una lista, y las citas serán ordenadas.

Para la clasificación ad hoc, un Comparador separado, posiblemente anónimo, es mejor.

+1

para "Para la clasificación ad hoc, un Comparador separado, posiblemente anónimo, es mejor". 1 – user3437460

14

Todo el mundo está de acuerdo en que quiere usar comparadores. Extendiéndose sobre esa idea, si usted quiere ser capaz de ordenar de varios criterios, a continuación, una clase como esto va a funcionar para usted:

public class MultiComparator<T> implements Comparator<T> { 
    private List<Comparator<T>> comparators; 

    public MultiComparator(List<Comparator<T>> comparators) { 
     this.comparators = comparators; 
    } 

    public int compare(T o1, T o2) { 
     for (Comparator<T> comparator : comparators) { 
      int comparison = comparator.compare(o1, o2); 
      if (comparison != 0) return comparison; 
     } 
     return 0; 
    } 
} 

A continuación, sólo escribir comparadores muy simple para cualquiera que los campos que desee y se pueden combinar en comparadores más complejos más fácilmente y con más reutilización.

+0

Si hay una gran cantidad de comparaciones a realizar y el rendimiento es un problema, la Lista privada > podría ser almacenada como una matriz Comparador [] (se establece una vez en el constructor, nunca se altera, y nunca leer por clientes) - por lo menos hacer que sea final. –

+0

De acuerdo, o tal vez la clase podría ser definitiva. Simplemente escribí eso fríamente para demostrar la idea. Realmente debería haber algo así en el JDK, y me sorprendería que no estuviera en una serie de bibliotecas de colecciones ... – romacafe

+0

¿Cuál sería la complejidad de este tipo de encadenamiento de comparadores? ¿Estamos esencialmente ordenando cada vez que encadenamos los comparadores? Entonces, ¿hacemos una operación n * log (n) para cada comparador? –

11

Eche un vistazo a la ComparatorChain de la Colección Apache Commons. Esto debería hacer el trabajo. No implemente la lógica si ya está disponible y probada.
En el siguiente sitio tengo un tutorial: Sorting Objects By Multiple Attributes"

+0

1 Gracias por esto. el tener que recurrir a una biblioteca de terceros para esto es mi humilde opinión, una gran deficiencia del lenguaje de programación Java. Estoy de acuerdo con strangeoptics, no lanzar su propia aplicación cuando hay es una biblioteca que puede hacerlo. Enlace directo a la clase libre de comparación ComparatorChain: http://www.jarvana.com/jarvana/view/commons-collections/commons-collections/3.2.1/commons-collections-3.2.1 -sources.jar! /org/apache/commons/collections/comparators/ComparatorChain.java – Moritz

+0

Gracias por salir ejemplo de código para demostrar el concepto. Esto (combinado con su artículo) es una excelente respuesta a la pregunta OP. –

Cuestiones relacionadas