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


102

我有一个。的对象列表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()吗?
马特·芬威克

object1并且object2必须是类型Campaign,比较函数是object1.getName().compareTo(object2.getName())
Bart van Heukelom

你混合List<Object>Comparator<Campaign>。你不能那样做。您拥有List<Object>and Comparator<Object>List<Campaign>andComparator<Campaign>
viktor

Answers:


230

从您的代码看来,您Comparator已经使用进行了参数设置Campaign。这仅适用于List<Campaign>。另外,您要寻找的方法是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()));

最后一条评论-检查列表大小毫无意义。排序将在一个空列表上进行。


2
我认为这是将OP提炼成所需内容的最佳答案。从评论中,我认为他希望不区分大小写,因此只需将compareTo切换为compareToIgnoreCase
Greg Case

未成年人在第一个解决方案改善:我们如果(则为list.size()> 1)做的-为1项不需要排序..
拉米亚姆波尔斯基

12
您可以使用Comparator.comparing(Campaign::getName)
Jose Da Silva

4
list.sort((object1, object2) -> object1. getName().compareTo(object2. getName()));为我工作
卢卡斯

1
尝试使用sortedList = list.stream().sort((object1, object2) -> object1. getName().compareTo(object2. getName()))..collect(Collectors.toList());以获取新的排序列表
Lukas

16

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

11

看一下Collections.sort()Comparator界面。

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

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


您如何建议namaObject类型中提取该字段?这个答案不完整。
艾米特

名称提取取决于对象的类型。我认为这只是一个占位符类型。如果您不能给出更具体的类型,则可以结束使用反射。
tobiasbayer 2011年


7
public class ObjectComparator implements Comparator<Object> {

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

}

请用包含名称字段的类替换Object

用法:

ObjectComparator comparator = new ObjectComparator();
Collections.sort(list, comparator);

我这样做了,但比“测试”要早于“搜索”。:(((
Saurabh Kumar

如果要进行反向排序,只需在比较器类中替换obj1.getName().compareTo(obj2.getName()obj2.getName().compareTo(obj1.getName()
Jan Vorcak,2011年

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

这是罗伯特·B(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

您可以sortThisBy()Eclipse Collections使用:

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

试试这个:

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

仅供参考,如果您在Android中执行此操作,则至少需要API级别24
MSpeed

1

如果您的对象具有某个共同的祖先[ T应为],则应使用List<T>代替List<Object>,并实现一个Comparator name字段为此T。

如果您没有共同的祖先,则可以实现Comperator并使用反射来提取名称,请注意,是不安全,不建议使用的,并且性能不佳,但是它允许您访问字段名称在不了解对象的实际类型的情况下[除了它具有具有相关名称的字段以外的事实]

在这两种情况下,都应使用Collections.sort()进行排序。



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。我认为,该解决方案要容易一些,尽管如果您是初学者并且不习惯使用库和/或“函数式编程”,则可能会更困难。

我自己的问题的答案中无耻地复制了下来


这是我要做的方式,但对于OP来说可能太多了。
格雷格案

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)解决方案。
艾米特

0

如果您使用a List<Object>来保存具有名称字段的子类型的对象(我们称其为subtype NamedObject),则需要向下转换列表元素才能访问该名称。您有3个选择,最好的是第一个:

  1. List<Object>如果可以帮助,请不要首先使用-将命名对象保存在List<NamedObject>
  2. 将您的List<Object>元素复制到中List<NamedObject>,在此过程中向下转换,进行排序,然后将其复制回
  3. 在比较器中进行向下转换

选项3如下所示:

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

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
想要详细说明而不是仅仅在3年的问题中转储代码?
Holloway

0

@Victor的答案对我有用,如果对其他使用Android的人有用,请在Kotlin上重新发布。

if (list!!.isNotEmpty()) {
   Collections.sort(
     list,
     Comparator { c1, c2 -> //You should ensure that list doesn't contain null values!
     c1.name!!.compareTo(c2.name!!)
   })
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.