• java学习--day18(TreeSet底层&内部类)



    昨天总结:

    ArrayList:就是单纯的add
    LinkedList: 也是单纯的add
    HashSet: 不单纯 得重写equals 和hashCode 方法
    TreeSet:不单纯  得在类中去实现Comparable这个接口  让类具有比较排序功能
    开发中使用ArrayList
    
    • 1
    • 2
    • 3
    • 4
    • 5

    资料:

    数据结构学习:http://data.biancheng.net/view/192.html

    java8官方文档:https://www.matools.com/api/java8

    1.二叉树的了解

    通过查阅API我们得知TreeSet集合是基于TreeMap的实现,而TreeMap是基于二叉树(红黑树)结构,也就是说TreeSet集合的底层使用的二叉树(红黑树)结构。
    
    树结构:它也是数据结构中的一种。在计算机领域中树结构指的是倒立的树。
    
    树结构存储的数据,每个数据也需要节点来保存。
    
    而TreeSet集合底层是二叉树的数据结构,什么是二叉树呢?
    
    二叉树:每个节点的下面最多只能有2个子节点。
    
    说明:最多表示一个节点下面可以有两个子节点或者一个子节点或者没有子节点。
    
    在二叉树的根节点左侧的节点称为左子树,在根节点的右侧的节点称为右子树。
    
    既然已经得知TreeSet集合底层是二叉树,那么二叉树是怎样存储数据的呢?是怎样保证存储的数据唯一并有序的呢?
    
    二叉树的存储流程:
    
    当存储一个元素的时候,如果是树的第一个元素,这个元素就作为根节点。
    
    如果不是第一个元素,那么就拿要存储的元素与根节点进行比较大小:
    
    大于根元素:就将要存储的元素放到根节点的右侧,作为右叶子节点。
    
    等于根元素:丢弃。
    
    小于根元素:就将要存储的元素放到根节点的左侧,作为左叶子节点。
    
    总结:二叉树是通过比较大小来保证元素唯一和排序的。
    20  10  31  5  13  23 51
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    案例:

    ​ 使用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);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    案例:

    ​ TreeSet里面存的是Dog类,

    ​ 两个属性: String name, int age

    ​ 先按照字符串的字典顺序排,然后字符串相等的话,在按照年龄排

    字符串也有compareTo方法,按字典顺序比较两个字符串。 比较是基于字符串中每个字符的Unicode值

    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);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    总结:使用TreeSet的时候需要类实现一个接口 Comparable这个接口去做比较排序

    但是就只有这一种方式进行排序吗?不是的!!!还有一种比较器的写法Comparator这个接口

    2.使用比较器将数据存储到TreeSet中

    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);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    3.匿名内部类

    为了减少代码量

    3.1基于抽象类的匿名内部类
    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();
    
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    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();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    3.2基于接口的匿名内部类
    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();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    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);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    真实开发的时候,一个方法参数是一个接口对象,不用再新建一个类去实现这个接口,直接方法中去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();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    4.内部类

    从字面意思来理解:在类的内部创建一个类,这个类叫内部类

    了解即可,开发禁止使用(效率太低)

    4.1成员内部类

    在类的方法的外面再类中,就是成员内部类

    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
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
  • 相关阅读:
    如何使用 Lambda 导出 EXCEL,并且实现本地调试
    苏州科技大学、和数联合获得国家知识产权局颁发的3项发明专利证书
    HTB-ScriptKiddie
    calibre部署指南:docker一键部署calibre在线书库
    Vue常用方法汇总
    Rust升级慢,使用国内镜像进行加速
    05 RocketMQ - Consumer 源码分析
    jquery-leonaScroll-1.1-自定义滚动条插件
    安全狗助力厦门“单一窗口”开展网络安全应急演练
    Jetbrains idea整合远程的docker服务器
  • 原文地址:https://blog.csdn.net/m0_46202060/article/details/133136774