Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java sort list of objects by specifiable attribute

I want to sort a List of objects by a specified attribute of those objects and I want to choose which attribute should be used for sorting. Example:

class Car{
  private String name;
  private String colour;
  public enum sortBy {NAME, COLOUR};

  public String name(){
    return name;
  }

  public String colour(){
    return colour;
  }

  public static Car[] getSortedArray(Car[] carArray, sortBy sortType){
    HashMap<Object, Car> carMap = new HashMap<Object, Car>();
    Object[] sortArray = new Object[carArray.length];
    Object value = null;
    for(int i = 0; i < carArray.length; i++){
      if(sortType == sortBy.NAME){
        value = carArray[i].name();
      }else if(sortType == sortBy.COLOUR){
        value = carArray[i].colour();
      }
      carMap.put(value, carArray[i]);
      sortArray[i] = value;
    }  
    Arrays.sort(sortArray);
    Car[] sortedArray = new Car[sortArray.length];
    for(int i = 0; i < sortArray.length; i++){
      sortedArray[i] = carMap.get(sortArray[i]);
    }
    return sortedArray;
  }
}

//external:
Car[] cars = getSomeCars();
Car[] nameSortedCars = Car.getSortedArray(cars, Car.sortBy.NAME);
Car[] colourSortedCars = Car.getSortedArray(cars, Car.sortBy.COLOUR);

The idea is simple:
I put all values that i want to sort by into an array, and i create a map that maps these values back to their objects. After I sorted this array I take the objects mapped to these values and put them in the same order into a new array which is then sorted by these values. The values are just created with type Object so I can sort by multiple types (not just Strings as in the example).

This works fine unless you have two objects with the same attribute value, then only one object will be in the returned array, but two times.
Is there a better way to achieve this sorting?

like image 579
jklmnn Avatar asked Sep 27 '26 08:09

jklmnn


1 Answers

It would be much simpler to use custom comparators:

To sort by name:

Arrays.sort(carArray, Comparator.comparing(Car::name));

To sort by colour:

Arrays.sort(carArray, Comparator.comparing(Car::colour));

So you could modify getSortedArray():

public static Car[] getSortedArray(Car[] carArray, Comparator<Car> comparator) {
    Car[] sorted = carArray.clone()
    Arrays.sort(sorted, comparator);
    return sorted;
}

And call it like this:

Car[] sorted = getSortedArray(carArray, Comparator.comparing(Car::name));

Edit:

If you use a language version that does not support these features, you can create the comparators by explicitly creating a nested class that implements the Comparator interface.

This, for example, is a singleton Comparator that compares Car instances by name:

static enum ByName implements Comparator<Car> {
    INSTANCE;

    @Override
    public int compare(Car c1, Car c2) {
        return c1.name().compareTo(c2.name());
    }
}

Then call:

Car[] sorted = getSortedArray(carArray, ByName.INSTANCE);
like image 92
Anderson Vieira Avatar answered Sep 30 '26 05:09

Anderson Vieira



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!