Comparartor使用(有坑)
首先虽然说是说Comparartor使用,但其实更多的是一个double类型精度的问题(哈哈,有点挂羊头卖狗肉的意思,虽然double类型精度的问题很常见,但当和Comparartor使用两个碰到一起就不那么容易发现了,所以在这里我们还是讲讲吧)。好了,先说问题,下面是问题代码:
- Person.java(这是一个用来存储数据的javaBean类)
import java.util.Objects;
/*
* Person类,遵从Comparable<T>接口, 要求实现对应 compareTo方法
*/
public class Person {
private int id;
private String name;
//关键就是这个double类型变量(工资)
private double salary;
public Person() {
}
public Person(int id, String name, double salary) {
super();
this.id = id;
this.name = name;
this.salary = salary;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
@Override
public String toString() {
return "Person [id=" + id + ", name=" + name + ", salary=" + salary + "]";
}
}
- Demo.java(使用TeerSet添加数据,也就是Person对象)
package com.qfedu.b_set;
import java.util.Comparator;
import java.util.Map.Entry;
import java.util.TreeSet;
public class Demo5 {
public static void main(String[] args) {
/*
* 匿名内部类的匿名对象作为方法参数
*/
TreeSet<Person> set = new TreeSet<Person>(new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
int ret = (int) ( (o1.getSalary() - o2.getSalary())*100 );
return ret;
}
});
Person p1 = new Person(1, "余晖", 10.01);
Person p2 = new Person(2, "将夜", 10.03);
Person p3 = new Person(3, "朔鼠", 10.05);
Person p4 = new Person(4, "邶风", 10.07);
Person p5 = new Person(5, "柏州", 10.00);
Person p6 = new Person(6, "与归", 11.00);
set.add(p1);
set.add(p2);
set.add(p3);
set.add(p4);
set.add(p5);
set.add(p6);
for(Person p : set) {
System.out.println(p);
}
}
}
好了, 坑来了,请问现在set里用几个Person对象?
(还要问吗,当然是六个)
嗯,我刚开始也是这样以为的,然后。。。。。我错了,不信?看下面截图
额。。。。“柏州”哪去了?
首先我们要知道TreeSet是一个基于二叉树实现的,有序,不可重复,即当有两个相同的对象(TreeSet
的比较器决定)就不会重复添加,TreeSet支持两种排序方式,自然排序 和定制排序,其中自然排序为默认的排序方式。向TreeSet中加入的应该是同一个类的对象。
TreeSet判断两个对象不相等的方式是两个对象通过equals方法返回false;或者通过CompareTo方法比较条件判断结果是相同,返回0;我们上面采用的是第二种方式通过CompareTo方法比较,问题就出在这了,因为在比较过程中我们根据 salary 来进行判定,在比较过程中 p1 和 p2 它们的工资比较 CompareTo 方法返回的是 0 ,相同。。。。。。
(骗人,( 10.01 - 10)*100 = 1,你别蒙我 明明返回的是1)
好吧还是来张图:
(什么鬼?不该是0.1吗?)
好了,讲到这里其实大家也都明白了为什么 set 里就5个Person 吧;然后出现这种问题主要还是double精度的问题,因为有些小数它无法用二进制表示出来,即比方十进制(0.1),你试试看,你写完我请你喝茶,哈哈,你会发现二进制表示是这样的(0.000110011001100…),它只能是一个近似值,
(那怎么解决呢?)
不乘100了,改成1000就好了
(…)
哈哈,不开玩笑,在这里我们只须使用BigDecimal(String value) 这个方法,把double转成字符后使用该方法将double 类型转为BigDecimal类型进行操作就好了
下面是改后的结果:
ps:(以后做开发如果碰到要求精度很高的计算千万别用double)