回顾
1·Object
toString()
equals()
hashCode()
2.hashSet这个类
3.TreeSet这个类
1.TreeSet的底层
2.匿名内部类【开发用的】
3.内部类
4.map
通过查阅API我们得知TreeSet集合是基于TreeMap的实现,而TreeMap是基于二叉树(红黑树)结构,也就是说TreeSet集合的底层使用的二叉树(红黑树)结构。
树结构:它也是数据结构中的一种。在计算机领域中树结构指的是倒立的树。
树结构存储的数据,每个数据也需要节点来保存。
而TreeSet集合底层是二叉树的数据结构,什么是二叉树呢?
二叉树:每个节点的下面最多只能有2个子节点。
说明:最多表示一个节点下面可以有两个子节点或者一个子节点或者没有子节点。
在二叉树的根节点左侧的节点称为左子树,在根节点的右侧的节点称为右子树。
既然已经得知TreeSet集合底层是二叉树,那么二叉树是怎样存储数据的呢?是怎样保证存储的数据唯一并有序的呢?
二叉树的存储流程:
当存储一个元素的时候,如果是树的第一个元素,这个元素就作为根节点。
如果不是第一个元素,那么就拿要存储的元素与根节点进行比较大小:
大于根元素:就将要存储的元素放到根节点的右侧,作为右叶子节点。
等于根元素:丢弃。
小于根元素:就将要存储的元素放到根节点的左侧,作为左叶子节点。
总结:二叉树是通过比较大小来保证元素唯一和排序的。
20 10 31 5 13 23 51
http://data.biancheng.net/view/192.html
案例:
? 使用TreeSet存储Employee对象,比较两个属性
? int age, int weight 先按照年龄进行升序排,如果年龄相等的话,按照体重升序排
package com.qfedu.a_treeset;
import java.util.Set;
import java.util.TreeSet;
class Employee implements Comparable<Employee>{
String name;
int age;
int weight;
public Employee(String name, int age, int weight) {
this.name = name;
this.age = age;
this.weight = weight;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", age=" + age +
", weight=" + weight +
'}';
}
@Override
public int compareTo(Employee o) {
//先按照年两比,如果年龄相等 就比较体重
int num = this.age - o.age;
if (num == 0) {
int num1 = o.weight - this.weight;
return num1;
}
return num;
}
}
public class Demo2 {
public static void main(String[] args) {
Set<Employee> set = new TreeSet<>();
set.add(new Employee("广坤", 35, 78));
set.add(new Employee("二贝", 26, 70));
set.add(new Employee("赵四", 35, 72));
set.add(new Employee("彩云", 35, 79));
set.add(new Employee("鸡哥", 32, 59));
set.add(new Employee("正经博", 32, 59));
System.out.println(set);
}
}
案例:
? TreeSet里面存的是Dog类,
? 两个属性: String name, int age
? 先按照字符串的字典顺序排,然后字符串相等的话,在按照年龄排
package com.qfedu.a_treeset;
import java.util.Set;
import java.util.TreeSet;
class Dog implements Comparable<Dog>{
String name;
int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Dog o) {
//先按照字典的顺序进行排,如果字符串相等再按照年龄升序排
int num = this.name.compareTo(o.name);
if (num == 0) {
//字符串相等的情况,又要比较年领
int num1 = this.age - o.age;
return num1;
}
return num;
}
}
public class Demo3 {
public static void main(String[] args) {
Set<Dog> set = new TreeSet<>();
set.add(new Dog("彩云", 5));
set.add(new Dog("旺财", 2));
set.add(new Dog("大黄", 6));
set.add(new Dog("大黄", 3));
set.add(new Dog("大黄", 4));
System.out.println(set);
}
}
总结:使用TreeSet的时候需要类实现一个接口 Comparable这个接口去做比较排序
但是就只有这一种方式进行排序吗?不是的!!!还有一种比较器的写法Comparator这个接口
package com.qfedu.b_comparator;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
class Student {
String name;
int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
class MyComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
int num = o1.age - o2.age;
return num;
}
}
public class Demo1 {
public static void main(String[] args) {
//如果想要使用比较器的写法 必须再new TreeSet的时候
//加上比较器对象
//TreeSet 有一个有参构造,有参构造的方法是Comparwator的对象
//Comparator是一个接口 不能实例化,咋办?再写一个类去实现这个接口
Set<Student> students = new TreeSet<>(new MyComparator());
students.add(new Student("维一", 23));
students.add(new Student("永康", 19));
students.add(new Student("赵娜", 18));
students.add(new Student("运铎", 28));
students.add(new Student("佳祥", 36));
System.out.println(students);
}
}
总结:
ArrayList:就是单纯的add
LinkedList: 也是单纯的add
HashSet: 不单纯 得重写equals 和hashCode 方法
TreeSet:不单纯 得在类中去实现Comparable这个接口 让类具有比较排序功能
开发中使用ArrayList
为了减少代码量
package com.qfedu.c_anno;
//声明一个抽象列类
abstract class Person {
public abstract void eat();
public void sleep() {
System.out.println("好想逃,然后去睡觉!!!");
}
}
//常规来讲,新建一个类 去继承抽象类。然后实例化继承的抽象类的类
//class Man extends Person {
//
// @Override
// public void eat() {
// System.out.println("好饿,想吃肉!!!");
// }
//}
public class Demo1 {
public static void main(String[] args) {
//匿名内部类:在实例化对抽象类同时并重写抽象方法
Person person = new Person(){
@Override
public void eat() {
System.out.println("吃吃喝喝");
}
};
person.eat();
person.sleep();
}
}
package com.qfedu.c_anno;
abstract class Animal{
public abstract void call();
public abstract void call1();
}
public class Demo2 {
public static void main(String[] args) {
new Animal(){
@Override
public void call() {
System.out.println("哇哇叫!!!");
}
@Override
public void call1() {
System.out.println("哈哈叫");
}
}.call();
new Animal(){
@Override
public void call() {
System.out.println("哇哇叫!!!");
}
@Override
public void call1() {
System.out.println("哈哈叫");
}
}.call1();
}
}
package com.qfedu.c_anno;
interface A {
void testA();
}
public class Demo3 {
public static void main(String[] args) {
// A a = new A(){
//
// @Override
// public void testA() {
// System.out.println("嘻嘻哒");
// }
// };
// a.testA();
new A(){
@Override
public void testA() {
System.out.println("哈哈");
}
}.testA();
}
}
package com.qfedu.c_anno;
import java.util.Comparator;
import java.util.TreeSet;
import java.util.Set;
class Student {
String name;
int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Demo4 {
//存到TreeSet里面
public static void main(String[] args) {
Set<Student> set = new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
int num = o1.age - o2.age;
return num;
}
});
set.add(new Student("维一", 23));
set.add(new Student("永康", 19));
set.add(new Student("赵娜", 18));
set.add(new Student("运铎", 28));
set.add(new Student("佳祥", 36));
System.out.println(set);
}
}
真实开发的时候,一个方法参数是一个接口对象,不用再新建一个类去实现这个接口,直接方法中去new 接口
package com.qfedu.c_anno;
interface B {
void eat();
}
public class Demo5 {
public static void main(String[] args) {
test(new B() {
@Override
public void eat() {
System.out.println("吃锦旗");
}
});
}
public static void test (B b) {
b.eat();
}
}
从字面意思来理解:在类的内部创建一个类,这个类叫内部类
在类的方法的外面再类中,就是成员内部类
package com.qfedu.d_inner;
class MemberDemo {
String name = "张三";
int age = 20;
public void printf() {
System.out.println("打印着玩");
}
class Inner {//就是内部类
String name = "李四";
//在Inner这个类中可以访问外部类的属性和方法
public void test () {
printf();//打印着玩
System.out.println(age);//20
System.out.println(name);//李四
//如果访问外部特定的属性的时候: 类名.this.属性
System.out.println(MemberDemo.this.name);//张三
}
}
}
public class Demo1 {
public static void main(String[] args) {
//成员内部类的创建步骤:
//1.实例化外部类 类对象
MemberDemo memberDemo = new MemberDemo();
//2.实例化内部类对象,但是new得改为 外部对象.new
MemberDemo.Inner inner = memberDemo.new Inner();
inner.test();
}
}
作业:
1.写博客
2.总结一下今天的东西
3.内部类
4.http://data.biancheng.net/view/192.html
5.书面作业