如何使用对象名称字段按字母顺序对List<Object>进行排序

116

我有一个对象列表 List<Object> p,我想按照对象名称字段的字母顺序对此列表进行排序。对象包含10个字段,其中名称字段是其中之一。

if (list.size() > 0) {
    Collections.sort(list, new Comparator<Campaign>() {
        @Override
        public int compare(final Object object1, final Object object2) {
        return String.compare(object1.getName(), object2.getName());
        }
    } );
}

但是没有像String.compare这样的东西吗?


3
你打算如何获取名字?-- Object 没有名字。你是指使用 .toString() 方法吗? - Matt Fenwick
object1object2 需要是 Campaign 类型,并且比较函数为 object1.getName().compareTo(object2.getName()) - Bart van Heukelom
你混合使用了 List<Object>Comparator<Campaign>,这是不允许的。你必须要么使用 List<Object>Comparator<Object>,要么使用 List<Campaign>Comparator<Campaign> - viktor
18个回答

1
如果您的对象有一些共同的祖先[假设为T],则应该使用List<T>而不是List<Object>,并为此T实现一个Comparator,使用名称字段。
如果您没有共同的祖先,可以实现一个Comperator,并使用reflection提取名称。请注意,使用反射是不安全、不建议且性能差的,但它允许您访问一个字段名称,而不需要知道对象的实际类型[除了它具有相关名称的字段]。
在这两种情况下,您都应该使用Collections.sort()进行排序。

0
if(listAxu.size() > 0){
     Collections.sort(listAxu, new Comparator<Situacao>(){
        @Override
        public int compare(Situacao lhs, Situacao rhs) {            
            return lhs.getDescricao().compareTo(rhs.getDescricao());
        }
    });
 }

1
能否详细说明一下,而不是只在一个三年前的问题中粘贴代码? - Holloway

0

如果属性还包含 NULL 值,则可以使用:

list.sort(Comparator.comparing(Campaign::getName, Comparator.nullsLast(Comparator.naturalOrder())));

这将把NULL值放在有序列表的最后位置。


0

这是基于 amit 的解释,假设使用 YourClass 列表而不是 Object

您可以使用 Google Guava 库中的以下代码:

Collections.sort(list, Ordering.natural()
  .onResultOf(new Function<String,YourClass>() {
  public String call(YourClass o) {
     return o.getName();
  }))
  .nullsLast();

其他提到 Comparator 的答案并不是不正确的,因为 Ordering 实现了 Comparator。在我看来,这个解决方案可能会更容易一些,尽管如果你是初学者并且不习惯使用库和/或“函数式编程”,那么它可能会更难一些。
无耻地复制自 我的问题的这个答案。

这是我会做的方式,但对于提问者来说可能太复杂了。 - Greg Case

0
使用选择排序
for(int i = list.size() - 1; i > 0; i--){

  int max = i

  for(int j = 0; j < i; j++){
      if(list.get(j).getName().compareTo(list.get(j).getName()) > 0){
            max= j;
      }
  }

  //make the swap
  Object temp = list.get(i);
  list.get(i) = list.get(max);
  list.get(max) = temp;

}

(1) 他为什么要重新发明轮子?Collections.sort()有什么问题吗? (2) 这个列表的类型是List<Object>,因此list.get(j).getName()无法编译。 (3) 这个解决方案的时间复杂度是O(n^2),而使用Collections.sort()是更好的O(nlogn)解决方案。 - amit

0

如果您正在使用 List<Object> 来保存具有名称字段(假设子类型称为 NamedObject)的对象,您需要向下转换列表元素以访问名称。您有三个选择,其中最好的是第一个:

  1. 如果可能的话,首先不要使用 List<Object> - 将命名对象保存在 List<NamedObject>
  2. List<Object> 元素复制到 List<NamedObject> 中,在此过程中进行向下转换,进行排序,然后将它们复制回来
  3. 在 Comparator 中执行向下转型

选项3将如下所示:

Collections.sort(p, new Comparator<Object> () {
        int compare (final Object a, final Object b) {
                return ((NamedObject) a).getName().compareTo((NamedObject b).getName());
        }
}

0
你可以使用这个:
List<Campaign> list = new ArrayList<>(); 
list.sort(Comparator.comparing(Campaign::getName));

0

@Victor的答案对我有用,这里用Kotlin重新发布一下,以防其他做Android的人也需要。

if (list!!.isNotEmpty()) {
   Collections.sort(
     list,
     Comparator { c1, c2 -> //You should ensure that list doesn't contain null values!
     c1.name!!.compareTo(c2.name!!)
   })
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接