Java基础学习笔记上

一、JDK与JRE

1. JDK是开发工具包,包含三部分:

  • jvm虚拟机:Java程序运行的地方
  • 核心类库:Java已经写好的
  • 开发工具:Javac、Java、jdb……

2. JRE是Java运行环境,包含三部分:

  • jvm
  • 核心类库
  • 运行工具

3. JDK、JRE、JVM三者关系

JDK包含JRE、JRE包含JVM

二、算术运算符

1. 隐式转换小结

  • 取值范围:byte<short<int<long<float<doule
  • byte、short、char会自提升为int,再计算

三、面向对象

1. 面向对象的介绍:

  • 面向:拿、找
  • 对象:能干活的东西
  • 面向对象:拿能干活的东西做对应的事

2. 构造器

  • 创建对象的时候, 虚拟机自动调用构造器,其作用是初始化成员变量
  • 创建对象是 new 的事,而不是 构造器 的事
  • 分为有参和无参构造器且构成重载
  • 推荐把无参构造器和带有所有成员变量的构造器都写出来

3. ptg

  • 标准JavaBean插件

4. 对象的内存图

(1)创建对象虚拟机至少做了以下7步:

  • 加载class文件
  • 申明局部变量
  • 在堆空间中开辟一个空间
  • 默认初始化
  • 显示初始化
  • 构造器初始化
  • 将堆内存中的地址赋值给左边的局部变量

(2)一个对象的内存图

public class Student{
    String name;
    int age;

    public void study(){
        sout("好好学习");
    }
}


public class SudentTest{
    public static void mian(String[] args){
        Student s = new Student();
        sout(s)
        s.name = "阿龙";
        s.age = 21;
        s.study()
    }
}

内存图

5. StringBuilder介绍

  • StringBuilder 是线程不安全的,效率比较高,是可变的
  • 应用场景主要:字符串拼接 和 字符串反转
  • 添加方法是 append()
  • 默认容量为 16 字节
  • 第一次扩容为 16*2+2=34,超过34以后以实际字符长度为容量,最大容量为 Int 最大值

6. StringJoiner介绍

  • StringJoiner 是可变的,JDk8出现
  • 添加属性是 add()
  • length() 求的是所有的长度包括开始符号、结束符号、间隔符号
  • StringJoiner stringJoiner = new StringJoiner(",") 这是以 "," 为间隔
  • StringJoiner stringJoiner = new StringJoiner(",", "[", "]"); 这是以"," 间隔 、"[" 开始、"]" 结束

7. 封装的介绍

  • 对象代表什么,就得封装对应的数据,并提供数据对应的行为

8. 继承的介绍

  • 可以把子类中重复的代码抽取到父类中,子类可以直接使用,从而减少代码的冗余,提高代码的复用性
  • 只支持单继承,不支持多继承,但支持多层继承

9. 多态的介绍

  1. 多态:同类型的对象,表现出的不同形态
  2. 成员属性:编译时看左边,运行时也看左边
  3. 成员方法:编译时看左边 ,运行时看右边

    class Fu{
    
        String name = "父亲";
        int age = 40;
        public void work(){
            sout("父亲在工作");
        }
    
    
    }
    

    class Zi {

        String name = "儿子"
        int age = 21;
        @Override
        public void work(){
            sout("儿子在工作");
        }

 }

class Test{

    public static void main(String[] args){
        Fu f = new Zi();
        sout(f.name);//父亲
        f.work();//儿子在工作
    }   


}
  1. 多态的前提
    • 需要有继承/实现关系
    • 有父类引用指向子类对象 Fu f = new Zi()
    • 有方法重写
  2. 多态的优势
    • 在多态形态下,右边对象可以实现解耦合,便于扩展与维护
    • 定义方法时,使用父类作为参数,可以接收所有子类对象,体现多态的扩展性与便利
  3. 多态的弊端
    • 使用Fu f = new Zi()创建对象时,子类扩展的方法不能调用
    • 解决方案:Zi z = (Zi) f

10. final介绍

  • final是最终类,不能被继承
  • final是最终方法,不能被重写
  • final叫做常量,只能被赋值一次,不能被修改;修饰基本类型常量,值不能被修改;修饰引用数据类型,地址值不能被修改,其内容可以被修改

11. 代码块

  • 局部代码块:提前结束变量的生命周期(已淘汰)
  • 构造代码块:抽取构造方法中重复的代码(不够灵活)
  • 静态代码块:随着类的加载而加载,只能被加载一次;可以做数据的初始化

12. 抽象类和抽象方法的介绍

  • 抽象类的作用:抽取共性时,无法确定方法体,就把方法定义为抽象的。强制子类按照某种格式重写。抽象方法所在的类必须是抽象类
  • 抽象类不能实例化
  • 抽象类中不一定有抽象方法,有抽象方法的一定是抽象类
  • 可以有构造方法
  • 抽象类的子类:要么重写抽象类的所有抽象方法,要么是抽象类

13. 接口(interface)的介绍

  • 接口就是一种规则
  • 接口不能实例化
  • 接口成员的特点:
    1. 成员变量:只能是常量,默认修饰符:public static final
    2. 构造方法:没有
    3. 成员方法:只能是抽象方法,默认修饰符:public abstract
    4. JDk7以前:接口中只能定义抽象方法
    5. JDk8的新特性:接口中可以定义有方法体的方法
    6. JDK9的新特性:接口中可以定义私有方法
14. 接口和类的关系
  • 类和类的关系:是继承关系,只允许单继承,不允许多继承,但可以多层继承
  • 类和接口的关系:是实现关系,可以单实现,也可以多实现,还可以继承一个类的同时实现多个接口
  • 接口和接口的关系:是继承关系,可以单继承,也可以多继承,但底层的实现类需要重写该体系的所有抽象方法

15.适配器的介绍

  • 当一个接口中抽象方法过多时,但我只要使用其中一部分的时候,就可以采用适配器的设计模式
  • 书写步骤:
    1. 编写中间类XXXAdapter,实现对应的接口。对接口中的抽象方法进行空实现
    2. 让真正的实现类继承中间类,并重新需要的方法,为了避免其他类创建适配器的对象,中间的适配器类用abstrac进行修饰

16. 内部类的介绍

  1. 内部类的访问特点:

    • 内部类可以直接访问外部类的成员,包括私有
    • 外部类不能直接访问内部类的成员,必须创建对象

      public class Car {

      private String carName;//车名
      //内部类
      class Engine{
          String engineName;//引擎名字
          public void show(){
              suot(carName);直接调用
          }
      } 
      
      public void show(){
          sout(engineName);错误不能直接调用
          //必须需要创建对象
          Engine e = new Engine();
          sout(e.engineName);//通过对象来调用
      }
      

      }

  2. 成员内部类创建对象

    public class Outer {
        private int a = 10;
        class Inner {
            private int a = 20;
    
            public void show(){
                int a = 30;
                System.out.println(a);//30
                System.out.println(this.a);//20
                System.out.println(Outer.this.a);//10
          }
    
        }
    
        public Inner getInstance(){
            return new Inner();
        }
    }
    

    创建对象

    Inner私有化时,创建对象
    Outer o = new Outer();
    Object oi = o.getInstance();
    
    //Inner没有私有化时,创建对象
    Outer.Inner oi = new Outer().new Inner();  
    
  3. 静态内部类:创建对象的方式 Outer.Inner oi = new Outer.Inner()

  4. 局部内部类

    • 将内部类定义在方法里面就叫做局部内部类,类型于方法里面的局部变量
    • 外界是无法直接使用的,需要在方法内部创建对象并使用
    • 该类可以直接访问外部类的成员,也可以访问方法内的局部变量
  5. 匿名内部类
    • 创建 new 类名/接口名() { 重写方法 };
    • 格式的细节:包含了继承或者实现,方法的重写,创建对象;整体就是一个类的子类对象或者接口的实现类对象
    • 使用场景: (1) 当方法的参数是接口或者类时。 (2) 以接口为例,可以传递这个接口的实现类对象。 (3) 如果实现类只使用一次,就可以用匿名内部类简化代码。

17. BigInteger介绍

  • BigInteger bigInteger = new BigInteger(4,new Random());

    sout(bigInteger) // 生成[0,2^4-1]的随机整数
    
  • BigInteger bigInteger = new BigInteger("1213213");参数里面只能是整数类型的字符串

  • BigInteger bigInteger = new BigInteger("12323",进制);
  • BigInteger bigInteger2 = BigInteger.valueOf(13213);范围和long的范围一样,内部有优化;对象一旦创建,内部数据就不会发生改变
  • 常用方法:

    1. 加法:add(),eg: bi1.add(bi2)
    2. 减法:substract(),eg: bi1.substract(bi2)
    3. 乘法:multiply,eg:bi1.multiply(bi2)
    4. 商:divide(),eg:bi1.divide(bi2)
    5. 商和取余:public BigInteger[] divideAndRemainder(),eg: BigInteger[] arr = bi1.divideAndRemainder(bi2),

      sout(arr[0]) //商
      sout(arr[1]) //余数
      
    6. 较大/小值:max()/min()

18. BigDecimal介绍

  • 用于精确计算小数
  • 常用方法:
    1. 加法:add(),eg: bd1.add(bd2)
    2. 减法:substract(),eg: bd1.substract(bd2)
    3. 乘法:multiply,eg:bd1.multiply(bd2)
    4. 商:divide(),eg:bd1.divide(bd2)

19. 正则表达式(pattern)

  • 方法:matches()
  • 作用:

    1. 校验字符串是否满足要求
    2. 在一段文本中查找满足要求的内容
  • 字符类(只能匹配一个字符):

    1. [abc] 只能是a,b或者c
    2. [^abc] 除了a,b,c之外的任何字符
    3. [a-zA-Z] a到z A到Z,包括(范围)
    4. [a-d[m-p]] a到d,或者m到p
    5. [a-z&&[def]] a-z和def的交集。为d,e,f
    6. [a-z&&[^bc]] a-z和非bc的交集(等同于[ad-z])
    7. [a-z&&[^mp]] a-z和非mp的交集(等同于[a-lq-z])
  • 预定义字符(只能匹配一个字符)

    1. . 任意字符
    2. \d 表示任意一个数字[0-9]
    3. \D 非数字[^0-9]
    4. \s 一个空白字符[\t\n\x0B\f\r]
    5. \S 非空字符
    6. \w [a-zA-Z_0-9]英文、数字、下划线
    7. \W [^\w]
    8. (?i) 大小写都可以
  • 数量词

    1. X? X,一次或者0次
    2. X* X,0次或者多次
    3. X+ X,一次或者多次
    4. X{n} X,正好n次
    5. X{n+,}X,至少n次
    6. X{n,m} X,至少n但不超过m次
  • 爬虫

    String str = "Java8十大慈善擦山东撒旦撒Java11";
    //获取正则表达式的对象
    Pattern pattern = Pattern.compile("Java\\d{1,2}");
    //获取文本选择器的对象
    Matcher m = pattern.matcher(str);
    while (m.find()){
        String s = m.group();
        System.out.println(s);//Java8   Java11
    }
    
  • 捕获分组

    1. 可以获取每组中的内容,反复使用
    2. 每组内部重复使用:\组号
    3. 每组外部重复使用:$组号

      //捕获分组
      //判断一个字符串的开始字符与结束字符是否一致?
      //举例:a123a   17891   a123b(false)
       String regex1 = "(.).+\\1";  // "\\1"把第一组数据在用一次
       System.out.println("a123a".matches(regex1));
       System.out.println("a123b".matches(regex1));
      /*
      * 判断一个字符串的开始部分与结束部分是否一致?开始部分内部每个字符也需要一致
      * 举例: aaa123aaa    bbb34bb   &&abc&&
      * .表示第一个字符任意
      * \\2 拿出第二组数据再用一次
      *  *作用于\\2,表示出现0次或者多次
      * 分组会以左括号为基准  eg:((.)\\2+).+\\1    (.)为第一组
       * */
      System.out.println("_________________");
      String regex2 = "((.)\\2+).+\\1";
      System.out.println("aaa1223aaa".matches(regex2));
      System.out.println("aaa123bbb".matches(regex2));
      
      String str = "我要学学编编编程程程";
      final String s = str.replaceAll("(.)\\1+", "$1");
      System.out.println(s);
      

      结果:

      true
      false
      _________________
      true
      false
      我要学编程
      
  • 非捕获分组:(:?)(?=)(?!)都是非捕获分组

20. SimpleDateFormat介绍

  • 日期格式化

    默认格式

    //默认格式
    SimpleDateFormat simpleDateFormat1 = new SimpleDateFormat();
    final String format1 = simpleDateFormat1.format(new Date(0L));
    System.out.println(format1);//70-1-1 上午8:00
    

    格式化

    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH时:mm分:ss秒");
    final String format = simpleDateFormat.format(new Date(0L));
    System.out.println(format);//1970年01月01日 08时:00分:00秒
    
  • 日期解析

    //日期解析
    String str = "2023-11-11 11:11:11";
    SimpleDateFormat simpleDateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    Date date;
    try {
        date = simpleDateFormat2.parse(str);
    } catch (ParseException e) {
        throw new RuntimeException(e);
    }
    final String format2 = simpleDateFormat2.format(date);
    System.out.println(format2);//2023-11-11 11:11:11
    

21. 排序算法

  • 冒泡排序

    public class BubbleSort {
    public static void main(String[] args) {
        int[] arr = {6, 1, 2, 7, 9, 3, 4, 5, 10, 8};
        bubbleSort(arr);
        System.out.println(Arrays.toString(arr));
    }
    
    private static void bubbleSort(int[] arr) {
        for (int i = 0; i < arr.length - 1; i++) { //n-1趟排序
            boolean flag = false;
            for (int j = 0; j < arr.length - 1 - i; j++) {  //每一趟进行n-1 - i次排序
                if (arr[j] > arr[j+1]){
                    int temp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = temp;
                    flag = true;
                }
            }
            if (!flag) return;
        }
      }
    }
    
  • 选择排序

    public class SelectSort {
    public static void main(String[] args) {
        int[] arr = {6, 1, 2, 7, 9, 3, 4, 5, 10, 8};
        selectSort(arr);
        System.out.println(Arrays.toString(arr));
    }
    
    private static void selectSort(int[] arr) {
        //思想:,每次都要拿第一个元素和后面元素比较
        for (int i = 0; i < arr.length - 1; i++) {//比较的趟数
            for (int j = i + 1; j < arr.length; j++) { //j 不能 < arr.length - 1,这样arr[arr.length-1]元素不能被比较
                if (arr[i] > arr[j]){
                    int temp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = temp;
                }
            }
        }
      }
    }
    
  • 插入排序

  • public class InsertSort { public static void main(String[] args) { int[] arr = {6, 1, 2, 7, 9, 3, 4, 5, 10, 8}; insertSort(arr); System.out.println(Arrays.toString(arr)); }

    private static void insertSort(int[] arr) {
        for (int i = 1; i < arr.length; i++) {
            int end = i - 1;//已经有序的最大下标
            int insert = arr[i];//需要插入的元素
            while (end >= 0 && insert < arr[end]){
                arr[end+1] = arr[end];
                end--;
            }
            //找到待插入元素的位置
            arr[end+1] = insert;
        }
    }
    
  • 快速排序

    public class QuickSort1 {
    public static void main(String[] args) {
        int[] arr = {6, 1, 2, 7, 9, 3, 4, 5, 10, 8};
        quickSort1(arr,0,arr.length-1);
        System.out.println(Arrays.toString(arr));
    }
    
    private static void quickSort1(int[] arr, int i, int j) {
        int start = i;
        int end = j;
        //递归出口
        if (start > end) return;
        //基准数
        int baseNumber = arr[i];
    
    
        while (start != end) {
    
            //必须先从后往前找,否则就会排序错误
            //end从后往前找
            while (true) {
                if (start >= end || arr[end] < baseNumber) break;
                end--;
            }
    
            //从外前往后找
            while (true) {
                if (start >= end || arr[start] > baseNumber) break;
                start++;
            }
    
            //end和start都找到对数以后,交换两个位置上的元素
            int temp = arr[start];
            arr[start] = arr[end];
            arr[end] = temp;
    
        }
        //找打基准数的位置,归位
        int temp = arr[i];
        arr[i] = arr[end];
        arr[end] = temp;
    
        //把基准数的右边继续进行排序
        quickSort1(arr,start+1,j);
        //把基准数的左边继续进行排序
        quickSort1(arr,i,end-1);
    
        }
    }
    

四、集合

1. Arrays介绍

  • Arrays.copyOf():int[] copyOf = Arrays.copyOf(被拷贝的数组, 拷贝数组)
  • Arrays.toString():把数组转换为字符串[数组元素]
  • Arrays.fill():Arrays.fill(填充数组,填充值)
  • Arrays.sort():给数组排序采用快排,默认升序,需要降序需要重写sort()方法
  • Arrays.sort()的重写,底层采用插入+二分查找实现,o1-o2实现升序,o2-o1降序

    Integer[] arr1= {6, 3, 2, 6, 8, 1};
    Arrays.sort(arr1,new Comparator<Integer>() {
    
        @Override
        public int compare(Integer o1, Integer o2) {
            return o2 - o1;
        }
    });
    System.out.println(Arrays.toString(arr1));//[8, 6, 6, 3, 2, 1]
    

2. Collection介绍

  • 是可以重复的、有序的,是所有单列集合的祖宗接口,它的功能是全部单列集合都可以继承的。不能创建对象,只能通过实现类创建对象,Collection coll = new ArrayList<>()
  • 方法

    1. coll.add():添加元素,添加成功返回True,一定添加成功
    2. coll.remove():删除元素,删除成功返回True,删除失败返回False
    3. cool.clear():清空集合
    4. coll.contains():查看是否包含某个元素,包含返回True,不包含返回False,特别注意:contains方法底层是通过equals方法判断的,如果是自定义对象,一定要在JavaBean中重写equals方法
    5. coll.size():获取集合大小
  • Collection的遍历

    1. 通过迭代器遍历:迭代器的遍历是不依赖索引的,索引不存在索引越界,只会发生NoSuchElementException(没有这个元素异常)。迭代器遍历完以后,指针是不会复位的,想要再次遍历只能重新获取一个新的迭代器对象

      public static void main(String[] args) {
          Collection coll = new ArrayList<>();
          //添加元素
          coll.add("aaa");
          coll.add("bbb");
          coll.add("ccc");
          //创建迭代器对象
          Iterator<String> iterator = coll.iterator();
          while (iterator.hasNext()){ //iterator.hasNext() 判断当前位置是否有元素,有返回True
              String s = iterator.next();//有两层意思:1.返回当前元素  2. 移动指针
              System.out.println(s);
      }
      

3. ArrayList介绍

  • ArrayList list = new ArrayList<>(),ArrayList大小是可变的,自动扩容; "< >"表示泛型只能为引用数据类型
  • 增加:add() 返回类型为boolean
  • 删除:remove("") 返回类型为boolean,remove(index)删除指定下标,返回值为被删除的元素
  • 修改:set(index,"替换") 返回值为被修改的元素
  • 查:get(index) 返回值为查找的元素
  • ArrayList 大小size()
  • 可以使用size()和get()实现遍历

4.红黑树

  • 红黑树的数据结构规则:

    1. 每一个节点只能是红色或者黑色
    2. 根节点必须是黑色
    3. 如果一个节点没有父节点或者子节点,该节点相应的指针属性值为Nil,这些Nil视为叶子节点,每个叶子节点(Nil)是黑色的
    4. 如果某一个节点是红色的,那么它的子节点必须是黑色的(不能出现开两个红色节点相连的情况)
    5. 对每一个节点,从该节点到其所有后代叶子节点的简单路径上,均包含相同数目的黑色节点
  • 添加的节点默认是红色的,添加效率更高

  • 红黑树的增删改查效率比较

5.set系列集合

  • 无序:存取顺序不一致
  • 不重复:可以去重
  • 无索引:没有带索引的方法,所有不能使用普通的for循环遍历,也不能通过索引来获取元素
  • set的实现类:

    1. HashSet:无序、不重复、无索引
    2. LinkedHashSet:有序、不重复、无索引
    3. TressSet:可排序、不重复、无索引
  • 常用方法:

    public class Set1 {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        set.add("张三");
        set.add("张三");//返回false  不允许重复添加
        set.add("王五");
        set.add("李四");
        System.out.println(set);//[李四, 张三, 王五]  存取是无序的
        /*//迭代器遍历
        Iterator iterator = set.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }*/
    
        //增强for循环遍历
        /*for (String s : set) {
            System.out.println(s);
        }*/
    
        //Lambda表达式
        /*set.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });*/
    
        set.forEach(s ->
                System.out.println(s)
        );
    
      }
    } 
    

6.HashSet介绍

  • HashSet底层原理:

    1. HashSet底层采用哈希表存取
    2. 哈希表是一种对于增删改查数据性能较好的数据结构
    3. 添加是的位置:int index = (数组长度-1)& 哈希值
  • 哈希表的组成:

    1. JDK8以前:数组+链表
    2. JDK8开始:数组+链表+红黑树
  • 哈希值

    1. 根据hashCode方法计算出来的的int类型的整数
    2. 该方法被定义在Object中,所有对象都可以调用,默认使用地址值来计算
    3. 一般情况下,会重写hashCode方法,利用对象内部的属性值计算哈希值
  • 对象的哈希值特点

    1. 如果没有重写hashCode方法,不同对象计算出来的哈希值是不同的
    2. 如果已经重写了hashCode方法,不同的对象只要属性值相同,计算出来的哈希值就是一样的
    3. 在小部分的情况下,不同属性值或者不同的地址值计算出来的哈希值也可能是一样的(哈希碰撞)

      public class HashSet1 {
      public static void main(String[] args) {
          Student student1 = new Student("张三",20);
          Student student2 = new Student("张三",20);
          Student student3 = new Student("李四",22);
      
        /*  //没有重写hashCode方法,不同对象计算出来的哈希值是不同的
          System.out.println(student1.hashCode());//460141958
          System.out.println(student2.hashCode());//1163157884
          */
          //重写hashCode方法以后,属性值相同计算出来的哈希值就是一样的
          System.out.println(student1.hashCode());//24022540
          System.out.println(student2.hashCode());//24022540
      
      
          //哈希碰撞
          System.out.println("abc".hashCode());//96354
          System.out.println("acD".hashCode());//96354
       }
      }
      
    4. HashSet的去重

      public class HasHSetTest {
      public static void main(String[] args) {
          Student student1 = new Student("张三",20);
          Student student2 = new Student("李四",21);
          Student student3 = new Student("王五",22);
          Student student4 = new Student("张三",20);
      
          HashSet<Student> hashSet = new HashSet<>();
          System.out.println(hashSet.add(student1));
          System.out.println(hashSet.add(student2));
          System.out.println(hashSet.add(student3));
          System.out.println(hashSet.add(student4));//false 实现去重
          // 输出和存入时候顺序不一样
          System.out.println(hashSet);//[Student{name = 张三, age = 20}, Student{name = 王五, age = 22}, Student{name = 李四, age = 21}]
       }
      }
      

7. linkedHashSet介绍

  • 有序、不重复、无索引
  • 这里的有序指的是保证存取的元素一致
  • 原理:底层的数据结构依旧是哈希表,只是每一个元素又额外多了一个双链表的机制记录存储的顺序

    public class LinkedHashSetTest {
        public static void main(String[] args) {
            Student student1 = new Student("张三",20);
            Student student2 = new Student("李四",21);
            Student student3 = new Student("王五",22);
            Student student4 = new Student("张三",20);
            LinkedHashSet<Student> linkedHashSet = new LinkedHashSet<>();
    
            //添加元素
            System.out.println(linkedHashSet.add(student1));
            System.out.println(linkedHashSet.add(student2));
            System.out.println(linkedHashSet.add(student3));
            System.out.println(linkedHashSet.add(student4));//false 也能实现去重
            // 输出的顺序和添加的一样
            System.out.println(linkedHashSet);//[Student{name = 张三, age = 20}, Student{name = 李四, age = 21}, Student{name = 王五, age = 22}]
    
        }
    }
    

8. TreeSet

  • 可排序、不重复、无索引
  • 底层是红黑树
  • 有序:

    public class TreeSet1 {
        public static void main(String[] args) {
            TreeSet<Integer> treeSet = new TreeSet<>();
            treeSet.add(2);
            treeSet.add(3);
            treeSet.add(4);
            treeSet.add(1);
            System.out.println(treeSet);//[1, 2, 3, 4]
        }
    }
    
  • 对于数值类型:Integer和Double都是默认小到大排序

  • 对于字符和字符串类型都是按照ASCLL表中升序排序

    //让Student类实现Comparable接口并重写compareTo方法,去实现默认排序
    public int compareTo(Student o) {
        //按照年龄的升序排序
        return this.age - o.age;
    }
    

    public class TreeSet1 {
        public static void main(String[] args) {
            TreeSet<Student> treeSet = new TreeSet<>();
            Student student1 = new Student("Zhangsan",22);
            Student student2 = new Student("Lisi",20);
            Student student3 = new Student("Wangwu",21);
            treeSet.add(student1);
            treeSet.add(student2);
            treeSet.add(student3);
            System.out.println(treeSet);//[Student{name = Lisi, age = 20}, Student{name = Wangwu, age = 21}, Student{name = Zhangsan, age = 22}]
        }
    }
  • 自定义Comparator比较器

    public class TreeSet1 { public static void main(String[] args) {

        Student student1 = new Student("Zhangsan",22,99);
        Student student2 = new Student("Lisi",22,98);
        Student student3 = new Student("Wangwu",20,80);
        TreeSet<Student> treeSet = new TreeSet<>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                int i = o1.getAge() - o2.getAge();
                i = i==0? o1.getSum() - o2.getSum() : i;
                return i;
            }
        });
        treeSet.add(student1);
        treeSet.add(student2);
        treeSet.add(student3);
        System.out.println(treeSet);
        //[Student{name = Wangwu, age = 20,sum =80}, Student{name = Lisi, age = 22,sum =98}, Student{name = Zhangsan, age = 22,sum =99}]
      }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值