使用自定义sorting顺序对对象的ArrayList进行sorting
我正在寻找实施我的地址簿应用程序的sortingfunction。
我想sorting一个ArrayList<Contact> contactArray
。 Contact
是一个包含四个字段的类别:姓名,家庭号码,手机号码和地址。 我想按name
sorting。
我怎样才能写一个自定义的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)
。
- 在其中创build一个方法
- 一旦你这样做,你可以调用
Collections.sort(myContactList);
,- 其中
myContactList
是ArrayList<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。