Java TreeSet的"陷阱"

    TreeSet基于TreeMap,它很有意思,当你执行add()方法的时候,集合会自动排序,不需要手工执行Collections.sort()进行排序,代码更加简洁(Clean),今天使用过程发现它暗藏机关,与大家分享。

 

使用TreeSet有两种方法:

一、元素实现Comparable接口,然后直接通过add方法添加元素即可。

二、创建一个Comparator,并在构造TreeSet的时候传入,如下:

 

 

//我这里Job为待添加元素
Set<Job> jobs = new TreeSet<Job>(new JobComparator());

 

我要实现的需求很简单,根据Job的优先级字段(Priority)进行排序,Job类代码如下:

 

 

public class Job implements Comparable<SortJob> {

	private String jobName;

	private Integer priority;

	public SortJob() {
	}

	public SortJob(String jobName, Integer priority) {
		this.jobName = jobName;
		this.priority = priority;
	}

	public String getJobName() {
		return jobName;
	}

	public void setJobName(String jobName) {
		this.jobName = jobName;
	}

	public Integer getPriority() {
		return priority;
	}

	public void setPriority(Integer priority) {
		this.priority = priority;
	}

	@Override
	public int compareTo(SortJob o) {
		return priority.compareTo(o.getPriority());
	}
}

 

   测试代码如下:

 

 

	@Test
	public void sortJob() {
		Set<SortJob> jobs = new TreeSet<SortJob>();

		jobs.add(new SortJob("001", 1));
		jobs.add(new SortJob("002", 1));
		jobs.add(new SortJob("003", 1));
		assertEquals(3, jobs.size());    // ①

		jobs.clear();
		jobs.add(new SortJob("001", 1));
		jobs.add(new SortJob("002", 3));
		jobs.add(new SortJob("003", 2));

		List<SortJob> listJobs = new ArrayList<SortJob>(jobs);
		assertEquals("001", listJobs.get(0).getJobName());
		assertEquals("003", listJobs.get(1).getJobName());
		assertEquals("002", listJobs.get(2).getJobName());
	}

 

    测试并没有通过,在行①,这里实际集合size为1,出了什么问题呢?

    soga,原来TreeSet的add方法会先调用Job的compareTo方法判断元素是否重复,因为Priority全部为1,所以TreeSet认为后两个Job是重复的,这样的结果显然不是我们想要的,重新实现compareTo方法如下:

 

 

	@Override
	public int compareTo(SortJob o) {
		int compare1 = priority.compareTo(o.getPriority());
		return compare1 == 0 ? this.jobName.compareTo(o.jobName) : compare1;
	}

 

再次运行测试,OK了。

 

总结:

 

  1. TreeSet通过集合元素的compareTo方法判断元素是否重复,实现compareTo方法既要考虑排序,又要考虑对象是否重复
  2. 发现这个陷阱后,发现Collections.sort()还是很不错的选择,只需要考虑排序就可以了。

 

--heipark

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值