How to sort an ArrayList using multiple sorting criteria?

60,150

Solution 1

Create an appropiate Comparator that will compare two items according to your desired criteria. Then use Collections.sort() on your ArrayList.

If at a later time you want to sort by different criteria, call Collections.sort() again with a different Comparator.

Solution 2

If you (almost) always want to use that order you can add the Comparable interface to Quote and implement a compareTo method.

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

Then use a sorted collection, or sort a list, and the quotes will be sorted.

For ad hoc sorting, a separate, possibly anonymous, Comparator is better.

Solution 3

Everybody is right that you want to use Comparators. Extending on that idea, if you want to be able to sort on multiple criteria, then a class like this will work for you:

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

Then you just write really simple comparators for whichever fields you desire and you can combine them into more complex comparators more easily and with more reuse.

Solution 4

Have a look at the ComparatorChain from the Apache Commons Collection. This should do the job. Don't implement logic if is already available and tested.
At the following site I have a tutorial: Sorting Objects By Multiple Attributes"

Solution 5

Sun has devoted big part of its tutorial to sorting in Java collections:
http://download.oracle.com/javase/tutorial/collections/interfaces/order.html

It discusses both Comparable and Comparator interfaces with examples.

Share:
60,150
Sheehan Alam
Author by

Sheehan Alam

iOS, Android and Mac Developer. i can divide by zero.

Updated on July 09, 2022

Comments

  • Sheehan Alam
    Sheehan Alam almost 2 years

    I have an array list that contains Quote objects. I want to be able to sort alphabetically by name, by change, and by percent change. How can I sort my arraylist?

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