使用自定义排序顺序对对象的ArrayList进行排序

我正在寻找为我的地址簿应用程序实施排序功能。

我想排序一个ArrayList<Contact> contactArrayContact是一个包含四个字段的类别:姓名,家庭号码,手机号码和地址。 我想按name排序。

我如何编写自定义排序功能来执行此操作?


以下是关于订购对象的教程:

  • Java教程 - 集合 - 对象排序
  • 尽管我会举一些例子,但我仍建议您阅读它。


    有多种方法可以对ArrayList进行排序。 如果你想定义一个自然的 (默认) 排序 ,那么你需要让Contact实现Comparable 。 假设你想按name默认进行排序,那么做(nullchecks为简单起见省略):

    public class Contact implements Comparable<Contact> {
    
        private String name;
        private String phone;
        private Address address;
    
        public int compareTo(Contact other) {
            return name.compareTo(other.name);
        }
    
        // Add/generate getters/setters and other boilerplate.
    }
    

    所以你可以做

    List<Contact> contacts = new ArrayList<Contact>();
    // Fill it.
    
    Collections.sort(contacts);
    

    如果你想定义一个外部可控排序 (这会覆盖自然排序),那么你需要创建一个Comparator

    List<Contact> contacts = new ArrayList<Contact>();
    // Fill it.
    
    // Now sort by address instead of name (default).
    Collections.sort(contacts, new Comparator<Contact>() {
        public int compare(Contact one, Contact other) {
            return one.getAddress().compareTo(other.getAddress());
        }
    }); 
    

    您甚至可以在Contact定义Comparator ,以便您可以重复使用它们而不是每次重新创建它们:

    public class Contact {
    
        private String name;
        private String phone;
        private Address address;
    
        // ...
    
        public static Comparator<Contact> COMPARE_BY_PHONE = new Comparator<Contact>() {
            public int compare(Contact one, Contact other) {
                return one.phone.compareTo(other.phone);
            }
        };
    
        public static Comparator<Contact> COMPARE_BY_ADDRESS = new Comparator<Contact>() {
            public int compare(Contact one, Contact other) {
                return one.address.compareTo(other.address);
            }
        };
    
    }
    

    可以使用如下:

    List<Contact> contacts = new ArrayList<Contact>();
    // Fill it.
    
    // Sort by address.
    Collections.sort(contacts, Contact.COMPARE_BY_ADDRESS);
    
    // Sort later by phone.
    Collections.sort(contacts, Contact.COMPARE_BY_PHONE);
    

    为了实现最佳效果,您可以考虑使用通用的javabean比较器

    public class BeanComparator implements Comparator<Object> {
    
        private String getter;
    
        public BeanComparator(String field) {
            this.getter = "get" + field.substring(0, 1).toUpperCase() + field.substring(1);
        }
    
        public int compare(Object o1, Object o2) {
            try {
                if (o1 != null && o2 != null) {
                    o1 = o1.getClass().getMethod(getter, new Class[0]).invoke(o1, new Object[0]);
                    o2 = o2.getClass().getMethod(getter, new Class[0]).invoke(o2, new Object[0]);
                }
            } catch (Exception e) {
                // If this exception occurs, then it is usually a fault of the developer.
                throw new RuntimeException("Cannot compare " + o1 + " with " + o2 + " on " + getter, e);
            }
    
            return (o1 == null) ? -1 : ((o2 == null) ? 1 : ((Comparable<Object>) o1).compareTo(o2));
        }
    
    }
    

    你可以使用如下:

    // Sort on "phone" field of the Contact bean.
    Collections.sort(contacts, new BeanComparator("phone"));
    

    (正如你在代码中看到的那样,可能的空字段已经被覆盖以避免NPE在排序中)


    除了已发布的内容之外,您应该知道,自从Java 8以后,我们可以缩短代码并将其写入如下所示:

    Collection.sort(yourList, Comparator.comparing(YourClass::getFieldToSortOn));
    

    或者因为List现在有sort方法

    yourList.sort(Comparator.comparing(YourClass::getFieldToSortOn));
    

    说明:

    从Java 8开始,函数接口(只有一个抽象方法的接口 - 它们可以有更多的默认或静态方法)可以通过以下方式轻松实现:

  • lambdas arguments -> body
  • 或方法引用source::method
  • 由于Comparator<T>只有一个抽象方法int compare(T o1, T o2)所以它是功能接口。

    所以,而不是(例如从@BalusC答案)

    Collections.sort(contacts, new Comparator<Contact>() {
        public int compare(Contact one, Contact other) {
            return one.getAddress().compareTo(other.getAddress());
        }
    }); 
    

    我们可以将此代码缩减为:

    Collections.sort(contacts, (Contact one, Contact other) -> {
         return one.getAddress().compareTo(other.getAddress());
    });
    

    我们可以通过跳过来简化这个(或任何)lambda

  • 参数类型(Java会根据方法签名推断它们)
  • {return ... }
  • 所以,而不是

    (Contact one, Contact other) -> {
         return one.getAddress().compareTo(other.getAddress();
    }
    

    我们可以写

    (one, other) -> one.getAddress().compareTo(other.getAddress())
    

    此外,现在Comparator具有静态方法,如comparing(FunctionToComparableValue)comparing(FunctionToValue, ValueComparator) ,我们可以使用它们轻松创建比较器,比较器应该比较对象的某些特定值。

    换句话说,我们可以将上面的代码重写为

    Collections.sort(contacts, Comparator.comparing(Contact::getAddress)); 
    //assuming that Address implements Comparable (provides default order).
    

    这个页面告诉你所有你需要知道的排序集合,比如ArrayList。

    基本上你需要

  • 让你的Contact类通过实现Comparable接口
  • 在其中创建一个方法public int compareTo(Contact anotherContact)
  • 一旦你这样做,你可以调用Collections.sort(myContactList);
  • 其中myContactListArrayList<Contact> (或任何其他Contact集合)。
  • 还有另外一种方法,涉及到创建一个Comparator类,并且您还可以从链接页面读取关于它的信息。

    例:

    public class Contact implements Comparable<Contact> {
    
        ....
    
        //return -1 for less than, 0 for equals, and 1 for more than
        public compareTo(Contact anotherContact) {
            int result = 0;
            result = getName().compareTo(anotherContact.getName());
            if (result != 0)
            {
                return result;
            }
            result = getNunmber().compareTo(anotherContact.getNumber());
            if (result != 0)
            {
                return result;
            }
            ...
        }
    }
    
    链接地址: http://www.djcxy.com/p/37663.html

    上一篇: Sorting an ArrayList of objects using a custom sorting order

    下一篇: Count child matches in linq Entity Framework