如何使用对象名称字段按字母顺序对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个回答

257
从您的代码来看,似乎您的比较器已经使用了参数化的Campaign。这只适用于List。另外,您要查找的方法是compareTo。
if (list.size() > 0) {
  Collections.sort(list, new Comparator<Campaign>() {
      @Override
      public int compare(final Campaign object1, final Campaign object2) {
          return object1.getName().compareTo(object2.getName());
      }
  });
}

如果你正在使用Java 1.8

list
  .stream()
  .sorted((object1, object2) -> object1.getName().compareTo(object2.getName()));

最后一点评论——检查列表大小是没有意义的。排序会在空列表上工作。


3
我认为这是最好的答案,将所有内容浓缩成 OP 所需的东西。从评论中看,我认为他想要不区分大小写,所以只需将 compareTo 更改为 compareToIgnoreCase。 - Greg Case
第一种解决方案的小改进:我们可以使用 if (list.size() > 1) - 对于1个项目不需要排序。 - Rami Yampolsky
14
您可以使用Comparator.comparing(Campaign::getName) - Jose Da Silva
4
这段代码 list.sort((object1, object2) -> object1.getName().compareTo(object2.getName())); 对我有用。它的作用是对列表进行排序,排序规则是按照对象的名称属性进行升序排序。 - Lucas
1
尝试使用 sortedList = list.stream().sort((object1, object2) -> object1. getName().compareTo(object2. getName()))..collect(Collectors.toList()); 来获取一个新的排序列表。 - Lukas
显示剩余2条评论

24

18

在进行字母排序时,最正确的方法是使用Collator,因为这样可以实现国际化。一些语言由于存在额外字符等原因而具有不同的排序顺序。

   Collator collator = Collator.getInstance(Locale.US);
   if (!list.isEmpty()) {
    Collections.sort(list, new Comparator<Campaign>() {
        @Override
        public int compare(Campaign c1, Campaign c2) {
            //You should ensure that list doesn't contain null values!
            return collator.compare(c1.getName(), c2.getName());
        }
       });
   }

如果您不关心国际化,请使用 string.compare(otherString)
   if (!list.isEmpty()) {
    Collections.sort(list, new Comparator<Campaign>() {
        @Override
        public int compare(Campaign c1, Campaign c2) {
            //You should ensure that list doesn't contain null values!
            return c1.getName().compare(c2.getName());
        }
       });
   }

13

请查看Collections.sort()Comparator接口。

使用object1.getName().compareTo(object2.getName())object2.getName().compareTo(object1.getName())(取决于所需的排序方向)可以进行字符串比较。

如果您希望排序不区分大小写,请使用object1.getName().toUpperCase().compareTo(object2.getName().toUpperCase())


你如何建议从“Object”类型中提取名为nama的字段?这个答案不完整。 - amit
名称提取取决于对象的类型。我认为这只是一个占位符类型。如果您不能给出更具体的类型,您可能会使用反射。 - tobiasbayer

7
public class ObjectComparator implements Comparator<Object> {

    public int compare(Object obj1, Object obj2) {
        return obj1.getName().compareTo(obj2.getName());
    }

}

请将 Object 替换为您的类,该类应包含 name 字段。
使用方法:
ObjectComparator comparator = new ObjectComparator();
Collections.sort(list, comparator);

我做了这个,但是“测试”出现在“搜索”之前。:((( - Saurabh Kumar
1
如果您想进行反向排序,只需在比较器类中将 obj1.getName().compareTo(obj2.getName() 替换为 obj2.getName().compareTo(obj1.getName() 即可。 - Jan Vorcak

3

试试这个:

List< Object> myList = x.getName;
myList.sort(Comparator.comparing(Object::getName));

如果你在Android上进行这个操作,需要至少API 24级。 - MSpeed

3
这是 Robert B 的答案版本,适用于 List<T> 并使用反射按对象的指定 String 属性进行排序,不需要第三方库。请参考以下内容:

/**
 * Sorts a List by the specified String property name of the object.
 * 
 * @param list
 * @param propertyName
 */
public static <T> void sortList(List<T> list, final String propertyName) {

    if (list.size() > 0) {
        Collections.sort(list, new Comparator<T>() {
            @Override
            public int compare(final T object1, final T object2) {
                String property1 = (String)ReflectionUtils.getSpecifiedFieldValue (propertyName, object1);
                String property2 = (String)ReflectionUtils.getSpecifiedFieldValue (propertyName, object2);
                return property1.compareToIgnoreCase (property2);
            }
        });
    }
}


public static Object getSpecifiedFieldValue (String property, Object obj) {

    Object result = null;

    try {
        Class<?> objectClass = obj.getClass();
        Field objectField = getDeclaredField(property, objectClass);
        if (objectField!=null) {
            objectField.setAccessible(true);
            result = objectField.get(obj);
        }
    } catch (Exception e) {         
    }
    return result;
}

public static Field getDeclaredField(String fieldName, Class<?> type) {

    Field result = null;
    try {
        result = type.getDeclaredField(fieldName);
    } catch (Exception e) {
    }       

    if (result == null) {
        Class<?> superclass = type.getSuperclass();     
        if (superclass != null && !superclass.getName().equals("java.lang.Object")) {       
            return getDeclaredField(fieldName, type.getSuperclass());
        }
    }
    return result;
}

2

类似于

  List<FancyObject> theList = … ;
  Collections.sort (theList,
                    new Comparator<FancyObject> ()
                    { int compare (final FancyObject a, final FancyObject d)
                          { return (a.getName().compareTo(d.getName())); }});

2
您可以使用Eclipse Collections中的sortThisBy()函数进行排序:
MutableList<Campaign> list = Lists.mutable.empty();
list.sortThisBy(Campaign::getName);

如果您无法更改列表类型为List

List<Campaign> list = new ArrayList<>();
ListAdapter.adapt(list).sortThisBy(Campaign::getName);

注意:我是Eclipse Collections的贡献者。

2
我找到了另一种实现类型的方法。
if(listAxu.size() > 0){
    Collections.sort(listAxu, Comparator.comparing(IdentityNamed::getDescricao));
}

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