Java比较器
1、java对象正常情况下只能进行 == 或 !=,不能进行比较大小。
若需要比较对象的大小,需要实现两个接口中的任何一个:Comparable 或 Comparator
2、Comparable接口与Comparator接口的使用比较
Comparable接口的方式一旦指定,该接口的实现类的对象可以在任何位置都可以比较大小
Comparator接口属于临时性的比较
Comparable接口
1、String、包装类等实现了Comparable接口,重写CompareTo(obj)或compare方法,给出了比较两个对象的方式
2、重写了CompareTo(obj)的方法以后,默认进行从小到大的排序
3、重写compareTo(obj)的规则:
-
如果当前对象的this大于形参对象obj,则返回正整数
-
如果当前对象的this小于形参对象obj,则返回负整数
-
如果当前对象的this等于形参对象obj,则返回零
4、(自然排序)对于自定义类,如需要排序,可以让自定义类实现Comparable接口,重写compareTo(obj)的方法,在compareTo(obj)的方法中指明如何排序
示例
@Test
public void test1(){
String[] arr = new String[]{"aa","bb","dd","cc","zz","mm"};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));//[aa, bb, cc, dd, mm, zz]
}
商品类Goods,声明name和price属性
//实现Comparable接口
public class Goods implements Comparable{
private String name;
private Integer price;
public Goods(String name, Integer price) {
this.name = name;
this.price = price;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getPrice() {
return price;
}
public void setPrice(Integer price) {
this.price = price;
}
@Override
public String toString() {
return "Goods{" +
"name='" + name + '\'' +
", price=" + price +
'}';
}
//重写comparaTo方法:具体的比较方式声明在此方法体中
@Override
public int compareTo(Object o) {
//方式一:
if(o instanceof Goods){
Goods obj = (Goods)o;
if(obj.price < this.price){
return 1;
}else if(obj.price > this.price){
return -1;
}else {
//return 0;
return -this.name.compareTo(obj.name);
}
//方式二:
//return Double.compare(obj.price, this.price);
}
throw new RuntimeException("输入的数据不一致!");
}
}
测试
@Test
public void test2(){
Goods[] arr = new Goods[5];
arr[0] = new Goods("xiaomi phone", 3999);
arr[1] = new Goods("huawei phone", 8899);
arr[2] = new Goods("apple phone", 8999);
arr[3] = new Goods("vivo phone", 4999);
arr[4] = new Goods("opple phone", 8899);
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}
Comparator接口
Comparator接口的使用:定制排序,解决没有实现java.lang.comparable接口或者不便修改原代码,或者原来的接口排序不满足要求,就可以实现定制Comparator接口。
重写compare(Object o1,Object o2)方法,比较o1和o2的大小:
- o1大于o2,则返回正整数
- o1等于o2,则返回0
- o1小于o2,则返回负整数
示例
@Test
public void test3(){
String[] arr = new String[]{"aa","bb","dd","cc","zz","mm"};
//字符串从大到小排序
Arrays.sort(arr, new Comparator() {//匿名实现类匿名对象
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof String && o2 instanceof String){
String obj1 = (String) o1;
String obj2 = (String) o2;
return -obj1.compareTo(obj2);
}
throw new RuntimeException("数据类型不一致");
}
});
System.out.println(Arrays.toString(arr));
}
@Test
public void test4(){
Goods[] arr = new Goods[6];
arr[0] = new Goods("xiaomi phone", 3999);
arr[1] = new Goods("huawei phone", 8899);
arr[2] = new Goods("apple phone", 8999);
arr[3] = new Goods("apple phone", 10999);
arr[4] = new Goods("vivo phone", 4999);
arr[5] = new Goods("opple phone", 8899);
//指明商品比较大小的方式:按照产品名称从低到高排序,再按照价格从高到低排序
Arrays.sort(arr, new Comparator<Goods>() {
@Override
public int compare(Goods o1, Goods o2) {
if(o1.getName().equals(o2.getName())){
//xxx.compare()默认从小到大
return -Double.compare(o1.getPrice(),o2.getPrice());
}else {
return o1.getName().compareTo(o2.getName());
}
}
});
System.out.println(Arrays.toString(arr));
}
使用比较器的场景:
Arrays.sort(goods, com);
Collections.sort(coll, com);
new TreeSet(com);
new TreeMap(com);
两种排序方式的比较
Comparable接口的方式一旦确定,保证Comparable接口实现类的对象在任何位置都可以比较
Comparator接口属于临时性比较
案例一: TreeSet的使用
实体类 - MyDate.java
/**
* MyDate类成员变量:
* year,month,day
*/
public class MyDate {
private int year;
private int month;
private int day;
public MyDate() {
}
public MyDate(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
...
}
Employee.java
/**
* Employee类成员变量:
* name,age,birthday(为MyDate类的对象)
*/
public class Employee implements Comparable{
private String name;
private Integer age;
private MyDate birthday;
public Employee() {
}
public Employee(String name, Integer age, MyDate birthday) {
this.name = name;
this.age = age;
this.birthday = birthday;
}
...
@Override
public int compareTo(Object o) {
if(o instanceof Employee){
Employee e = (Employee)o;
return this.getName().compareTo(e.getName());
}
throw new RuntimeException("输入的数据类型不匹配");
}
}
测试一
//使用:自然排序
@Test
public void test1(){
TreeSet set = new TreeSet();
Employee e1 = new Employee("liudehua", 51, new MyDate(1973, 4, 9));
Employee e2 = new Employee("zhangxueyou", 52, new MyDate(1953, 4, 9));
Employee e3 = new Employee("guofucheng", 63, new MyDate(1942, 8, 11));
Employee e4 = new Employee("liming", 42, new MyDate(1983, 8, 29));
Employee e5 = new Employee("liangzhaowei", 66, new MyDate(1936, 6,19));
set.add(e1);
set.add(e2);
set.add(e3);
set.add(e4);
set.add(e5);
Iterator iterator = set.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
//结果
Employee{name='guofucheng', age=63, birthday=MyDate{year=1942, month=8, day=11}}
Employee{name='liangzhaowei', age=66, birthday=MyDate{year=1936, month=6, day=19}}
Employee{name='liming', age=42, birthday=MyDate{year=1983, month=8, day=29}}
Employee{name='liudehua', age=51, birthday=MyDate{year=1973, month=4, day=9}}
Employee{name='zhangxueyou', age=52, birthday=MyDate{year=1953, month=4, day=9}
测试二
//按照:生日排序,定制排序
@Test
public void test2(){
TreeSet set = new TreeSet(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof Employee && o2 instanceof Employee){
Employee b1 = (Employee) o1;
Employee b2 = (Employee) o2;
MyDate d1 = b1.getBirthday();
MyDate d2 = b2.getBirthday();
//比较年
int subYear = d1.getYear() - d2.getYear();
if(subYear != 0){
return subYear;
}
//比较月
int subMonth = d1.getMonth() - d2.getMonth();
if(subMonth != 0){
return subMonth;
}
//比较日
int subDay = d1.getDay() - d2.getDay();
if(subDay != 0){
return subDay;
}
//在birthday相同的情况下比较name
return b1.getName().compareTo(b2.getName());
}
throw new RuntimeException("输入的数据不匹配!");
}
});
Employee e1 = new Employee("zhangxueyou", 51, new MyDate(1973, 4, 9));
Employee e2 = new Employee("liudehua", 52, new MyDate(1973, 4, 9));
Employee e3 = new Employee("guofucheng", 63, new MyDate(1942, 8, 11));
Employee e4 = new Employee("liming", 42, new MyDate(1942, 8, 9));
Employee e5 = new Employee("liangzhaowei", 66, new MyDate(1936, 6,19));
set.add(e1);
set.add(e2);
set.add(e3);
set.add(e4);
set.add(e5);
Iterator iterator = set.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
//结果
Employee{name='liangzhaowei', age=66, birthday=MyDate{year=1936, month=6, day=19}}
Employee{name='liming', age=42, birthday=MyDate{year=1942, month=8, day=9}}
Employee{name='guofucheng', age=63, birthday=MyDate{year=1942, month=8, day=11}}
Employee{name='liudehua', age=52, birthday=MyDate{year=1973, month=4, day=9}}
Employee{name='zhangxueyou', age=51, birthday=MyDate{year=1973, month=4, day=9}}
案例二: TreeMap的使用
//User.java
class User implements Comparable {
private String name;
private Integer age;
public User() {
}
public User(String name, Integer age) {
this.name = name;
this.age = age;
}
...
@Override
public int compareTo(Object o) {
if(o instanceof User){
User user = (User)o;
//按照姓名的字母从大到小排序
//return -user.name.compareTo(this.name);
int compara = user.name.compareTo(this.name);
if(compara != 0){
return compara;
}else {
//在姓名相同的情况下:比较年龄的,从小到大
return -Integer.compare(user.getAge(), this.getAge());
}
}else {
throw new RuntimeException("输入数据类型不一致");
}
}
}
示例:按照key自然排序
@Test
public void test5(){
TreeMap treeMap = new TreeMap();
User u1 = new User("Jack", 34);
User u2 = new User("Mary", 54);
User u3 = new User("Jam", 24);
User u4 = new User("Tom", 19);
treeMap.put(u1, 99);
treeMap.put(u2, 45);
treeMap.put(u3, 18);
treeMap.put(u4, 19);
Set set = treeMap.keySet();
Iterator iter = set.iterator();
while (iter.hasNext()){
Object key = iter.next();
Object value = treeMap.get(key);
System.out.println(key + "===" + value);
}
}
//结果
Person{name='Tom', age=19}===19
Person{name='Mary', age=54}===45
Person{name='Jam', age=24}===18
Person{name='Jack', age=34}===99
示例:按照key定制排序
@Test
public void test6(){
TreeMap treeMap = new TreeMap(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof User && o2 instanceof User){
User u1 = (User) o1;
User u2 = (User) o2;
//按照年龄 从小到大
return Integer.compare(u1.getAge(), u2.getAge());
}
throw new RuntimeException("输入数据不匹配");
}
});
User u1 = new User("Jack", 34);
User u2 = new User("Mary", 54);
User u3 = new User("Jam", 24);
User u4 = new User("Tom", 19);
treeMap.put(u1, 99);
treeMap.put(u2, 45);
treeMap.put(u3, 18);
treeMap.put(u4, 19);
Set set = treeMap.keySet();
Iterator iter = set.iterator();
while (iter.hasNext()){
Object key = iter.next();
Object value = treeMap.get(key);
System.out.println(key + "===" + value);
}
}
//结果
Person{name='Tom', age=19}===19
Person{name='Jam', age=24}===18
Person{name='Jack', age=34}===99
Person{name='Mary', age=54}===45
标签:name,MyDate,基础,public,User,Employee,new,javaSE,比较
From: https://www.cnblogs.com/bione/p/16815051.html