TreeSet与TreeMap实现自定义比较器

1.常见集合

  • 键值:Map集合等;

  • 单值存储:数组,List,Set,Queue集合等;

  • 我们知道部分的集合实现的原理不用,比如TreeMap底层采用红黑树,实现了排序的功能,其默认排序一般为从小到大排序数字,根据字典序排序字符等,但默认排序方式因为缺陷往往不能满足开发的需求,因此必须自己学会如何实现自定义比较器;

  • TreeSet与TreeMap可以代表大部分集合实现自定义比较器的操作,因此以TreeSet与TreeMap为例;

2.TreeMap默认排序与自定义比较器实现

       1.TreeMap部分源码;


     // 调用compare比较两个key值
     cmp = cpr.compare(key, t.key);
     if (cmp < 0)
        t = t.left;
     else if (cmp > 0)
        t = t.right;
     else
        return t.setValue(value);
        
    final int compare(Object k1, Object k2) {
        // 调用默认的比较器,实现默认排序
        return comparator==null ? ((Comparable)k1).compareTo((K)k2)
            : comparator.compare((K)k1, (K)k2);
    }

    2.测试以Integer为键类型的默认排序;

package test;

import java.util.Map.Entry;
import java.util.TreeMap;

public class MyTreeMap {
	//public static TreeMap studentMap = new TreeMap<>();
	public static TreeMap intergerMap = new TreeMap<>();
	
	public static void main(String[] args) {
		// 给集合中添加10个student对象
		for (int i = 10; i > 0; --i) {
			//studentMap.put(new Student(i, "小王" + i), i);
			intergerMap.put(i, new Student(i, "小王" + i));
		}
		// 打印集合中的元素
		while(!intergerMap.isEmpty()) {
			Entry firstEntry = intergerMap.pollFirstEntry();
			System.out.println(firstEntry.getValue().toString());
		}
	}
}

class Student {
	int age;
	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 String toString() {
		return "Student [age=" + age + ", name=" + name + "]";
	}

	public Student(int age, String name) {
		super();
		this.age = age;
		this.name = name;
	}
}
        // 输出结果

        /*

        Student [age=1, name=小王1]
        Student [age=2, name=小王2]
        Student [age=3, name=小王3]
        Student [age=4, name=小王4]
        Student [age=5, name=小王5]
        Student [age=6, name=小王6]
        Student [age=7, name=小王7]
        Student [age=8, name=小王8]
        Student [age=9, name=小王9]
        Student [age=10, name=小王10]
        */

     由默认排序结果可以看出,IntegerMap根据键(Interger)从小到大进行排序;

3.自定义比较器,根据键从大到小进行排序

   1.初始化TreeMap时实现匿名内部类Comparator,实现根据Interger键从大到小排序

 

package test;

import java.util.Map.Entry;
import java.util.Comparator;
import java.util.TreeMap;

public class MyTreeMap {
	public static TreeMap intergerMap = new TreeMap<>(new Comparator() {

		@Override
		public int compare(Integer o1, Integer o2) {
			Integer integer1 = (Integer)01;
			Integer integer2 = (Integer)o2;
			return integer1 > integer2? 1:-1;
		}
	});
	public static void main(String[] args) {
		// 给集合中添加10个student对象
		for (int i = 1; i < 11; ++i) {
			//studentMap.put(new Student(i, "小王" + i), i);
			intergerMap.put(i, new Student(i, "小王" + i));
		}
		// 打印集合中的元素
		while(!intergerMap.isEmpty()) {
			Entry firstEntry = intergerMap.pollFirstEntry();
			System.out.println(firstEntry.getValue().toString());
		}
	}
}

class Student {
	int age;
	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 String toString() {
		return "Student [age=" + age + ", name=" + name + "]";
	}

	public Student(int age, String name) {
		super();
		this.age = age;
		this.name = name;
	}

}               
        
        // 测试结果
        /*
        Student [age=10, name=小王10]
        Student [age=9, name=小王9]
        Student [age=8, name=小王8]
        Student [age=7, name=小王7]
        Student [age=6, name=小王6]
        Student [age=5, name=小王5]
        Student [age=4, name=小王4]
        Student [age=3, name=小王3]
        Student [age=2, name=小王2]
        Student [age=1, name=小王1]
        */

 

      2.初始化TreeMap时,将comparator的实现类进行传参,实现根据Interger从大到小排序;

package test;

import java.util.Map.Entry;
import java.util.Comparator;
import java.util.TreeMap;

public class MyTreeMap {
	static MyCompare com = new MyCompare();
	public static TreeMap intergerMap = new TreeMap<>(com);
	
	public static void main(String[] args) {
		// 给集合中添加10个student对象
		for (int i = 1; i < 11; ++i) {
			//studentMap.put(new Student(i, "小王" + i), i);
			intergerMap.put(i, new Student(i, "小王" + i));
		}
		// 打印集合中的元素
		while(!intergerMap.isEmpty()) {
			Entry firstEntry = intergerMap.pollFirstEntry();
			System.out.println(firstEntry.getValue().toString());
		}
	}
}

class Student {
	int age;
	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 String toString() {
		return "Student [age=" + age + ", name=" + name + "]";
	}

	public Student(int age, String name) {
		super();
		this.age = age;
		this.name = name;
	}

} 
class MyCompare implements Comparator{

	@Override
	public int compare(Object o1, Object o2) {
		Integer integer1 = (Integer)o1;
		Integer integer2 = (Integer)o2;
		return integer1 > integer2?-1:1;
	}
	
}              
        
        // 测试结果
        /*
        Student [age=10, name=小王10]
        Student [age=9, name=小王9]
        Student [age=8, name=小王8]
        Student [age=7, name=小王7]
        Student [age=6, name=小王6]
        Student [age=5, name=小王5]
        Student [age=4, name=小王4]
        Student [age=3, name=小王3]
        Student [age=2, name=小王2]
        Student [age=1, name=小王1]
        */ 
  

4.键为对象时,进行自定义排序

     1.student对象实现compare接口的compareTo方法,根据age从大到小排序;

package test;

import java.util.Map.Entry;
import java.util.Comparator;
import java.util.TreeMap;

public class MyTreeMap {
	public static TreeMap studentMap = new TreeMap<>();
	public static void main(String[] args) {
		// 给集合中添加10个student对象
		for (int i = 1; i < 11; ++i) {
			studentMap.put(new Student(i, "小王" + i), i);
		}
		// 打印集合中的元素
		while(!studentMap.isEmpty()) {
			Entry firstEntry = studentMap.pollFirstEntry();
			System.out.println(firstEntry.getKey().toString());
		}
	}
}

class Student implements Comparable{
	int age;
	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 String toString() {
		return "Student [age=" + age + ", name=" + name + "]";
	}

	public Student(int age, String name) {
		super();
		this.age = age;
		this.name = name;
	}

	@Override
	public int compareTo(Object o) {
		Student student = (Student)o;
		return this.age < student.age? 1: -1;
	}
	
}
            /*
                Student [age=10, name=小王10]
                Student [age=9, name=小王9]
                Student [age=8, name=小王8]
                Student [age=7, name=小王7]
                Student [age=6, name=小王6]
                Student [age=5, name=小王5]
                Student [age=4, name=小王4]
                Student [age=3, name=小王3]
                Student [age=2, name=小王2]
                Student [age=1, name=小王1]
            */ 
  

2.初始化是实现匿名内部类Comparator,实现根据age从大到小排序

package test;

import java.util.Map.Entry;
import java.util.Comparator;
import java.util.TreeMap;

public class MyTreeMap {
	public static TreeMap studentMap = new TreeMap<>(new Comparator() {

		@Override
		public int compare(Student o1, Student o2) {
			Student student1 = (Student)o1;
			Student student2 = (Student)o2;
			return student1.age <  student2.age? 1 : -1;
		}
	});
	public static void main(String[] args) {
		// 给集合中添加10个student对象
		for (int i = 1; i < 11; ++i) {
			studentMap.put(new Student(i, "小王" + i), i);
		}
		// 打印集合中的元素
		while(!studentMap.isEmpty()) {
			Entry firstEntry = studentMap.pollFirstEntry();
			System.out.println(firstEntry.getKey().toString());
		}
	}
}

class Student {
	int age;
	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 String toString() {
		return "Student [age=" + age + ", name=" + name + "]";
	}

	public Student(int age, String name) {
		super();
		this.age = age;
		this.name = name;
	}

	 /*
                Student [age=10, name=小王10]
                Student [age=9, name=小王9]
                Student [age=8, name=小王8]
                Student [age=7, name=小王7]
                Student [age=6, name=小王6]
                Student [age=5, name=小王5]
                Student [age=4, name=小王4]
                Student [age=3, name=小王3]
                Student [age=2, name=小王2]
                Student [age=1, name=小王1]
            */
	
}

3. 初始化TreeMap时,将comparator的实现类进行传参,实现根据Interger从大到小排序;

package test;

import java.util.Map.Entry;
import java.util.Comparator;
import java.util.TreeMap;

public class MyTreeMap {
	static Mycompare cMycompare = new  Mycompare();
	public static TreeMap studentMap = new TreeMap<>(cMycompare);
	public static void main(String[] args) {
		// 给集合中添加10个student对象
		for (int i = 1; i < 11; ++i) {
			studentMap.put(new Student(i, "小王" + i), i);
		}
		// 打印集合中的元素
		while(!studentMap.isEmpty()) {
			Entry firstEntry = studentMap.pollFirstEntry();
			System.out.println(firstEntry.getKey().toString());
		}
	}
}

class Student {
	int age;
	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 String toString() {
		return "Student [age=" + age + ", name=" + name + "]";
	}

	public Student(int age, String name) {
		super();
		this.age = age;
		this.name = name;
	}
}

class Mycompare implements Comparator{

	@Override
	public int compare(Object o1, Object o2) {
		Student student1 = (Student)o1;
		Student student2 = (Student)o2;
		return student1.age < student2.age ? 1 : -1;
	}
	
}
 /*
                Student [age=10, name=小王10]
                Student [age=9, name=小王9]
                Student [age=8, name=小王8]
                Student [age=7, name=小王7]
                Student [age=6, name=小王6]
                Student [age=5, name=小王5]
                Student [age=4, name=小王4]
                Student [age=3, name=小王3]
                Student [age=2, name=小王2]
                Student [age=1, name=小王1]
            */ 
  

3.TreeSet的默认排序与自定义比较器

      TreeSet的底层实现相似于TreeMap,可以将TreeSet看作TreeMap的vlalue值为object,而TreeSet值可以认为TreeMap的键,依次可以知道,TreeSet的比较用法;

4.总结

   1.当要排序的对象实现目标为基本类型时

  • 实现匿名内部类Comparator,作为集合的构造参数;
  • 实现Comparator的实现类作为集合的构造参数

   2.当要排序的对象实现目标为对象时

  • 实现匿名内部类Comparator,作为集合的构造参数;
  • 实现Comparator的实现类作为集合的构造参数
  • 对象实现compareable接口的compareTo方法

   3.以上为简单的总结,实际的开发中,比较器的构造比较灵活,大家根据情况实现;

你可能感兴趣的:(TreeSet与TreeMap实现自定义比较器)