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

我正在寻找实施我的地址簿应用程序的sortingfunction。

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

我怎样才能写一个自定义的sortingfunction来做到这一点?

这是一个关于订购对象的教程:

  • Java教程 – 集合 – 对象sorting

虽然我会举一些例子,但我仍然build议您阅读它。


有多种方法可以对ArrayList进行sorting。 如果要定义自然 (默认) sorting ,则需要让Contact实现“ Comparable 。 假设你想按name默认sorting,那么做(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); 

如果你想定义一个外部可控sorting (这会覆盖自然顺序),那么你需要创build一个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 ,以便您可以重复使用它们而不是每次重新创build它们:

 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在sorting中)

除了已经发布的内容之外,你应该知道,自从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)所以它是function接口。

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

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

我们可以减less这个代码:

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

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

  • 参数types(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)静态方法,我们可以用它来轻松创build比较器,比较器应该比较对象的某些特定值。

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

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

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

基本上你需要

  • 让你的Contact类通过实现Comparable接口
    • 在其中创build一个方法public int compareTo(Contact anotherContact)
  • 一旦你这样做,你可以调用Collections.sort(myContactList);
    • 其中myContactListArrayList<Contact> (或任何其他Contact集合)。

还有另外一种方法,涉及到创build一个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; } ... } } 

BalusC和bguiz已经给出了关于如何使用Java内置比较器的完整答案。

我只想补充一点,谷歌集合有一个比标准比较器更“强大”的sorting类。 这可能值得一试。 你可以做一些很酷的事情,比如复合Orderings,颠倒它们,根据你的对象的函数结果进行sorting…

这里有一个博客文章,提到它的一些好处。

您需要使您的Contact类实现Comparable ,然后实现compareTo(Contact)方法。 这样,Collections.sort将能够为你分类。 根据我链接的页面,compareTo'返回一个负整数,零或一个正整数,因为这个对象小于,等于或大于指定的对象。

例如,如果你想按名字sorting(A到Z),你的类将看起来像这样:

 public class Contact implements Comparable<Contact> { private String name; // all the other attributes and methods public compareTo(Contact other) { return this.name.compareTo(other.name); } } 

通过使用lambdaj,您可以按照以下方式对联系人的集合进行sorting(例如按照他们的名字)

 sort(contacts, on(Contact.class).getName()); 

或通过他们的地址:

 sort(contacts, on(Contacts.class).getAddress()); 

等等。 更一般地说,它提供了一个DSL来以许多方式访问和操作你的集合,比如根据某些条件过滤或分组你的联系人,集合他们的一些属性值等等。

Collections.sort是一个很好的sorting实现。 如果您没有为联系人实施类似function,则需要传入比较器实施

注意:

sortingalgorithm是一个修改的合并sorting(如果低位子列表中的最高位元素小于高位子列表中的最低位元素,则合并位置将被省略)。 该algorithm提供了有保证的n log(n)性能。 指定的列表必须是可修改的,但不需要resize。 这个实现将指定的列表转储到一个数组中,对数组进行sorting,然后迭代列表中的数组,从数组中的相应位置重置每个元素。 这样可以避免尝试对链表进行sorting而导致的n2 log(n)性能。

合并sorting可能比大多数searchalgorithm更好。

我通过以下方式做到了。 数字和名字是两个arraylist。 我必须sorting的名称。如果任何更改发生命名arralist命令那么数列表也改变它的顺序。

 public void sortval(){ String tempname="",tempnum=""; if (name.size()>1) // check if the number of orders is larger than 1 { for (int x=0; x<name.size(); x++) // bubble sort outer loop { for (int i=0; i < name.size()-x-1; i++) { if (name.get(i).compareTo(name.get(i+1)) > 0) { tempname = name.get(i); tempnum=number.get(i); name.set(i,name.get(i+1) ); name.set(i+1, tempname); number.set(i,number.get(i+1) ); number.set(i+1, tempnum); } } } } } 

你应该使用Arrays.sort函数。 包含的类应该实现Comparable。