java按可指定属性对对象进行排序

java按可指定属性对对象进行排序,java,arrays,sorting,Java,Arrays,Sorting,我想按对象的指定属性对对象列表进行排序,并选择应使用哪个属性进行排序。例如: 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 Ca

我想按对象的指定属性对对象列表进行排序,并选择应使用哪个属性进行排序。例如:

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);
等级车{
私有字符串名称;
私人弦色;
公共枚举排序{名称,颜色};
公共字符串名称(){
返回名称;
}
公共字符串颜色(){
返色;
}
公共静态车辆[]GetSortDarray(车辆[]carArray,sortBy sortType){
HashMap carMap=新的HashMap();
Object[]sortArray=新对象[carArray.length];
对象值=空;
对于(int i=0;i
想法很简单:
我将所有要排序的值放入一个数组,然后创建一个映射,将这些值映射回它们的对象。在对这个数组进行排序之后,我将映射到这些值的对象按照相同的顺序放入一个新数组中,然后按这些值进行排序。这些值是用type对象创建的,因此我可以按多种类型(而不仅仅是示例中的字符串)排序

除非有两个具有相同属性值的对象,否则返回的数组中只会有一个对象,但会有两次。

有没有更好的方法来实现这种排序

使用自定义比较器要简单得多:

要按
名称排序

Arrays.sort(carArray, Comparator.comparing(Car::name));
static enum ByName implements Comparator<Car> {
    INSTANCE;

    @Override
    public int compare(Car c1, Car c2) {
        return c1.name().compareTo(c2.name());
    }
}
要按
颜色排序

Arrays.sort(carArray, Comparator.comparing(Car::colour));
因此,您可以修改
GetSorterDarray()

编辑:

如果使用的语言版本不支持这些功能,则可以通过显式创建实现
Comparator
接口的嵌套类来创建比较器

例如,这是一个单例
比较器
,它通过
name
比较
Car
实例:

Arrays.sort(carArray, Comparator.comparing(Car::name));
static enum ByName implements Comparator<Car> {
    INSTANCE;

    @Override
    public int compare(Car c1, Car c2) {
        return c1.name().compareTo(c2.name());
    }
}
TL;医生:已经有一个轮子了。 我想说,最简单的方法是创建一个比较器:

final Comparator<Car> byName = Comparator.comparing(Car::name);
final Comparator<Car> byColour = Comparator.comparing(Car::colour);
Arrays.sort(carArray, byName);
现在,您想使用
枚举执行此操作吗?只需让
枚举
实现比较器

是否要按名称反向排序?简单:

final Comparator<Car> byName = SortBy.NAME.reversed();
final Comparator byName=SortBy.NAME.reversed();

你在重新发明轮子!如果您使用模板化的集合API,您的生活将更加轻松。要做到这一点,您需要使用列表而不是数组,定义一个比较器来进行排序,然后让API为您完成这项工作

 Comparator<Car> carComparator = new Comparator<Car>(){
    public int sort(Car car1, Car car2){
      //Sorting logic goes here.
    }
 }
 List<Car> cars = getCars();
 cars = Collections.sort(cars, carComparator); //the cars collection is now sorted.
比较器carComparator=新比较器(){ 公共整数排序(car1、car2){ //排序逻辑在这里。 } } 列出汽车=获取汽车(); cars=集合。排序(cars、carComparator)//汽车收藏现已分类。
如果您有时想按一个或另一个属性进行排序,可以将我的变量carComparator放入它自己的类中,并在构造函数中定义要按哪些属性进行排序

希望有帮助:)


编辑:正如其他人指出的,这种方法也适用于数组。但是,除非您有充分的理由使用数组,否则使用集合通常会更容易。

我认为如果您将Comparator实现传递给Arrays.sort,那么解决方案会更有效。现在,从外观上看,您正在循环n*2,哈希映射(O(1))加上array.sort(这是另一个0(n logn)或类似的值)。如果执行以下操作,则可以跳过当前使用的2个循环和贴图

您只需创建一个比较器,如(粗略代码):

,或者使用更专业的比较器类,每个属性一个,并使用工厂来呈现它们,当然,如果经常发生这种情况,请不要为每个排序创建新的比较器()

总的来说,这种方法应该使您的代码更高效。
}

问题是,HashMap不接受重复的密钥,那么如果你有两个具有相同密钥的对象,那么第二个对象将超速驱动第一个对象。这看起来可以解决我的问题,但在Android上似乎不起作用。我将Java 8作为JDK应用于AndroidStudio,但它似乎不知道Comparator.Comparating和Car::name给了我一个错误,即在此语言级别不支持方法引用。@jklmnn我更新了答案。这应该适用于较旧的Java版本。好吧,这似乎是Android的问题,我用car类创建了一个小测试,结果成功了。谢谢
final Comparator<Car> byName = SortBy.NAME.thenComparing(SortBy.COLOUR);
final Comparator<Car> byName = SortBy.NAME.reversed();
 Comparator<Car> carComparator = new Comparator<Car>(){
    public int sort(Car car1, Car car2){
      //Sorting logic goes here.
    }
 }
 List<Car> cars = getCars();
 cars = Collections.sort(cars, carComparator); //the cars collection is now sorted.
class CarComparator implements Comparator<Car> {
    enum compareType; //plus setter

    public int compareTo(Car a, Car b) {
        if(compareType == COLOUR) return a.colour.compareTo(b.colour);
        if(compareType == NAME.....
    }
}
Arrays.sort(cars, new CarComparator(COLOUR))