• Java


    # day01

    一:基本操作

    package _01.java基本操作;
    
    /**
     * 文档注释
     */
    public class _01Alls {
        public static void main(String[] args){
            /*
            * 数据类型:
            * 数值型:
            *   整数:byte(1), short(2), int(4), long(8)
            *   浮点:float(4), double(8)
            * 字符串:char(2)
            * 布尔  :boolean(1)
            *
            * String:双引号(单引号只能放一个)
            *
            * 类型转换:
            *   手动转换:
            *       1. 不能直接把一个大的类型赋值给小的类型
            *       2. 强制类型转换后才可赋值:byte b (byte)100;
            *   自动转换:
            *       1. 运算时,两端类型需要一致
            *       2. 如果是数值运算,会把小的转换为大的类型
            *       3. JVM 运算时,最小识别类型时 int (byte,short char 会自动提升为 int 类型)
            *
            * 自增与自减:(正在运算时不会计算,但是运算结束后会加上,且不会叠加,++几次就是几)
            *   注:a++ / a-- 参与运算时使用初始值
            *       ++a / --a 参与运算时使用的是自增后或自减后的值
            *
            * 三元运算:
            *   接收值 = 逻辑表达式 ?表达式1(true) : 表达式2(false)
            *
            * 逻辑运算:
            *   ^ : 相同返回 false, 不同返回 true
            *   && / || : 一旦一方成立,后面不再执行
            *
            * switch 语句:
            * 1. 完整写法:
            *   switch(整型表达式){
            *       case 值1 : {
            *           返回结果;
            *       }break;
            *       case 值2 : {
            *           返回结果;
            *       }break;
            *       default : 没有条件满足则执行此语句;
            *   }
            * 2. 简写:
            *   switch(整型表达式){
            *       case 值1 : 返回结果;break;
            *       case 值2 : 返回结果;break;
            *       case 值3 : 返回结果;break;
            *       default : 没有条件满足则执行此语句;
            *   }
            *
            * do while(先执行一次代码块,再进行判断):
            *   do{
            *       代码块;
            *   }while(表达式);
            *
            * for 循环:( 可以给循环起 别名:outter : for(..){...} )
            * for(int num = 1; num <= 10; num++){
            *   代码块;
            * }
            * foreach:
            * for(数据类型 i : 数组){
            *   代码块;
            * }
            *
            * 终止:
            *   1. break  : 跳出循环, 后续同级代码继续执行
            *   2. return : 跳出循环, 后续不执行,包括同层级代码
            *
            * 方法:
            *   1. 声明到 class 中
            *   2. 如果一个方法之前有 static 那么这个方法也需要加 static
            *   3. void : 这个参数意思是返回空, 但是如果有返回值的话, void需要改成返回值的数据类型
            * 方法重载:
            *   - 在同一个类中,允许两个方法名重复,但前提是两个方法的参数(类型也可以一致)不能一致
            *
            * 可变参数:
            *   1. 数组: void a(int[] arg){xxx}
            *   2. 可变: void a(int ...arg){xxx}
            * */
    
            // 变量声明
            int a = 10;
            int b = 20;
    //
    //        // 打印
            System.out.println('a');
            System.out.println(true ^ false); // true
    
            int num = 100;
            if(num == 100){
                System.out.println("true");
            }
    
            boolean s = true;
            while(s){
                System.out.println('1');
            }
        }
    }

    二:数组

    package _01.java基本操作;
    
    public class Array {
        public static void main(String[] args) {
    
            // 数组写法:
            // 要存放的数据类型[] 数组名 = new 要存放的数据类型[] {存放的数据内容}
            // 简写:int[] array = {1,2,3}
    //        int[] array = new int[] {1,2,3};
    //        System.out.println(array[0]);
    
    /*
            // 1. 静态定义数组
            // 定义一个数组
            String[] strInfo;
            // 初始化数组
            strInfo = new String[] {"q","w"};
            System.out.println(strInfo[1]);
    
            String l = "[";
    
            for(int i=0; i<strInfo.length; i++){
                l+=strInfo[i]+',';
            }
            String res = l+"]";
            System.out.println(res);
    */
            // 2. 动态定义数组
    //        String[] all = new String[100];
    //        all[0] = "Hello";
    //        System.out.println(all[0]);
    
            // 3. 二维数组
            // 写法:int[][] Arrays = new int[][] {arr1,arr2,arr3}
            // 获取:
            int[] arr1 = {1,2,3};
            int[] arr2 = {4,5,6};
            int[][] arr = {arr1,arr2};
            for(int i : arr1){
                System.out.println(i);
            }
            /*
            for(int i = 0; i<arr.length; i++){
                int[] now_arr = arr[i];
                for(int j = 0; j < now_arr.length; j++){
                    System.out.println(now_arr[j]);
                }
            }
            */
        }
    }

    三:面向对象

    package _02.java面向对象;
    
    public class _02SomeInfo {
    
        String name;
        int age;
    
        _02SomeInfo(String name){
            this.name = name;
        }
    
        _02SomeInfo(String name, int age){
            this(name);
            this.age = age;
        }
    
        void run(){
            System.out.println(name+" is Run..");
        }
    
        void eat(String food){
            System.out.println(name+" want Eat " +food);
        }
    
        public static void main(String[] args){
            /*
            _02SomeInfo info = new _02SomeInfo();
            info.name = "q";
            info.age = 11;
            info.run();
            info.eat("apple");
            */
            _02SomeInfo info = new _02SomeInfo("q",11);
            info.run();
            info.eat("apple");
        }
    
        /*
        * 虚拟机栈:(每个函数从调用到执行结束,就是对应一个栈帧的入栈和出栈)
        *   当执行一个方法时,就会为这个函数创建一个栈帧,并加入虚拟机栈。
        *
        * 堆:被所有线程共享的一块区域,在虚拟机启动时创建,所有的对象实例及数组都在堆上分配
        *       (使用 new 关键字表示在堆中开辟一块新的空间)
        *
        * 属性概念:
        *   - 有 getter/setter 方法的才是属性,否则是 字段或成员变量。
        *
        * 构造器:
        *   1. 作用:
        *       - 创建对象,必须和new一起使用。
        *       - 完成对象的初始操作。
        *   2. 特点:
        *       - 构造器的名称和当前类名是一样的。
        *       - 禁止有返回类型,不能使用void作为返回值。
        *       - 在构造器中不能使用 return
        *           - 但是构造器有返回值(返回值时内存地址)
        *   3. 默认构造器特点:
        *       - 符合构造器特点。
        *       - 无参数。
        *       - 如果类中有 public 装饰,那么构造器也会有public,否则无。
        *   4. 自定义构造器:
        *       - 使用:
        *           User(){
        *               代码块;
        *           }
        *       - 构造器重载:
        *           User(String name){
        *               Myname = name;
        *           }
        *           User(String name, int age){
        *               Myname = name;
        *               Myage = age;
        *           }
        *
        * static 修饰符:
        *   1. 概念:
        *       - 如果在字段或方法面添加了 static, 那么它的字段或方法就属于类(类成员),没有添加则是 实例成员
        *   2. 特点:
        *       - static装饰的内容是随着类的加载而加载的。
        *       - static装饰的内容,优先于对象的存在。
        *       - static装饰的内容,被该类型的所有对象共享。
        *       - static装饰的内容,可以直接使用类名调用。
        *   3. 类成员和实例成员的访问:
        *       - 在 static 方法中只能调用 static 成员
        *       - 非 static 方法,两者都可以访问。
        *   4. 注:
        *       - 方法中不能定义以 static装饰的变量。
        *
        * 封装:
        *   1. 访问修饰符:
        *       - private   : 表示私有(类访问权限),且只能在类中才有访问权限。
        *       - protected : 表示子类访问权限,同包中可以访问,不同包中不能访问,同包不同类不能访问,继承可以访问。
        *       - public    : 表示全局,可以在项目中任何地方使用。
        *       - 默认      : 表示包访问权限,同一类中可以访问,同一包,不同类可以访问,不同包不能访问。
        *
        * this:
        *   1. 解决成员变量和参数问题。
        *   2. static 不能和 this 一起使用。
        *   3. 构造器的重载互调:
        *       - 在一个构造器中调用另一个构造器:
        *           - this(xx)  // 必须写在第一行。
        *           User(String name){
        *               this.name = name;
        *           }
        *           User(String name, int age){
        *               this(name);
        *               this.age = age;
        *           }
        * */
    }

    # day02

    一. 封装:(提供外部能够访问的接口)
    1. 良好的封装能够减少耦合。
    2. 类内部的结构可以自由修改。
    3. 可以对成员进行更精确的控制。
    4. 隐藏信息,实现细节。


    二. 继承:
    01. 使用 extends 来继承父类(extends 后面跟继承类):
      - public class Student extends Person{}
    02. 修饰符继承:
      - public 子类都可以继承。
      - protected 子类可以继承,不同包也可以继承。
      - private 只能在本类中可以使用,子类无法使用。
      - 默认 同一包可以继承,不同包不能继承。
    注:父类的构造器是无法继承的。


    2. 覆盖原则:
      - 方法名和参数一致。
      - 子类方法的返回值类型和父类方法返回值类型一致。
      - 子类方法的访问权限比父类要大或者相同。

    3. 判断该方法是否是覆盖方法(如果不是则会报错)。
      - 在子类中将覆盖方法上方加上 @Override 。

    4. 继承super关键字:
      - 凡是子类的构造方法中就会有 super();
      - super 代表的父类对象。
      - super 构造方法必须要放到第一行。

    Foo(xx,xx){
      super(xx,xx);
      this.xx = xx;
    }

    三. 多态:
    1. 特点:
      - 子类对象赋值给父类类型。
      - Animal cat = new Cat();
      - 运行时,表现的是子类的特征(先去找子类)。

    2. 使用:

    class Animal{
      static void eat(){
        System.out.println('animal')
      }
    }
    class Dog extends Animal{
      static void eat(){
        System.out.println('dog')
      }
    }
    
    class Cat extends Animal{
      static void eat(){     System.out.println('cat')   } } class Person{   - 在接收值得时候只需要当作类对象接收,这样就不需要考虑是哪个类对象的实例了。   void get(Animal anim){     anim.eat();   } } Dog dog = new Dog(); Cat cat = new Cat(); Person per = new Person(); per.get(dog); per.get(cat);

    四. instanceof 关键字:
    - 判断一个对象是否是指定的类,如果是返回true,否则false。

    if(anim instanceof Dog){
      // 类的强制类型转换: 把父类对象赋值给子类对象。
      Dog dog = (Dog)anim;
    }

    - 注:字段不存在多态。

    五. 局部代码块和初始化代码块:
    使用: 在类中或方法中,使用{}括起来。
    1. 局部代码块 : 直接定义在方法内部的代码块。
    2. 初始化代码块: 直接在类当中定义的代码块(运行时还是要放在构造方法中)。
    3. 静态代码块 : 在初始化代码块前面加 static。
      - 在加载字节码的时候自动调用。
      - 在主方法之前执行,且只执行一次。

    六:组合关系:
    1. 类中的字段是 另一个 "类" 类型, 依赖其它的类。
      - Person per;

    2. 类在第一次使用该类对象的时候就 加载到 JVM 中,
    只加载一次,下一次就直接从内存中使用。

    七: final 关键字:
    1. 只可用,不可修改,保证数据的安全。
    2. 可以修饰:
      - 字段:不能修改该字段。
      - 方法:子类就不能覆盖该方法。
      - 类 :该类不能被其它类继承(不能有子类)。
    3. 修饰字段时,字段是没有初始值,须手动设置。
    4. 修饰变量,就代表是一个常量(因为无法修改)。 命名:所有的字母都可大写。
      - final int MAX_VALUE
    5. 可以带局部代码块中使用。
    6. 修饰基本数据类型: 值不能改。 final int a = 1;
    修饰引用数据类型: 地址不能改。 final Person p = new Person();


    八. 单例模式:

    class ToolUtil{
      // 1. 必须要在类中创建一个对象。
      private static ToolUtil instance = new ToolUtil();
      // 2. 私有化自己的构造器,防止外界通过构造器创建新的对象。 
      private ToolUtil(){}
      // 3. 给外界提供一个接口,拿到已经创建好的对象。
      static public ToolUtil getInstance(){
        return instance;
      }
    }

    九. 包装类:

    byte - Byte
    short - Short
    int - Integer
    long - Long
    
    float - Float
    double - Double
    char - Character
    boolean - Boolean

    1. 自动装箱与自动拆箱。
    - Integer i = 20; (装)
    - int i1 = i; (拆)


    十. 抽象方法:
    1. 使用:在方法前加一个关键字 abstract
    2. 特点:
      - 子类必须覆盖此方法。
      - 抽象方法没有方法体(也就是没有{})。
      - 抽象方法必须要定义在抽象类中 或 接口中(在类前面添加一个abstract 就是抽象类)
      - 抽象方法不能与 private, final, static 同时装饰。

    十一. 抽象类:
    注:必须要有子类。
    定义: 在类前面添加一个 abstract 就是抽象类。
    1. 不能直接创建对象。
    2. 可以有抽象方法,也可有非抽象方法。


    十二. 接口:
    1. 接口中没有构造器,不能创建对象。
    2. 接口中定义的变量都是全局的静态常量。
      - String name = 'q'; --> public static final String name;
    3. 接口当中定义的方法都是公共的抽象的方法。
      - void transData(); --> public abstract void transData();

    4. 接口可以多继承。

    5. 接口的使用:

    - 定义接口: interface 接口类名{} 
    - 实现接口: class 类名 implements 接口类名{}
    
    interface Iwalkable{
      void walk();    // 编译时: public abstract void walk();
    }
    
    interface Iswimable{
      void swim();
    }
    
    interface Iqable extends Iwalkable, Iswimable{
    // 接口的多继承
    }
    
    // 实现接口
    // 同时也可以继承类(只能继承一个类)
    class Cat extends Animal implements Iwalkable{
    // 1. 需要 implements 关键字后面跟接口
    // 2. 必须加 public 因为接口类的方法在编译的时候是由 public装饰的。
      // 而子类权限必须要比父类大或者一致才可。
      public void walk(){}
    }
    // main 中:
    Iwalkable cat = new Cat(); // 面向接口编程
    cat.walk();    // 多态运行时表现的还是子类特征(编译时看左边,运行时,看右边)


    十三. 抽象类 和 接口类:
    1. 相同点:
      - 都是被其他类实现或被继承。
      - 都不能实例化。
      - 都可以定义抽象方法,定义的抽象方法子类必须覆盖。
    2. 不同点:
      - 接口类没有构造器,抽象类有构造器。
      - 抽象类可以包含普通方法和抽象方法,
        接口类中只能有抽象方法,不能有普通方法(方法不能加{})。
      - 接口类中默认成员变量 : public static final 变量; (静态变量)。
      - 抽象类:默认权限。
      - 接口类中方法: public abstract 方法名;


    十四. 内部类 (外部类修饰符只能有 public 或 不加(默认), 内部可随意装饰):
    1. 实例内部类(是属于对象的内部类,且不被 static 装饰):
      - 必须创建外部类才能使用 内部类。
      - 内部类可以访问外部类成员。
      - 内部类中不能有静态成员。
      - 外部类不能直接访问内部类成员。

    class Outter{
      String name = '1';
      class Inner(){
        String name = '2';
        void test(){
          String name = '3';
          System.out.println(name); // 3
          System.out.println(this.name); // 2 
          System.out.println(Outter.this.name); // 1
        }
      }
    }
    
    // main 中:
    // 创建内部类。
    Outter out = new Outter();
    Outter.Inner in = out.new Inner();
    // 调用内部类方法。
    in.test();

    2. 静态内部类:
      - 静态内部类是不需要创建外部对象。
        Outter.Inner in = new Outter.Inner();
      - 静态内部类中,是没有外部类引用(由于static装饰,没有创建外部类对象地址,所以没有被外部类引用)。
      - 静态内部类,是可以访问外部类的静态成员的。
      - 访问静态内部类中的静态成员: Outter.Inner.h;

    class Outter(){
      static String name = "q";
      static class Inner(){
        String h = "hello";
        void test(){
          System.out.println(name);
          System.out.println(new Outter().age);
        }
      }
    }
    
    // main :
    // 创建静态内部类。
    Outter.Inner in = new Outter.Inner();
    in.test();
    
    // 访问静态内部类中的静态成员
    System.out.println(Outter.Inner.h);


    3. 局部内部类(定义在方法中的内部类):
      - 不能使用装饰。
      - 局部内部类只能在定义的方法中使用。
      - 不能包含静态变量。
      - 可以包含局部变量,使用局部变量的本质是 final (常量)。

    class Outter{
      void q(){
        // final 可以不写,默认编译时会自动加上(1.8之后)
        final String name = "q";
        class Inner{
          void test(){
            System.out.println(name);
          }
        }
    
        Inner in = new Inner();
        in.test();
      }
    }
    
    // main 中:
    new Outter().q();

    4. 匿名内部类:
      - 必须有父类,或者实现了接口。
      - 没有名字的局部内部类。
      - 没有构造器。
    使用方法:
    new 父类的构造器 或 接口 (){
      public void test(){
      // 代码块...
      }
    }


    十五. 枚举:
      - 枚举: 表示一个事件固定状态。
      - java 枚举 : 一个特殊的类,多个常量对象的集合。
      - 格式:
        [修饰符] enum 枚举名称{ 常量1,常量2... }

    enum SEX{
      NAN,NV
    }

    十六. 常用工具类:

    1. Scanner 输入键盘信息:

    import java.util.Scanner;
    
    Scanner sc = new Scanner(System.in);
    // 会在控制台等待键盘输入。
    String str = sc.nexLine(); // 字符


    2. 数据的拷贝:
      - 参数:
        arraycopy(源数组, 源数组中起始位置, 目标数组, 目标数组中起始位置, 要复制的数据量)
      - 使用:

    int[] src = {1,2,3};
    int[] desc = new int[5];
    System.arraycopy(src, 2, desc, 0, 2);

    3. 计算时间 (其它查文档):

    long time = System.currentTimeMillis();


    4. Math 数学类:

    // 求最大值
    int res = Math.max(10, 20);
    
    // 求最小值
    int res = Math.min(1, 2);
    
    // 返回 0 - 1 之间随机数
    Math.random();
    
    // 返回 0 - 100 随机整数
    int res = (int) (Math.random*100);
    
    // 开根
    double res = Math.sqrt(4);
    
    // 数字精度计算
    import java.math.BigDecimal
    
    BigDecimal num1 = new BigDecimal("0.9");
    BigDecimal num2 = new BigDecimal("0.1");
    System.out.println(num1.add(num2));


    十七. 字符串:
    1. 空值:
      - String str = null;   还未初始化,没有分配内存空间。
      - String str = "";      已经创建对象,分配了内存,内容为空。
    2. 字符比较:
      - == 比较内存地址是否相等。
      - equals
        a. 先比较内存地址是否相等
        b. 如果不相等,再去判断是否为String,然后再将每一个字符取出来判断相不相等。

    String str1 = "AB";
    String str2 = new String("AB");
    
    if(str1.equals(str2)){ ... }

    3. 常用方法(看文档):

    // 获取长度
    str.length();
    
    // 获取字符串中某一字符
    str.charAt(2);
    
    // 返回一个字符串在字符中第一次出现的位置
    str.indexOf(str2);
    
    // 最后一次出现的位置(从左边开始数)
    str.lastIndexOf(str2);
    
    // 大写转小写
    str1.toLowerCase();
    
    // 小写转大写
    str1.toUpperCase();
    
    // 忽略大小写的比较
    str1.equalsIgnoreCase(str2);
    
    // 字符串的分割
    String[] res = str1.split(";");
    
    // 去前后空格
    str1.trim();
    
    // 替换
    str1.replace("a","b");

    # day03

    十八. 字符串(StringBuilder, StringBuffer)
      - 可变字符串(效率高):

    // StringBuilder : 没有(没有锁) synchronized 
      StringBuilder i = new StringBuilder();
    
    // StringBuffer : 有(加锁) synchronized 
      StringBuffer i = new StringBuffer();

    十九. Random 类

    import java.uitl.Random;
    
    Random r = new Random();
    
    // 生成随机的整数 ()
    int res = r.nextInt();
    // 生成 0 - 100 之间的整数
    int res = r.nextInt(100);
    
    // 生成随机小数
    r.nextDouble();
    
    // 生成随机布尔值
    r.nextBoolean();
    
    // 相同的种子,生成的随机数是一样的(带参数)。
    Random r2 = new Random(11);
    r2.nextInt();

    二十. 生成 UUID

    String uuid = UUID.randomUUID().toString();

    二十一. 日期 Date 类

    import java.util.Date;
    
    // 创建一个日期对象
    Date date = new Date();
    
    // 获取当前时间毫秒数
    long curTime = System.CurrentTimeMillis();
    
    // 把一个毫秒值转换日期类型
    Date date = new Date(curTime);
    
    // 2019-4-3 11:15:00 日期格式
    String str = date.toLocaleString();
    
    // 日期格式化
    // 19-4-3 上午11:46 格式
    DateFormat df = DateFormat.getInstance();
    
    // 长日期 LONG
    // 段日期 SHORT
    
    // 19-4-3 上午11:46 格式
    DateFormat df2 = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
    String time = df2.format(date);
    
    // 2019年4月3日 上午11时49分00秒 格式
    DateFormat df2 = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);
    String time = df2.format(date);
    
    // 11:50:00 格式
    DateFormat df = DateFormat.getTimeInstance();
    String time = df.format(date);
    
    // 字符转日期 (需要添加异常声明 - main(String[] args) throws ParseException{ ... })
    DateFormat df2 = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);
    String newStr = "2019年4月3日 上午11时49分00秒";
    Date date = df2.parse(newStr);
    
    
    // 把一个日期转换毫秒值
    date.getTime();
    
    
    // 自定义日期格式
    import java.util.Date;
    import java.text.SimpleDateFormat;
    
    Date date = new Date();
    
    // 存放日期
    SimpleDateFormat sd = new SimpleDateFormat();
    // 自定义日期展示格式
    String pattern = "yyyy-MM-dd HH/mm/ss";
    sd.applyPattern(patern);
    
    // 以指定的模式格式化日期
    String res = sd.format(date);

    二十二. Collection

    a. ArrayList 的使用:

    import java.util.ArrayList;
    import java.util.Collection;
    
    1. 添加元素
    Collection c = new ArrayList();
    c.add("abc"); // 自动装箱(把基本数据类型转成对象)
    
    1.1 集合合并
    c1.addAll(c2);
    
    2. 删除指定元素
    c.remove("abc");
    
    2.1 删除集合交集
    c1.removeAll(c2);
    
    3. 判断集合是否为空
    c.isEmpty();
    
    3.1 判断调用的集合是否包含传入的集合(全部包含)
    boolean res = c1.containsAll(c2);
    
    3.2 取交集 把交集的结果赋值给调用者(如果调用的集合改变,则返回true,否则返回false)
    boolean b = c1.retainAll(c2);
    System.out.println(c1); // 将两个集合一样的内容返回到调用集合中。
    
    4. 获取集合长度
    c.size();
    
    5. 清空集合
    c.clear();
    
    
    6. 集合转普通数组
    
    // 存放普通数据类型
    Collection c = new ArrayList();
    Object[] arr = c.toArray();
    for(int i = 0; i < arr.length; i++){
      System.out.println(arr[i]);
    }
    
    
    // 存放对象
    Collection c2 = new ArrayList();
    c2.add(new Dog("a"));
    c2.add(new Dog("b"));
    Object[] arr2 = c2.toArray(); // 自动把数组中所有元素向上转型(数组中都是Object)
    
    for(int i = 0; i < arr2.length; i++){
    Dog d = (Dog)arr2[i]; // 向下转型 (子类(向下)/父类(向上))
      System.out.println(d.getName());
    }
    
     
    
    // Collection 迭代器遍历元素
    Collection c = new ArrayList();
    
    // 迭代器遍历(将集合中元素放到迭代器)
    Iterator it = c.iterator(); // 对象会提升为 Object
    
    // 获取迭代器中内容
    it.next();
    
    // 判断迭代器是否还有元素(返回 true or false)
    it.hasNext();

    b. ArrayList 的 List 集合
      - listIterator 在List 中特有的迭代器。
    1. 创建

    List list = new ArrayList();
    ListIterator it = list.listIterator();
    
    while(it.hasNext()){ list.add(); }

    2. 迭代添加/删除元素并发异常
    原因: 迭代器遍历时不能直接(list.add()) 添加/删除 list 中的元素,需要使用迭代器内置的 add/remove 删除。
      - 内部有 modCount != expectedModCount; 每次循环进行判断,如果不相等就会抛异常。
      - modCount : 集合修改次数(如 add() 一次就会记录一次)。
      - expectedModCount : 迭代器中集合修改的次数。

    解决:
      - 每次 add/remove 会执行 modCount = expectedModCount

    while(it.hasNext()){ it.add(); it.remove(); }

    3. 判断当前元素是否存在与这个集合

    newList.contains(obj);

    c. LinkedList - 链式实现
      - 添加/删除 速度快
      - 查询 速度慢

    import java.util.LinkedList;
    
    LinkedList list = new LinkedList();
    
    // 将元素添加到集合 最前面和最后面
    list.addFirst("add1");
    list.addLast("add2");
    
    // 将集合 最前面和最后面 的元素删除
    list.removeFirst();
    list.removeLast();
    
    // 查询
    list.get(0);

    d. Vector (更多详细查文档)
      - 和 ArrayList 差不多,只不过当前这个加锁了。

    import java.util.Verctor;
    Vector vc = new Vector();

    e. Set集合

    1. HashSet / LinkedHashSet
    HashSet:
      - 无序,不重复。
    
    import java.util.HashSet;
    import java.util.Iterator;
    HashSet<String> hs = new HashSet<String>();
    hs.add("a");
    
    Iteractor<String> it = hs.iterator();
    while(it.hasNext()) { ... }


    LinkedHashSet:
      - 有序,不重复。

    import java.util.LinkedHashSet;
    LinkedHashSet<String> set = new LinkedHashSet<>();
    set.add("a");

    f. TreeSet:
      - 自动排序,不重复。

    import java.util.TreeSet;
    TreeSet<Integer> set = new TreeSet<Integer>();
    set.add(1);

    - 比较器:
      - 默认情况下, 比较时会调用对象的 compareTo 进行比较。
      - 如果传入了 比较器,不会调用 compareTo, 就会使用传入的比较器。

    import java.util.TreeSet;
    TreeSet<String> set = TreeSet<String>();
    // 默认按字母的顺序,数字的大小...进行排序。
    set.add("aa");
    set.add("bb");
    set.add("1");
    
    // 使用比较器
      // 实现一个接口 comparator。
      // 定义一个类来实现这个接口。
      // 覆盖里面的方法。
    
    class CompareLength implements Comparator<String>{
      // o1 : 当前正在添加的元素。 o2 : 集合当中的对象。  
      @override
      public int compare(String o1, String o2){
        // 0 : 只添加第一个元素。
        // 正数: 全部添加到集合中,按添加顺序。
        // 负数: 全部添加到集合中,按添加顺序倒序。
        return 0;
      }
    }

    二十三. 泛型:
    1. 定义:
    - 泛型类:
      - 在类上面定义的泛型,在创建对象的时候,指明泛型类型。
      - 泛型中 定义的泛型只能用在普通方法上面。
      - 静态方法(static)不能使用 (因为静态方法直接通过类名调用,而泛型必须实例的时候才指定类型)。
    - 泛型方法:
      - 对一个方法声明了泛型。

    2. 注意:
      - 泛型前后类型需保持一致。
      - 可以这样写: Foo<String> foo = new Foo<>();
      - 泛型欸有继承。
      - 泛型其实时一个语法糖 (本质还是 Object, 内部做强转)

    3. 使用:
    // 泛型类

    class Foo<T>{ ... }
    Foo<String> foo = new Foo<String>();

    4. 自定义泛型方法
    // 方法中定义的泛型,是在使用方法时,参数传递的数据类型。

    <T> void test(T a){
      System.out.println(a.getClass());
    }
    
    new Student().test("a");
    
    // 静态方法也可以使用泛型
    static <E> void test(E name){
      System.out.println(name.getClass());
    }
    
    Student.test(true);
    
    
    static <E> E test1(E name){
      return name
    }
    
    String str = Student.test1('f');


    5. 泛型通配符:
      - 一般用于接收

    import java.util.List;
    import java.util.ArrayList;
    
    static void test(List<?> list){ ... }
    
    List<String> list = new ArrayList<>();
    test(list);


    // 泛型的上限和下限

    // 上限: 用来指定元素的类型必须要是指定类型 (Number) 的子类,或者是指定类型。
    static void test(List<? extends Number> list) { ... }
    
    // 下限: 用来指定元素的类型必须要是指定类型 (Number) 的父类,或者是指定类型。
    static void test(List<? super Number> list) { ... }


    // 泛型擦除

    List<String> list = new ArrayList<>();
    list.add("a")
    
    List list1 = null;
    list1 = list;    // 把 list 当中的泛型给清除。
    list1.add(19);
    list1.add("a");

    二十四. List 与 数组之间的转换。

    ## 数组转集合

    import java.util.Arrays;
    import java.util.List;
    
    // 1. 方式一 (不使用)
    int[] arr = {1,2,3}; // int - 基本数据类型
    
    // 数组转集合 (转换后不能 添加/删除 元素)
    // 这种转法返回的只是一个内存地址 (将 arr 当成一个整体存储为一个对象)
    List list = Arrays.asList(arr); // 0xxx1
    
    // 2. 方式二 (推荐使用)
    Integer[] arr = {1,2,3};    // 引用数据类型
    List list = Array.asList(arr); // 返回的是一个集合 [1,2,3]


    ## 集合转数组

    List<String> list = new ArrayList<>();
    list.add("a");
    list.add("a");
    
    // 方法一:
    Object[] o = list.toArray();
    
    // 方法二:
    String[] str = list.toArray(new String[]);    // 可以写容量大小,容量不够会自动填充,超出用 null 表示。

    二十五. 集合嵌套集合。

    Person per1 = new Person("zs");
    Person per2 = new Person("ls");
    List<Person> c1 = new ArrayList<>();
    c1.add(per1);
    c1.add(per2);
    
    Person per3 = new Person("w5");
    Person per4 = new Person("xl");
    List<Person> c2 = new ArrayList<>();
    c1.add(per3);
    c1.add(per4);
    
    // 集合类型是 List<Person> 嵌套
    List<List<Person>> x = new ArrayList();
    x.add(c1);
    x.add(c2);

    二十六. Map

    HashMap:
      - key 无序

    // 创建
    Map<String,Object> map = new HashMap<String,Object>();
    
    1. 获取所有 keys
    Set<String> keys = map.keySet();
    
    2. 获取所有 values
    Collection<Object> values = map.values();
    
    3. 添加元素
    map.put("k1":"k2");
    
    4. 修改元素
    // 如果keys存在,那么会将 Values 覆盖,并返回原本 values。
    map.put("k1":"k2");
    
    5. 删除元素
    map.remove("k1");
    
    6. 清空字典
    map.clear();
    
    7. 获取字典元素个数
    map.size();
    
    8. 获取一个 keys 的 values
    map.get("k1");

    9. 遍历元素

    // 通过 iterator 遍历。
    Set<String> allKeys = map.keySet();
    Iterator<String> it = allKeys.iterator();
    while(it.hasNext()){
      String key = it.next();
      Object values = map.get(key);
      System.out.println(key+":"+values);
    }
    
    
    
    // 使用 foreach 遍历。
    for(String key : map.keySet()){
      System.out.println(key+":"+map.get(key));
    }
    
    
    
    // 使用 entry 遍历。
    
    // 创建 一个字典。
    Map<String, Integer> map = new HashMap();
    map.put("K1":"v1");
    ...
    
    // 获取所有的 entry 对象。
    Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
    
    // 遍历每一个entry对象。
    Iterator<Entry<String, Integer>> it = entrySet.iterator();
    
    while(it.hasNext()){
      // 取出每一个 key:value
      Entry<String, Integer> en = it.next();
      // 获取 key
      String key = en.getKey();
      // 获取 value
      Integer value = en.getValue();
    }
    
    
    // foreach 写法
    for(Entry<String, Integer> entry:entrySet){
      System.out.println(entry.getKey() + ":" + entry.getValue());
    }

    10. LinkedHashMap / TreeMap

    LinkedHashMap:
      - key 的排序顺序为添加顺序

    LinkedHashMap<String, Integer> hm = new LikedHashMap<>();


    TreeMap:
      - 会对 key 进行排序(其余实现和 TreeSet一致)

    TreeMap<String, Integer> treeMap = new TreeMap<>();


    二十七. 异常

    1. 捕获异常:

    try{
    
    }catch(Exception e){
      //1. 获取异常信息,参数
      e.getMessage();
    
      //2. 获取异常类名和异常信息
      e.toString();
    
      //3. 获取异常 类名,错误信息 和出错位置
      e.printStackTrace();
    }

    2. 抛出异常:

    // 2.1 抛出运行异常
    throw new RuntimeException("异常信息");
    
    // 2.2 抛出编译异常
      // 必须要处理
    throw new Exception("异常信息");
    
    // 处理方式 :
      //1. try 
      // 2. throws Exception 继续向上抛(将异常给类 throws 可以跟多个异常)
    public void Foo() throws Exception, RuntimeException{ ... }


    2.3 finally

    try{
    
    }catch(Exception e){
    
    }finally{
      // 不管有没有异常,这里都会执行。
    }


    3. 自定义异常:

    3.1 运行异常
      - 定义一个类继承 Exception。
      - 抛出异常时,只需要抛出定义的类名。

    class MyException extends RuntimeException{
      // 自定义异常参数
      MyException(String message){
        super(message);
      }  
    }
    throw new MyException("异常信息");


    3.2 编译异常

    class MyException extends Exception{
    
    }
    
    // 或者继续向上抛异常 (类)
    try{
      ...
    }catch(MyException e){
      ...
    }
  • 相关阅读:
    codeforces #313(div 2)
    云计算设计模式(二十四)——仆人键模式
    封装一个ViewPager真正的实现图片无限循环滚动带导航点
    HDU4622:Reincarnation(后缀数组,求区间内不同子串的个数)
    数据库分页
    [Swift]LeetCode728. 自除数 | Self Dividing Numbers
    [Swift]LeetCode726. 原子的数量 | Number of Atoms
    [Swift]LeetCode725. 分隔链表 | Split Linked List in Parts
    [Swift]LeetCode724. 寻找数组的中心索引 | Find Pivot Index
    [Swift]LeetCode722. 删除注释 | Remove Comments
  • 原文地址:https://www.cnblogs.com/chaoqi/p/10640204.html
Copyright © 2020-2023  润新知