【问题标题】:Find the highest value in a HashSet/ArrayList by a specific object attribute通过特定对象属性查找 HashSet/ArrayList 中的最大值
【发布时间】:2013-04-19 00:26:21
【问题描述】:

我有一个汽车对象列表。每个汽车对象都有一个类型,指示它是轿车、suv、双门轿车、面包车还是卡车)以及其他属性。假设我的应用程序按下面列出的顺序排列这些

  • 轿车(最低)
  • 双门轿车
  • SUV
  • 卡车(最高)

如何从列表中找到排名最高的类型。

class Car {

 public Car (String type, String model, int year, long mileage){
     this.type=type;
     this.model = model;
     this.year = year;
     this.mileage = mileage;
 }

  private String type; // Sedan, SUV etc
  private String model; // Focus, Corolla, Camry, Taurus etc
  private int year; 
  private long mileage;

 //getters

}

List<Car> allCars = new ArrayList();
allCars.add(new Car("Coupe", "Focus", 1999, 50000) );
allCars.add(new Car("Sedan", "Camry", 2007, 60000) );
allCars.add(new Car("Truck", "Sierra", 2007, 50000) );
allCars.add(new Car("Truck", "F-150", 2001, 60000) );
allCars.add(new Car("Van", "Sienna", 1999, 40000) );

在 Java 5 中找到卡车(具有最高排名类型的汽车)的最有效方法是什么。如果需要,我可以使用 apache commons api 或 guava。

我可以循环并创建一组独特的类型。

 Set<String> uniqueTypes = new HashSet<String>;
 for(Car car: allCars) {
     uniqueTypes.add(car.getType);
 }

使用上面的集合,我怎样才能找到最大值(即本例中的卡车)。 Collections.max() 会按自然顺序返回最大值吗?

【问题讨论】:

  • type 设为enum
  • 您需要使用max 方法和Comparator 并告诉它如何订购商品。

标签: java collections guava apache-commons


【解决方案1】:

首先,将汽车的类型设置为 enum 会有所帮助 - 这使您可以更轻松地对值进行排序,并为 Car 类添加类型安全性。

下一步是使用Collections中的max(Collection&lt;? extends T&gt; coll, Comparator&lt;? super T&gt; comp)方法。

当您有两辆相同类型的汽车时,您需要决定如何对其他值进行排序。默认实现将返回它遇到的第一个最大值。如果类型相同,您可能希望对模型进行二次排序。

这是一个例子:

public static void main(String[] args) throws ParseException {
    List<Car> allCars = new ArrayList();
    allCars.add(new Car(CarType.COUPE, "Focus", 1999, 50000));
    allCars.add(new Car(CarType.SEDAN, "Camry", 2007, 60000));
    allCars.add(new Car(CarType.TRUCK, "Sierra", 2007, 50000));
    allCars.add(new Car(CarType.TRUCK, "F-150", 2001, 60000));
    allCars.add(new Car(CarType.VAN, "Sienna", 1999, 40000));

    Car max = Collections.max(allCars, new Comparator<Car>() {
        @Override
        public int compare(Car o1, Car o2) {
            return o1.getType().compareTo(o2.getType());
        }
    });
    System.out.println(max);
}

static class Car {

    public static enum CarType {

        SEDAN,
        COUPE,
        VAN,
        SUV,
        TRUCK;
    }
    private CarType type;
    private String model; // Focus, Corolla, Camry, Taurus etc
    private int year;
    private long mileage;

    public Car(CarType type, String model, int year, long mileage) {
        this.type = type;
        this.model = model;
        this.year = year;
        this.mileage = mileage;
    }
    //getters
    //toString
}

在这种情况下,max 是“Sierra”,因为它是列表中的第一辆卡车。

或者,您可以使用SortedSetTreeSet,但是在实施Comparator 时您需要非常小心,因为它需要是consistent with equals 否则项目排名相同但不是equals 将被忽略。

编辑

在内部使用enum 但在构造函数中使用String 的示例:

static class Car {

    public static enum CarType {

        Sedan,
        Coupe,
        Van,
        SUV,
        Truck;
    }
    private CarType type;
    private String model; // Focus, Corolla, Camry, Taurus etc
    private int year;
    private long mileage;

    public Car(String type, String model, int year, long mileage) {
        this.type = CarType.valueOf(type);
        this.model = model;
        this.year = year;
        this.mileage = mileage;
    }
    //getters
    //toString
}

【讨论】:

  • 感谢@bmorris591 的示例。就我而言,CarTypes 是许多 API 使用的现有对象,将它们转换为 Enums 可能并非易事。但是,即使使用枚举,您在哪里指定顺序(VAN 的排名高于 COUPE、SEDAN 或 TRUCK 高于其他所有)。
  • 您可以在内部使用CarType.valueOf(String) 将其设为enum,以将传入的String 解析为CarType。当枚举被声明时,它们被分配一个索引,这个索引是它们的自然顺序——所以它们被声明的顺序就是它们的排序顺序。也许阅读this
【解决方案2】:

虽然引入 CarType 枚举是一个很好的方法,但如果您不能/不想将类型更改为字符串,您可以使用 Guava 的 Ordering,它更强大且更流畅的 Comparator API。在你的情况下使用Ordering#explicit(T, T...):

final Car maxRank = Ordering.explicit("Sedan", "Coupe", "Van", "SUV", "Truck")
    .onResultOf(CarFunction.GET_TYPE)
    .max(allCars);
System.out.println(maxRank.getModel()); // Sierra

其中CarFunction.GET_TYPE 定义为:

private enum CarFunction implements Function<Car, String> {
  GET_TYPE {
    @Override
    public String apply(final Car car) {
      return car.getType();
    }
  };
}

private static final Function 或在 Java 8 中为 lambda c -&gt; c.getType()

您可以在this Wiki page 上阅读有关订购的更多信息。

【讨论】:

    猜你喜欢
    • 2018-07-09
    • 2013-07-05
    • 2017-05-10
    • 2016-07-26
    • 1970-01-01
    • 2022-07-08
    • 1970-01-01
    • 2019-09-14
    相关资源
    最近更新 更多