如何对自定义实体的集合进行排序?

时间:2014-06-27 14:52:19

标签: java collections

我有一个自定义实体列表,我需要按此顺序排序:valueOne,valueTwo和valueThree。

这是我的代码

public class AppRunner {
    public static void main(String[] args) {

        Detail d1 = new Detail("valueOne");
        Detail d2 = new Detail("valueTwo");
        Detail d3 = new Detail("valueFive");
        Detail d4 = new Detail("valueTen");
        Detail d5 = new Detail("valueOne");
        Detail d6 = new Detail("valueOne");

        List<Detail> details = new ArrayList<Detail>(Arrays.asList(d1, d2, d3, d4, d5, d6));

        Collections.sort(details);
        System.out.println(details);
    }
}

我的实体类

public class Detail implements Comparable<Detail> {

    private String value; // there are three options: valueOne, valueTwo, and some other value

    public Detail(String value) {
        this.value = value;
    }

    @Override
    public int compareTo(Detail detail) {
        String val = detail.getValue();
        if (val.equals(this.value) && val.equals("valueOne")) {
            return 1;
        } else if (val.equals(this.value) && val.equals("valueTwo")) {
            return -1;
        } else {
            return 0;
        }
    }
    // getter, setters, toString
}

我认为需要compareTo方法的帮助。最后,我需要按此顺序获取列表:

  1. valueOne
  2. valueOne
  3. valueOne
  4. valueTwo
  5. valueFive

3 个答案:

答案 0 :(得分:3)

使用枚举并比较序数:

enum ValidValues { valueOne, valueTwo, valueThree }

......然后:

public int compareTo(Object detail) {
    return Integer.compare(ValidValues.valueOf(this.value).ordinal(),
                           ValidValues.valueOf(((Detail)detail).value).ordinal());
}

对于更多的值,使用集合或映射而不是枚举来执行此操作可能是值得的。

答案 1 :(得分:0)

最后请注意可能更好的设计。

我建议在Detail类中添加另一个字段,在所需的排序顺序和value上填充该字段,并使用此字段进行排序。

public class Detail implements Comparable<Detail> {

    private String value;
    private int sortOrder;

    public Detail(String value) {
        this.value = value;
        if(value.equals("valueOne") {
            sortOrder = 1;
        }
        if(value.equals("valueTwo") {
            sortOrder = 2;
        }
        ...
        ...
    }

这使compareTo变得简单:

public int compareTo(Detail detail) {
    if(this.sortOrder < detail.sortOrder) {
        return -1;
    }
    if(this.sortOrder == detail.sortOrder) {
        return 0;
    }
    if(this.sortOrder > detail.sortOrder) {
        return 1;
    }
}

注意: 以上是您现有问题的解决方案。但是,您可能有更好的选择。如果您使用详细信息来重新定义一组固定值,请查看Enums。 Java中的Enum非常强大且功能多样。您可以让enum代表一组固定的值并使用Detail类中的枚举。

如果您可能拥有一组未预定义的大量值,则可以使用Map将排序顺序与值进行映射。

private static Map<Int, String> sortOrder = new HashMap<Int, String>();

sortOrder.put(1, "valueOne");
...

并使用此地图排序。根据您的具体情况,您可以从数据库,初始化文件或仅运行时间点来映射此映射。

答案 2 :(得分:0)

你可以有一个简单的getter,它根据你的String值返回一个数值,并简单地返回compare()方法中两个数值的差值(请记住compare()如果两个都应返回0对象是等于的,请参阅Comparable javadoc。

public static class Detail implements Comparable<Detail> {

    private String value; // there are three options: valueOne, valueTwo, and some other value

    public Detail(String value) {
        this.value = value;
    }

    @Override
    public int compareTo(Detail detail) {
        return this.getNumericValue() - detail.getNumericValue();
    }

    private int getNumericValue() {
        switch (this.value) {
            case "valueOne": return 1;
            case "valueTwo": return 2;
            default: return 3;
        }
    }

}