2014-07-25 38 views
1

我有一个方法getPriority()返回对象的名称(也是一个字符串)的方法getName()返回对象的列表中的对象的列表。我有一个“优先级”列表,其中包含“高”“中”和“低”等字符串。根据单独的列表排序列表

我想通过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"); 

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

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

回答

1

您可以使用排序比较列表。例如: -

代码

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

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

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)); 
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

+0

这又是一个很好的选择。我相信你可以在你的buildPriorityOrdering方法中使用'.nullsLast()'最后对空值进行排序。 – Barett

+0

我会检查出来并更新。 – Jeff

+0

@Barett错字现在修复 – Jeff