</pre><p>需要对一个Collection进行某种方式的排序。比如一个User对象的集合,我们需要按公司和姓名进行排序。User对象如下:</p><pre class="java" name="code">public class User {
private String name;
private String sex;
private String company;
User() {};
User(String name, String sex, String company) {
this.name = name;
this.sex = sex;
this.company = company;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public void setCompany(String company) {
this.company = company;
}
public String getCompany() {
return company;
}
public String toString() {
return "[name=" + this.name + ",sex=" + this.sex +",company=" + this.company +"]";
}
}
解决方案:
一般简单的排序,我们用现有的排序算法就可以解决了。但是对于复杂的排序,比如根据公司名称、职位、工号等信息排序的话,那往往是不够的。这就需要我们实现Comparator接口,通过该接口进行比较。Comparator接口只定义了一个方法compare,该方法根据一定的策略比较两个对象,然后返回一个整数值。如下为该接口的定义:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.collections.ComparatorUtils;
import org.apache.commons.collections.comparators.ComparableComparator;
import org.apache.commons.collections.comparators.ComparatorChain;
public class UserComparator implements Comparator<User> {
public static void main(String[] args) {
// startCompare();
// start();
ListCompare();
}
/**
* 3、ComparatorChain把若干个Comparator对象连起来,组成一个Comparator链。
* 在比较两个对象的时候,依次用这个Comparator链中的每个Comparator进行比较,直到有一个Comparator返回非零值则结束比较;
* 如果相等,则继续用该链中的下一个Comparator比较
*/
public static void start() {
User user1 = new User("A", "男", "AA");
User user2 = new User("A", "男", "BB");
User user3 = new User("B", "女", "AA");
User user4 = new User("B", "男", "BB");
User user5 = new User("C", "男", "BB");
User[] users = new User[] { user1, user2, user3, user4, user5 };
ComparatorChain comparatorChain = new ComparatorChain();
comparatorChain.addComparator(new BeanComparator("name"));
// comparatorChain.addComparator()方法中的第二个参数,其含义是是否反转(也就是为true就倒序,默认是升序)。
comparatorChain.addComparator(new BeanComparator("sex"), true);
comparatorChain.addComparator(new BeanComparator("company"));
Arrays.sort(users, comparatorChain);
for (User user : users) {
System.out.println(user.getName() + " " + user.getSex() + " "
+ user.getCompany());
}
}
/**
* 2、使用ComparatorChain对ArrayList<Object> BeanComparator排序
*/
public static void ListCompare() {
// 在列表中加入若干CompareTipA对象
ArrayList<Object> list = new ArrayList<Object>();
list.add(new User("A", "男", "AA"));
list.add(new User("A", "男", "BB"));
list.add(new User("B", "女", "AA"));
list.add(new User("B", "男", "BB"));
list.add(new User("C", "男", "BB"));
// 创建一个排序规则
Comparator mycmp = ComparableComparator.getInstance();
mycmp = ComparatorUtils.nullLowComparator(mycmp); // 允许null
mycmp = ComparatorUtils.reversedComparator(mycmp); // 逆序
// 声明要排序的对象的属性,并指明所使用的排序规则,如果不指明,则用默认排序
ArrayList<Object> sortFields = new ArrayList<Object>();
sortFields.add(new BeanComparator("name", mycmp)); // name逆序 (主)
sortFields.add(new BeanComparator("company")); // company正序 (副)
// 创建一个排序链
ComparatorChain multiSort = new ComparatorChain(sortFields);
// 开始真正的排序,按照先主,后副的规则
Collections.sort(list, multiSort);
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i)); // 输出
}
}
/**
* 1、使用比较器排序规则
*/
public static void startCompare() {
User user1 = new User("A", "男", "AA");
User user2 = new User("A", "男", "BB");
User user3 = new User("B", "女", "AA");
User user4 = new User("B", "男", "BB");
User user5 = new User("C", "男", "BB");
User[] users = new User[] { user1, user2, user3, user4, user5 };
Comparator userComparator = new UserComparator();
Arrays.sort(users, userComparator);
for (User user : users) {
System.out.println(user.getCompany() + " " + user.getName() + " "
+ user.getSex());
}
}
/**
* 定义比较器
*/
@Override
public int compare(User user1, User user2) {
int comparison = -1;
String company1 = user1.getCompany();
String company2 = user2.getCompany();
String name1 = user1.getName();
String name2 = user2.getName();
if (company1.length() != 0 && company2.length() != 0) {
// 如果o1小于o2,返回-1;o1等于o2,返回0;o1大于o2,返回1。
comparison = company1.compareTo(company2);
}
/* 在公司名称相同的前提下,根据姓名比较 */
if (comparison == 0 && name1.length() != 0 && name2.length() != 0) {
comparison = name1.compareTo(name2);
}
return comparison;
}
}
这里要说明的两点是:①ComparatorChain来自commons.collections这个包,BeanComparator 来自commons.beanutils这个包,所以一定要引用这两个包才行。commons-collections-xx.jar
需求升级:
更进一步,大家或许有疑问了。这B公司的AA和BB好像不对啊,这个中文是依据什么排序的呢?按性别倒过来应该是女、男才对啊。到这一步,我也说不上来,因为我不懂这里的中文是根据什么来排序的。那面对中文该怎么办呢?
还好,有很多中文工具可以帮我们实现,比较常见的有Collator和pinyin4j。Collator是JDK自带的一个本地化工具,pinyin4j是google上的一个开源项目。以Collator实现的中文排序Comparator如下:
import java.text.CollationKey;
import java.text.Collator;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Locale;
import org.apache.commons.beanutils.BeanComparator;
import org.apache.commons.collections.comparators.ComparatorChain;
import org.apache.commons.collections.comparators.FixedOrderComparator;
import org.apache.commons.collections.comparators.NullComparator;
public class ChineseComparator implements Comparator<String> {
private final static Collator collator = Collator.getInstance(Locale.CHINESE);
public static void main(String[] args) {
start();
// 对null的比较:
Comparator userComparator = new UserComparator();
Comparator nullComparator = new NullComparator(userComparator,true);
// 固定顺序的比较:
String[] weeks = {"星期一","星期二","星期三","星期四","星期五","星期六","星期日"};
Comparator fixedComparator = new FixedOrderComparator(weeks);
Comparator weeksComparator = new BeanComparator("week",fixedComparator);
}
@Override
public int compare(String str1, String str2) {
int comparison = -1;
if (str1 == null && str2 == null) {
comparison = 0;
} else if (str1 == null) {
comparison = -1;
} else if (str2 == null) {
comparison = 1;
} else {
CollationKey key1 = collator.getCollationKey(str1);
CollationKey key2 = collator.getCollationKey(str2);
comparison = key1.compareTo(key2);
}
return comparison;
}
// 将需要排序的User数组和Comparator装饰改为如下:
@SuppressWarnings("unchecked")
public static void start() {
User user1 = new User("马加爵", "男", "招商局");
User user2 = new User("李刚", "男", "公安局");
User user3 = new User("马加爵", "女", "招商局");
User user4 = new User("李英", "男", "公安局");
User user5 = new User("马加爵", "男", "公安局");
User[] users = new User[] { user1, user2, user3, user4, user5 };
Comparator chineseComparator = new ChineseComparator();
ComparatorChain comparatorChain = new ComparatorChain();
comparatorChain.addComparator(new BeanComparator("company", chineseComparator));
comparatorChain.addComparator(new BeanComparator("name", chineseComparator));
comparatorChain.addComparator(new BeanComparator("sex", chineseComparator));
Arrays.sort(users, comparatorChain);
for (User user : users) {
System.out.println(user.getCompany() + " " + user.getName() + " " + user.getSex());
}
}