如何对对象列表进行排序

时间:2014-12-21 14:46:00

标签: java collections

假设我有一个Test列表如下:

    public class Test {
    public static enum Unit {
        DAY, WEEK, MONTH, YEAR /* , DAY_TO_DAY */
    }

    private int value;
    private Unit unit;
    public int getValue() {
        return value;
    }
    public void setValue(int value) {
        this.value = value;
    }
    public Unit getUnit() {
        return unit;
    }
    public void setUnit(Unit unit) {
        this.unit = unit;
    }
}

我将有一个带有以下值的Test列表:

3天,  5个月,  5天,  6年了  6周,  12周,

和我们的预期结果如下:

3天,5天,6周,12周,5个月,6年

目前,我创建了一个代码,如下所示

Collections.sort(tests, new Comparator<Test >() {
  @Override
  public int compare(Test o1, Test o2) {
    if(o1.getValue() > o2.getValue()) return 1;
    if(o1.getValue() < o2.getValue()) return -1;
    return 0;
  }

但是,它只按值而非按单位排序。 上述实现的结果是:

3天,5天,5个月,6周,6年,12周。

请告诉我在这种情况下满足两个条件(单位和值)的方法。 感谢。

6 个答案:

答案 0 :(得分:5)

您需要先转换为通用格式,然后进行比较。由于天是最小的类型,您应该将您比较的两个实例转换为若干天,然后根据它进行比较。

但你首先要做一些消歧。一个月多久了?它是否超过30天,或更短,或相同?

答案 1 :(得分:1)

如果您只是想根据您的示例进行比较,以下代码可以解决问题:

Collections.sort(terms, new Comparator<Test>() {
    @Override
    public int compare(final Test o1, final Test o2) {
        int unitCompare = o1.getUnit().compareTo(o2.getUnit());
        if (unitCompare == 0) {
            return o1.getValue() - o2.getValue();
        }
        return unitCompare;
    }
});

但是,此代码确实 NOT 因素可能会有不同的长度,而代码确实 NOT 因为35天的时间长于一个月。

为了做到这一点,我建议使用java.time包中的类(例如java.time.Period)进行适当的比较(可以找到一条很好的路径来了解这一点{{3 }})。如果Java 8不是选项here提供相同类型的功能。

答案 2 :(得分:1)

首先必须检查Unit,然后根据重写的compareTo()中的Value进行检查。在这里看到基于姓氏的排序实现,然后是名字:http://docs.oracle.com/javase/tutorial/collections/interfaces/order.html

答案 3 :(得分:1)

使用TimeUnit替换您的Unit枚举。

因此,您的Term课程可以使用.toMillis()方法,这非常简单:

public final long toMillis()
{
    return timeUnit.toMillis(value);
}

然后,您可以Long.compare(o1.toMillis(), o2.toMillis())中的Comparator

其他解决方案:

  • 如果您使用Java 8,请使用新的日期/时间API;
  • 如果您使用Java 7-和threetenbp,请使用相同的方法,backported;
  • 如果您使用Java 7和Joda Time,请使用Period。它几乎相当于Java 8 / threetenbp的。

答案 4 :(得分:0)

如果您真的想这样做,请分配您的枚举值,如下所示: 第(1)周,第7周,每月(31),年(365)

比你的comperator倍增 Unit.getValue()* value

e.g。 4个月给你31 * 4 = 124大于100天。

仍然存在问题,即teher是少于31天的月份。建议转换为一些常见日期单位,例如joda时间。

答案 5 :(得分:0)

请使用compareto功能,如下所示:

public int compareTo(Object o) {
        Test t1 = (Test)this;
        Test t2 = (Test)o;
        if(t1.getValue()*(t1.getUnit().getValue()+1) > t2.getValue()*(t2.getUnit().getValue()+1)) return 1;
        if(t1.getValue()*(t1.getUnit().getValue()+1) < t2.getValue()*(t2.getUnit().getValue()+1)) return -1;
        return 0;
    }

并将枚举更改为

 public static enum Unit {
    DAY(1), WEEK(7), MONTH(31), YEAR(365) ;/* , DAY_TO_DAY */
        private final int id;
        Unit(int id) { this.id = id; }
    public int getValue() { return id; }
    }

现在使用collection.sort(),它将自动排序