通过特定对象属性在HashSet / ArrayList中查找最高值

时间:2013-04-19 00:26:22

标签: java collections guava apache-commons

我有一个Car对象列表。每个汽车对象都有一个类型,表明它是轿车,轿车,轿跑车,货车还是卡车)以及其他属性。假设我的应用程序按照下面列出的顺序排列

  • 轿车(最低)
  • 跑车
  • 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中找到Truck(排名最高的汽车)的最有效方法是什么。如果需要,我可以使用apache commons api或guava。

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

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

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

2 个答案:

答案 0 :(得分:2)

首先,它有助于使汽车类型为enum - 这使您可以更轻松地对值进行排序,并为Car类添加类型安全性。

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

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

以下是一个例子:

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”,因为它是列表中的第一辆卡车。

或者您可以像SortedSet一样使用TreeSet,但是您需要非常小心来实施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
}

答案 1 :(得分:2)

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

Comparator

其中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(); } }; } 或在Java 8中作为lambda private static final Function

您可以在this Wiki page上阅读有关订购的详情。