Comparator集合排序

</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());
		}

	}



 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值