【问题标题】:How to sort a List<Object> alphabetically using Object name field如何使用对象名称字段按字母顺序对 List<Object> 进行排序
【发布时间】:2012-01-15 23:36:11
【问题描述】:

我有一个对象列表,例如List&lt;Object&gt; 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..?

【问题讨论】:

  • 你将如何获得这个名字? -- Objects 没有名字。你的意思是使用.toString()
  • object1object2需要是Campaign类型,比较函数是object1.getName().compareTo(object2.getName())
  • 你将List&lt;Object&gt;Comparator&lt;Campaign&gt; 混合使用。你不能那样做。你要么有List&lt;Object&gt;Comparator&lt;Object&gt; 要么有List&lt;Campaign&gt;Comparator&lt;Campaign&gt;

标签: java list


【解决方案1】:

从您的代码来看,您的 Comparator 似乎已经使用 Campaign 进行了参数化。这仅适用于List&lt;Campaign&gt;。此外,您正在寻找的方法是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()));

最后一条评论——检查列表大小是没有意义的。排序将适用于空列表。

【讨论】:

  • 我认为这是将所有内容提炼成 OP 正在寻找的最佳答案。从 cmets 来看,我认为他想要不区分大小写,所以只需将 compareTo 切换为 compareToIgnoreCase
  • 第一个解决方案的小改进:我们可以做 if (list.size() > 1) - 至于 1 项不需要排序..
  • 你可以使用Comparator.comparing(Campaign::getName)
  • list.sort((object1, object2) -&gt; object1. getName().compareTo(object2. getName())); 为我工作
  • 尝试使用sortedList = list.stream().sort((object1, object2) -&gt; object1. getName().compareTo(object2. getName()))..collect(Collectors.toList());获取新的排序列表
【解决方案2】:

由于国际化,按字母顺序排序字符串的最正确方法是使用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());
        }
       });
   }

【讨论】:

    【解决方案3】:

    使用 Java 8 Comparator.comparing

    list.sort(Comparator.comparing(Campaign::getName));
    

    【讨论】:

      【解决方案4】:

      看看Collections.sort()Comparator 接口。

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

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

      【讨论】:

      • 您如何建议从Object 类型中提取名为nama 的字段?这个答案不完整。
      • 名称提取取决于对象的类型。我想它只是一个占位符类型。如果你不能给出更具体的类型,你可能会使用反射结束。
      【解决方案5】:
      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);
      

      【讨论】:

      • 我这样做了,但是“测试”在“搜索”之前出现。:(((
      • 如果要进行反向排序,只需在比较器类中将obj1.getName().compareTo(obj2.getName() 替换为obj2.getName().compareTo(obj1.getName()
      【解决方案6】:

      这是 Robert B 的答案的一个版本,适用于 List&lt;T&gt;,并使用反射按对象的指定字符串属性进行排序,不使用第 3 方库

      /**
       * 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;
      }
      

      【讨论】:

        【解决方案7】:

        类似

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

        【讨论】:

          【解决方案8】:

          你可以从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 的贡献者。

          【讨论】:

            【解决方案9】:

            试试这个:

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

            【讨论】:

            • 仅供参考,如果您在 Android 中执行此操作,则至少需要 API 级别 24
            【解决方案10】:

            如果你的对象有一些共同的祖先[让它成为T],你应该使用List&lt;T&gt;而不是List&lt;Object&gt;,并为此T实现一个Comparator,使用名称字段。

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

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

            【讨论】:

              【解决方案11】:

              我找到了另一种类型的方法。

              if(listAxu.size() > 0){
                  Collections.sort(listAxu, Comparator.comparing(IdentityNamed::getDescricao));
              }
              

              【讨论】:

                【解决方案12】:

                这是假设YourClass 的列表而不是Object,如amit 所述。

                您可以使用 Google Guava 库中的这个位:

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

                提到Comparator 的其他答案并非不正确,因为Ordering 实现了Comparator。在我看来,这个解决方案更容易一些,但如果您是初学者并且不习惯使用库和/或“函数式编程”,则可能会更难。

                无耻地抄自this answer on my own question.

                【讨论】:

                • 这是我的做法,但对于 OP 来说可能太多了。
                【解决方案13】:

                使用选择排序

                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&lt;Object&gt;,因此list.get(j).getName() 将无法编译。 (3)这个解是O(n^2),而使用Collections.sort()是一个更好的O(nlogn)解。
                【解决方案14】:

                如果您使用List&lt;Object&gt; 来保存具有名称字段的子类型的对象(让我们调用子类型NamedObject),则需要向下转换列表元素才能访问名称。您有 3 个选项,其中最好的是第一个:

                1. 如果可以的话,首先不要使用List&lt;Object&gt; - 将命名对象保存在List&lt;NamedObject&gt;
                2. 将您的 List&lt;Object&gt; 元素复制到 List&lt;NamedObject&gt;,在此过程中向下转换,进行排序,然后将它们复制回来
                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());
                        }
                }
                

                【讨论】:

                  【解决方案15】:
                  if(listAxu.size() > 0){
                       Collections.sort(listAxu, new Comparator<Situacao>(){
                          @Override
                          public int compare(Situacao lhs, Situacao rhs) {            
                              return lhs.getDescricao().compareTo(rhs.getDescricao());
                          }
                      });
                   }
                  

                  【讨论】:

                  • 在一个 3 年前的问题中要详细说明而不是仅仅倾销代码?
                  【解决方案16】:

                  @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!!)
                     })
                  }
                  

                  【讨论】:

                    【解决方案17】:

                    你可以用这个:

                    List<Campaign> list = new ArrayList<>(); 
                    list.sort(Comparator.comparing(Campaign::getName));
                    

                    【讨论】:

                      猜你喜欢
                      • 2021-06-18
                      • 2019-06-25
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2017-02-19
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多