基于单独列表排序列表

时间:2014-07-25 23:55:17

标签: java sorting

我有一个带有方法getPriority()的对象列表,它返回字符串中的对象优先级,以及返回对象名称(也是字符串)的方法getName()。我有一个列表,' priority',其中包含类似' high' '介质'和'低'。

我想按顺序列表中getPriority()方法的位置来排序对象列表,对于具有相同优先级或没有优先级的对象,然后根据名称按字母顺序排序。

例如:

    List<MyObject> objects = new ArrayList<MyObject>();
    objects.add(new MyObject("apple", "low"));
    objects.add(new MyObject("bacon", "medium"));
    objects.add(new MyObject("cheese", "low"));
    objects.add(new MyObject("doughnut", "high"));
    objects.add(new MyObject("eggs", null));
    objects.add(new MyObject("fudge", null));

    List<String> priority = new ArrayList<String>();
    priority.add("high");
    priority.add("medium");
    priority.add("low");

将分类为:甜甜圈,培根,苹果,奶酪,鸡蛋,软糖。

重要的是不要使用枚举作为优先级,因为它需要由最终用户自定义。它还需要接受空优先级,因为从数据库中获取优先级,如果在数据库中找不到对象仍然需要进行排序。

3 个答案:

答案 0 :(得分:2)

添加一个新的比较器类来对对象进行排序,定义如下:

class MyObjectPrioritizer extends Comparator<MyObject> {
    List<String> priority;

    MyObjectPrioritizer(List<String> priorityOrder) {
        priority = priorityOrder;
    }

    public int compare(MyObject o1, MyObject o2) {
        int v1 = resolveValue(o1);
        int v2 = resolveValue(o2);
        return v1 - v2;
    }

    int resolveValue(MyObject o) {
        int sort = priority.indexOf(o.priority));
        // put null & unknown values at the end
        if (sort == -1) sort = Integer.MAX_VALUE;
        return sort;
    }
}

然后只是:

Collections.sort(objects, new MyObjectPrioritizer(priority));

答案 1 :(得分:1)

您可以使用比较器对列表进行排序。 e.g:

<强>代码

List<MyObject> objects = new ArrayList<MyObject>();
objects.add(new MyObject("apple", "low"));
objects.add(new MyObject("bacon", "medium"));
objects.add(new MyObject("cheese", "low"));
objects.add(new MyObject("doughnut", "high"));
objects.add(new MyObject("eggs", null));
objects.add(new MyObject("fudge", null));

final List<String> priority = new ArrayList<String>();
priority.add("high");
priority.add("medium");
priority.add("low");

Comparator<MyObject> comparator = new Comparator<MyObject>() {
    public int compare(MyObject o1, MyObject o2) {
        int p1 = priority.indexOf(o1.getPriority());
        int p2 = priority.indexOf(o2.getPriority());
        if (p1 == -1 && p2 != -1) {
            return 1;
        }
        if (p1 != -1 && p2 == -1) {
            return -1;
        }
        if (p1 != p2) {
            return p1 - p2;
        }
        return o1.getName().compareTo(o2.getName());
    }
};

Collections.sort(objects, comparator);

for(MyObject obj : objects) {
    System.out.printf("%-10s %10s%n", obj.getName(), obj.getPriority());
}

<强>输出

doughnut         high
bacon          medium
apple             low
cheese            low
eggs             null
fudge            null

答案 2 :(得分:0)

我建议使用Guava Ordering

使用Ordering.explicit可以让我们按照它们在列表中显示的顺序进行比较。

为了按优先级排序对象按名称排序,这两个排序与Ordering.thenComparing一起组成。

// Sorts MyObject by name
public static final Ordering<MyObject> MY_OBJECT_FOOD_ORDERING = new Ordering<MyObject>() {

    @Override
    public int compare(final MyObject left, final MyObject right) {

        return ComparisonChain.start()
                .compare(left == null ? null : left.getName(), right == null ? null : right.getName())
                .result();
    }
};

public static final Ordering<MyObject> buildPriorityOrdering(final List<String> priorities) {

    return buildPriorityOrdering(Ordering.explicit(ImmutableList.<String> builder()
            .addAll(priorities)
            .build())
        .nullsLast());
}

public static final Ordering<MyObject> buildPriorityOrdering(final Ordering<String> priorityOrdering) {
    return new Ordering<ListOrdering.MyObject>() {

        @Override
        public int compare(final MyObject left, final MyObject right) {

            return ComparisonChain.start()
                .compare(left == null ? null : left.getPriority(), right == null ? null : right.getPriority(),
                        priorityOrdering)
                .result();
        }
    };
}

public static void main(final String... args) {

    final List<String> priorities = ImmutableList.<String> builder()
            .add("high")
            .add("medium")
            .add("low")
            .build();

    final List<MyObject> myObjects = ImmutableList.<MyObject> builder()
            .add(new MyObject("doughnut", "high"))
            .add(new MyObject("cheese", "low"))
            .add(new MyObject("eggs", null))
            .add(new MyObject("apple", "low"))
            .add(new MyObject("fudge", null))
            .add(new MyObject("bacon", "medium"))
            .build();

    final List<MyObject> myObjectsSorted = FluentIterable.from(myObjects)
            .toSortedList(buildPriorityOrdering(priorities).thenComparing(MY_OBJECT_FOOD_ORDERING));

    /*
     * Results: 
     * MyObject [name=doughnut, priority=high] 
     * MyObject [name=bacon, priority=medium] 
     * MyObject [name=apple, priority=low] 
     * MyObject [name=cheese, priority=low] 
     * MyObject [name=eggs, priority=null] 
     * MyObject [name=fudge, priority=null]
     */

    System.out.println(Joiner.on("\n")
            .join(myObjectsSorted));
}

public static class MyObject {

    private final String name;

    private final String priority;

    public MyObject(final String name, final String priority) {
        this.name = name;
        this.priority = priority;
    }

    public String getName() {
        return this.name;
    }

    public String getPriority() {
        return this.priority;
    }

    @Override
    public String toString() {
        return "MyObject [name=" + this.name + ", priority=" + this.priority + "]";
    }
}

感谢@Barett的 nullsFirst nullsLast