Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
783 views
in Technique[技术] by (71.8m points)

arrays - 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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...