1. Comparable---接口(集合中元素实现此接口,元素具有可比性)
Comparable可以认为是一个内比较器,实现了Comparable接口的类有一个特点,就是这些类是可以和自己比较的,至于具体和另一个实现了Comparable接口的类如何比较,则依赖compareTo方法的实现,compareTo方法也被称为自然比较方法。如果开发者add进入一个Collection的对象想要Collections的sort方法帮你自动进行排序的话,那么这个对象必须实现Comparable接口。compareTo(Object o)方法的返回值是int,且此方法只有一个参数,返回值有三种情况:
1、返回正整数
2、返回0
3、返回负整数
可以这么理解:返回1表示当前元素排在与之对比的元素后面,返回-1表示当前元素排在与之对比的元素前面,返回0表示不排序(按其原顺序排列)。(其实并不是1,-1,0;只要是正数负数和0就可以进行区分)。
元素自身可以理解为基准,而参数上的obj可以理解为与之对比的元素。
1.比如我们想比较人的时候按年龄倒序排列
思路:实现上面接口,如果与之对比的元素年龄比他大,排在他前面(返回负数),否则排在他后面(返回正数)。
例如:
public class Person implements Comparable<Person> {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int compareTo(Person o) {
if(this.age > o.getAge()){//返回负数表示比他大的排在他前面
return -1;
}
if(this.age < o.getAge()){//返回整数表示比他小的排在他后面
return 1;
}
return 0;
}
public Person(int age, String name) {
super();
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Person [age=" + age + ", name=" + name + "]";
}
}
测试:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Test1 {
public static void main(String[] args) {
List<Person> list = new ArrayList<>();
list.add(new Person(20, "张三"));
list.add(new Person(22, "李四"));
list.add(new Person(19, "王五"));
list.add(new Person(19, "张是"));
list.add(new Person(17, "开发"));
list.add(new Person(29, "看"));
Collections.sort(list);
for(Person p : list){
System.out.println(p);
}
}
}
结果:
Person [age=29, name=看]
Person [age=22, name=李四]
Person [age=20, name=张三]
Person [age=19, name=王五]
Person [age=19, name=张是]
Person [age=17, name=开发]
2.按照上面的思路我们写一个按年龄正序排列
修改上面的compareTo方法:
@Override
public int compareTo(Person o) {
if(this.age > o.getAge()){//返回正数表示比他大的排在他后面
return 10;
}
if(this.age < o.getAge()){//返回负数表示比他小的排在他前面
return -1;
}
return 0;
}
测试代码还是上面代码,查看结果:
Person [age=17, name=开发]
Person [age=19, name=王五]
Person [age=19, name=张是]
Person [age=20, name=张三]
Person [age=22, name=李四]
Person [age=29, name=看]
3.将自身具有可比性的元素存入TreeSet或者TreeMap进行查看(TreeSet会自动将元素排序,元素作为key的时候TreeMap会根据key排序)
public class Person implements Comparable<Person> {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public int compareTo(Person o) {
if(this.age > o.getAge()){//返回负数表示比他大的排在他前面
return -1;
}
if(this.age < o.getAge()){//返回整数表示比他小的排在他后面
return 1;
}
return 0;
}
public Person(int age, String name) {
super();
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Person [age=" + age + ", name=" + name + "]";
}
}
测试代码:
package cn.qlq.test;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
public class TreeSetTest {
public static void main(String[] args) {
Set<Person> list = new TreeSet<>();
list.add(new Person(20, "张三"));
list.add(new Person(22, "李四"));
list.add(new Person(19, "王五"));
list.add(new Person(19, "张是"));
list.add(new Person(17, "开发"));
list.add(new Person(29, "看"));
for(Person p : list){
System.out.println(p);
}
System.out.println("-----------------------------");
//作为key会将key排序
Map map = new TreeMap();
map.put(new Person(20, "张三"), "1");
map.put(new Person(22, "李四"), "2");
map.put(new Person(19, "张三"), "3");
map.put(new Person(25, "哇塞"), "4");
for(Object key :map.keySet()){
System.out.println(key+"\t"+map.get(key));
}
System.out.println("-----------------------------");
//作为value无效
Map map2 = new TreeMap();
map2.put("1",new Person(20, "张三"));
map2.put("2",new Person(22, "李四"));
map2.put("3",new Person(19, "张三"));
map2.put("4",new Person(25, "哇塞"));
for(Object key :map2.keySet()){
System.out.println(key+"\t"+map2.get(key));
}
}
}
结果:
Person [age=29, name=看]
Person [age=22, name=李四]
Person [age=20, name=张三]
Person [age=19, name=王五]
Person [age=17, name=开发]
-----------------------------
Person [age=25, name=哇塞] 4
Person [age=22, name=李四] 2
Person [age=20, name=张三] 1
Person [age=19, name=张三] 3
-----------------------------
1 Person [age=20, name=张三]
2 Person [age=22, name=李四]
3 Person [age=19, name=张三]
4 Person [age=25, name=哇塞]
2. Comparator---接口(可以理解为比较器,给集合传递比较器集合具有可比性)
Comparator相当于外部比较器,其作为参数传给具有可比性的集合,使集合具有可比性。比如: TreeSet ts = new TreeSet(new MyComparator()); 比较器需要重写compareTo(Object o1,Object o2)方法,返回值也是下面三个值:
1、返回正整数
2、返回0
3、返回负整数
可以这么理解:返回1表示当前元素排在与之对比的元素后面,返回-1表示当前元素排在与之对比的元素前面,返回0表示不排序(按其原顺序排列)。(其实并不是1,-1,0;只要是正数负数和0就可以进行区分)
compareTo(Object o1,Object o2)方法的第一个参数可以理解为基准,而参数上的第二个参数可以理解为与之对比的元素。
1.比如我们想比较人的时候按年龄倒序排列
public class Person{
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person(int age, String name) {
super();
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Person [age=" + age + ", name=" + name + "]";
}
}
比较器类:(可以理解为第一个参数是基准,第二个参数是与之对比的元素,返回-1表示基准排在与之对比元素前面,返回1表示基准在与之对比的元素后面)
import java.util.Comparator;
public class PersonComparator implements Comparator<Person> {
/**
* 第一个参数可以理解为基准,第二个是与之比较多元素 。返回负数表示排在其前面,返回正数表示排在其后面
*/
@Override
public int compare(Person o1, Person o2) {
if (o1.getAge() > o2.getAge()) {// 返回正数表示比他大的排在他后面
return -1;
}
if (o1.getAge() < o2.getAge()) {
return 1;
}
return 0;
}
}
测试代码:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Test1 {
public static void main(String[] args) {
List<Person> list = new ArrayList<>();
list.add(new Person(20, "张三"));
list.add(new Person(22, "李四"));
list.add(new Person(19, "王五"));
list.add(new Person(19, "张是"));
list.add(new Person(17, "开发"));
list.add(new Person(29, "看"));
Collections.sort(list,new PersonComparator());
for(Person p : list){
System.out.println(p);
}
}
}
结果:
Person [age=29, name=看]
Person [age=22, name=李四]
Person [age=20, name=张三]
Person [age=19, name=王五]
Person [age=19, name=张是]
Person [age=17, name=开发]
2.将一个比较器传入TreeSet或者TreeMap是集合有序,或者TreeMap的key值有序(也就是TreeMap排序是将key排序)
TreeSet中的元素会自动排序,根据传下来的比较器对里面的元素进行排序。TreeMap传入比较器的话是元素作为key才可以排序,如果传入比较器但是key不是比较器指定的元素会报错。。。。。。。
比较器:
package cn.qlq.test;
import java.util.Comparator;
public class PersonComparator implements Comparator<Person> {
/**
* 第一个参数可以理解为基准,第二个是与之比较多元素 。返回负数表示排在其前面,返回正数表示排在其后面
*/
@Override
public int compare(Person o1, Person o2) {
if (o1.getAge() > o2.getAge()) {// 返回正数表示比他大的排在他后面
return 10;
}
if (o1.getAge() < o2.getAge()) {
return -10;
}
return 0;
}
}
测试代码:
package cn.qlq.test;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
public class TreeSetTest {
public static void main(String[] args) {
Set<Person> list = new TreeSet<>(new PersonComparator());
list.add(new Person(20, "张三"));
list.add(new Person(22, "李四"));
list.add(new Person(19, "王五"));
list.add(new Person(19, "张是"));
list.add(new Person(17, "开发"));
list.add(new Person(29, "看"));
for(Person p : list){
System.out.println(p);
}
System.out.println("-----------------------------");
//作为key不会报错,会将key排序
Map map = new TreeMap(new PersonComparator());
map.put(new Person(20, "张三"), "1");
map.put(new Person(22, "李四"), "2");
map.put(new Person(19, "张三"), "3");
map.put(new Person(25, "哇塞"), "4");
for(Object key :map.keySet()){
System.out.println(key+"\t"+map.get(key));
}
//作为value报错
Map map2 = new TreeMap(new PersonComparator());
map2.put("1",new Person(20, "张三"));
map2.put("2",new Person(22, "李四"));
map2.put("3",new Person(19, "张三"));
map2.put("4",new Person(25, "哇塞"));
for(Object key :map2.keySet()){
System.out.println(key+"\t"+map2.get(key));
}
}
}
结果:
Person [age=17, name=开发]
Person [age=19, name=王五]
Person [age=20, name=张三]
Person [age=22, name=李四]
Person [age=29, name=看]
-----------------------------
Person [age=19, name=张三] 3
Person [age=20, name=张三] 1
Person [age=22, name=李四] 2
Person [age=25, name=哇塞] 4
-----------------------------
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to cn.qlq.test.Person
at cn.qlq.test.PersonComparator.compare(PersonComparator.java:1)
at java.util.TreeMap.compare(Unknown Source)
at java.util.TreeMap.put(Unknown Source)
at cn.qlq.test.TreeSetTest.main(TreeSetTest.java:37)