API

Application Programming Interface 应用程序编程接口

字符串

String

  • 程序中所有字符串文字, 都为此类的对象

  • 字符串不可变, 它们的值在创建后不能被改变

  • 创建对象的方式

    • String name = "xxx"

    • String name = new String(String original)

    • String name = new String(char[] chs)

      • 需求: 修改字符串的内容

        • 如: abc – {‘a’, ‘b’, ‘c’} – {‘Q’, ‘b’, ‘c’} – Qbc
        1
        2
        3
        char[] chs = {'a', 'b', 'c', 'd'};
        String s4 = new String(chs);
        sout(s4); // abcd
    • String name = new String(byte[] chs)

      • 应用场景: 在网络当中传输的数据都是字节信息, 一般要将字节信息进行转换, 转成字符串, 此时就要用到这个构造

        1
        2
        3
        byte[] bytes = {97, 98, 99, 100};
        String s5 = new String(bytes);
        sout(s5); // abcd
  • 内存模型

    • 当使用双引号直接赋值时, 系统会检查该字符串在串池中是否存在,不存在则创建新的, 存在则复用 (节约内存)

      image-20250118233354903

    • 每次 new 都会创造一个新空间, 这种方式创建对象不会复用 (占内存)

      image-20250118233402059

  • 常用方法

    • 字符串比较
      • boolean equals()
      • boolean equalsIgnoreCase()
    • int compareTo(String s) : 对字符串进行字典序比较
    • 字符串遍历
      • char charAt(int index) : 根据索引返回字符
      • int length()
  • 字符串截取

    • String substring(int beginIndex, int endIndex)
    • String substring(int beginIndex)
    • 字符串替换
    • String replace(target, replacement)

StringBuilder

  • StringBuilder 可以看成是一个容器, 创建之后里面的==内容是可变==的

  • 作用: 提高字符串的操作效率 (拼接和反转字符串时常用StringBuilder)

  • 构造方法

    • StringBuilder strb = new StringBulder()
    • StringBuilder strb = new StringBulder(String str)
  • 常用方法

    • StringBuilder append(任意类型) : 添加数据, 并返回对象本身
    • StringBuilder reverse() : 反转容器中的内容
    • int length() : 返回长度
    • String toString() : 将StringBuilder转换成String

StringJoiner

  • 与 StringBuilder 一样可以看成是一个容器, 创建之后里面的==内容是可变==的

  • 作用: 提高字符串的操作效率, 而且代码编写更加简洁, 但是目前市场上很少有人用(JDK8后出现的)

  • 构造方法

    • StringJoiner sj = new StringJoiner(间隔符号) : 创建一个对象, 指定拼接时的间隔符号
    • StringJoiner sj = new StringJoiner(间隔符号, 开始符号, 结束符号) : 创建一个对象, 指定拼接时的间隔符号、开始符号、结束符号
  • 常用方法

    • StringJoiner add(添加的内容)
    • int length()
    • String toString()

java已经写好的类, java在底层对它们做了一些处理, 使得打印对象不是地址值而是属性值

字符串原理

  • 字符串存储的内存原理

    • 直接赋值会复用字符串常量池中的
    • new 出来不会复用, 而是开辟一个新空间
  • == 比较的到底是什么

    • 基本数据类型比较数据值
    • 引用数据类型比较地址值
  • 字符串拼接的底层原理

    • 无变量直接拼接: 会复用串池中的字符串

      image-20250118233414663

    • 有变量拼接

      • JDK8前: String s2 = s1 + "b" 相当于 new StringBuilder().append(s1).append("b").toString()

        image-20250118233419196

      • JDK8后: 预估空间, 创建数组

        image-20250118233424984

    • 结论: 如果很多字符串变量拼接, 不要直接 + , 在底层会创建多个对象, 浪费时间, 浪费空间 (建议使用StringBuilder)

  • StringBuilder提高效率原理图

    image-20250118233429606

  • StringBuilder源码分析

    • 默认创建一个长度为16的字节数组
    • 添加的内容长度小于16, 则直接存
    • 添加的内容长度大于16, 则扩容 (原来容量 * 2 + 2)
    • 如果扩容后还不够, 则以实际长度为准扩容

ArrayList

  • 集合和数组的对比

    • 数组长度固定; 集合长度可变 (自动扩容)

    • 数组可以存基本数据类型和引用数据类型; 集合可以存引用数据类型, 如果要存基本数据类型, 只能存包装类

      基本数据类型 对应的包装类
      byte Byte
      short Short
      char Character
      int Integer
      long Long
      float Float
      double Double
      boolean Boolean
  • 泛型(<E>): 集合中存储数据的类型

  • 创建集合对象

    • ArrayList<数据类型> list = new ArrayList<>()
  • ArrayList 时 Java 已经写好的一个类, 这个类在底层做了一些处理

    • 打印对象不是地址值, 而是集合中存储数据内容
  • 成员方法

      • boolean add(E e) : 返回值表示是否添加成功
      • boolean remove(E e) : 返回值表示是否删除成功
      • E remove(int index) : 删除指定索引的元素, 返回被删除的元素
      • E set(int index, E e) : 返回原来的元素
      • E get(int index)
      • int size()

Math

  • 常用方法

    • int abs(int a)
    • double ceil(double a) : 向上取整
    • double floor(double a) : 向下取整
    • int round(float a) : 四舍五入
    • int max(int a, int b)
    • double pow(double a, double b) : b可以是负数或小数
    • double sqrt(double a)
    • double cbrt(double a)
    • double random() : 返回值为double的随机值, 范围[0.0, 1.0)

System

  • 常用方法

    • void exit(int status) : 终止当前java虚拟机(0 : 正常停止;1 : 异常停止)
    • long currentTimeMillis() : 返回当前系统的时间毫秒值形式(时间原点 1970.1.1 8:0:0)
    • void arraycopy(数据源数组, 起始索引, 目的地数组, 起始索引, 拷贝个数) : 数组拷贝
  • 输出语句

    • System.out.println()
    • System : 类名
    • out : 静态变量
    • System.out : 获取打印的对象
    • println() : 方法
    • 参数 : 表示打印的内容
    • 核心逻辑
      • 当我们打印一个对象的时候, 底层会调用对象的toString方法, 把对象变成字符串, 然后再打印再控制台上, 打印完毕换行处理

Runtime

  • 常用方法

    • Runtime getRuntime() : 获取当前系统的运行环境对象
    • void exit(int status) : 停止虚拟机
    • int availableProcessors() : 获得CPU的线程数
    • long maxMemory() : JVM能从系统中获取总内存大小(单位byte)
    • long totalMemory() : JVM已经从系统中获取总内存大小(单位byte)
    • long freeMemory() : JVM剩余内存大小(单位byte)
    • Process exec(String command) : 运行cmd命令

Object

  • 顶级父类, 只有空参构造

  • 常用方法

    • String toString()

      • 默认情况下, 因为Object类中的toString方法返回的是地址值, 所以, 默认情况下, 打印一个对象打印的就是地址值, 但是地址值对于我们是没有意义的
      • 处理方案: 重写父类Object中的toString方法
    • boolean equals(Object obj)

      • 同上, 默认的Object方法比较的是地址值, 需要重写

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        String s = "abc";
        StringBuilder sb = new StringBuilder("abc");
        sout(s.equals(sb)); // false
        // equals方法是被s调用的, 而s是字符串
        // 所以equals要看String类中的
        // 字符串中的equals方法, 先判断参数是否为字符串
        // 如果是字符串, 再比较内部的属性
        // 但如果参数不是字符串的, 直接返回false

        sout(sb.equals(s)); // false
        // 由于StringBuildedr中没有重写equals方法
        // 使用的是Object中的, 即比较地址值
    • protected Object clone(int a)

      • 方法在底层会帮我们创建一个对象, 并把原对象中的数据拷贝过去
      • 书写细节
        • 重写Object中的clone方法
        • 让JavaBean类实现Cloneable接口
        • 创建原对象并调用clone
      • 浅克隆 (Object默认浅克隆)
        • 不管对象内部的属性是基本数据类型还是引用数据类型, 都完全拷贝过来
      • 深克隆 (自己重写或使用第三方工具)
        • 基本数据类型拷贝过来, 常量池中的字符串复用, 引用数据类型会重新创建新的

Objects

  • 工具类

  • 常用方法

    • boolean equals(Object a, Object b) : 先做非空判断, 再比较两个对象
      • 方法底层先判断a是否为null, 如果是null, 直接返回false, 如果不是, 那么就利用a再次调用equals方法
    • boolean isNull(Object obj)
    • boolean nonNull(Object obj)

BigInteger

  • 在底层占用字节个数: byte1个字节, short2个字节, int4个字节, float4个字节, double8个字节, long8个字节

  • 构造方法

    • BigInteger(int num, Random rnd) : 获取随机大整数, 范围: [0, 2num - 1]

    • BigInteger(String val) : 获取指定的大整数

    • BigInteger(String val, int radix) : 获取指定进制的大整数

    • public static BigInteger valueOf(long val) : 静态方法获取BigInteger的对象, 内部有优化

  • 总结

    • 如果BigInteger表示的数字没有超出long的范围, 可以用静态方法获取

    • 如果BigInteger表示的超出long的范围, 可以用构造方法获取

    • 对象一旦创建, BigInteger内部记录的值不能发生改变

      1
      2
      3
      4
      5
      6
      BigInteger bd1 = BigInteger.valueOf(10);
      BigInteger bd2 = BigInteger.valueOf(5);
      BigInteger bd3 = BigInteger.valueOf(10);

      sout(bd1 == bd2); // false
      sout(bd1 == bd3); // true
    • 只要进行计算都会产生一个新的BigInteger对象

  • 常见方法

    • BigInteger add(BigInteger val) : 加法
    • BigInteger subtract(BigInteger val) : 减法
    • BigInteger multiply(BigInteger val) : 乘法
    • BigInteger divide(BigInteger val) : 除法, 获取商
    • BigInteger[] divideAndRemainder(BigInteger val) : 除法, 获取商和余数
    • boolean equals(Object x)
    • BigInteger pow(int exponent)
    • BigInteger max/min(BigInteger val)
    • int intValue(BigInteger val) : 转为int类型正数, 超出范围数据有误

BigDecimal

  • 用于小数的精确运算

  • 构造方法

    • BigDecimal(double val) : 有可能不准确, 不建议使用
    • BigDecimal(String val) : 更加精确
    • public static BigDecimal valueOf(double val)
  • 细节

    • 如果表示的数字不大, 没有超出double的取值范围, 建议使用静态方法
    • 如果要表示的数字比较大, 超出了double的取值范围, 建议使用构造方法
    • 如果我们传递的是0~10之间的整数(如果是小数还是会重新new), 包含0和10, 那么方法会返回已经创建好的对象, 不会重新new
  • 常用方法

    • BigDecimal add(BigDecimal val)
    • BigDecimal substract(BigDecimal val)
    • BigDecimal multiply(BigDecimal val)
    • BigDecimal divide(BigDecimal val) : 整除
    • BigDecimal divide(BigDecimal val, 精确几位, 舍入模式)
      • 舍入模式(RoundingMode)
        • UP : 远离零方向舍入
        • DOWN : 向零方向舍入
        • CEILING : 向正无限大方向舍入
        • FLOOR : 向负无限大方向舍入
        • HALF_UP : 四舍五入(0.5向上舍)
        • HALF_DOWN : 四舍五入(0.5向下舍)

正则表达式

  • 作用

    • 校验字符串是否满足规则
    • 在一段文本中查找满足要求的内容
  • 用法

    image-20250118233446185

  • [] : 只匹配其中的一个

  • (?i)xxx : 忽略xxx的大小写

  • 贪婪爬取

    • ab+ 或 ab*

      • 贪婪(尽可能多): abbbbbbbbbbb…
    • java默认的是贪婪爬取

  • 非贪婪

    • ab+? 或 ab*?
      • 非贪婪(尽可能少): ab
  • 正则表达式在字符串中的作用

    • boolean matches(String regex) : 判断字符串是否满足正则表达式的规则
    • String replaceAll(String regex, String newStr) : 按照正则表达式的规则进行替换
    • String[] split(String regex) : 按照正则表达式的规则切割字符串
  • 捕获分组

    • 每组有组号

      • 以左括号为基准, 最左边的是第一组, 其次是第二组, 以此类推
    • \\组号 : 表示把第x组的内容拿出来再用一次

    • 以 (.)\\1* 为例

      • (.) : 以任意单字符看作第一组
      • \\1 : 把第一组拿出来再次使用
      • * : 作用于 \\1, 表示把第一组拿出来用0次或多次
    • 后续还要继续使用本组数据

      • 正则内部使用 : \\组号
      • 正则外部使用 : $组号
      • 例 : String s = str.relpaceAll("(.)\\1*", "$1");
  • 非捕获分组

    • 仅仅是把数据括起来, 不占用组号
    • xxx(?=yyy) : ? 指代前面的数据xxx, = 表示xxx后面要跟随的数据, 获取时只获取xxx
    • xxx(?:yyy) : ? 指代前面的数据xxx, : 表示xxx后面要跟随的数据, 获取时获取所有
    • xxx(?!yyy) : ? 指代前面的数据xxx, ! 表示xxx后面要跟随的数据, 获取时只获取不包含yyy的xxx文本

爬虫

  • Pattern : 表示正则表达式对象

  • Matcher : 文本匹配器, 按照正则表达式的规则去读取字符串, 从头开始读取

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // 获取正则表达式对象
    Pattern p = Pattern.compile(regex);
    // 获取文本匹配器对象
    // m在str中找符合p规则的小串
    Matcher m = p.matcher(str);
    // 寻找匹配器中满足规则的子串
    // 如果没有返回false, 如果有返回true, 在底层记录子串的 起始索引 和 结束索引+1
    while(m.find()) {
    // 方法底层会根据find方法记录的索引进行字符串的截取
    String s = m.group();
    sout(s);
    }

JDK7以前的时间相关类

Date

  • Javabean类, 用来描述时间, 精确到毫秒

  • 构造方法

    • Date date = new Date() : 创建当前时间对象
    • Date date = new Date(毫秒值) : 创建指定时间对象
  • 常用方法

    • void setTime(long time) : 设置/修改毫秒值
    • long getTime() : 获取时间对象的毫秒值

SimpleDateFormat

  • 作用

    • 格式化: 把时间变成我们喜欢的格式

    • 解析: 把字符串表示的时间变成Data对象

  • 构造方法

    • SimpleDateFormat() : 使用默认格式
    • SimpleDateFormat(String pattern) : 使用指定格式
  • 常用方法

    • final String format(Date date) : 格式化 (日期对象 – 字符串)
    • Date parse(String source) : 解析 (字符串 – 日期对象)

Calendar

  • Calendar代表了系统当前时间的日历对象, 可以单独修改、获取时间中的年、月、日

  • 细节

    • Calendar是一个抽象类, 不能直接创建对象
    • 月份范围: 0~11
    • 星期范围: 1~7 (但是1代表星期日)
    • 字段表示 (Calendar类中有常量表示)
      • 0 – 纪元 1 – 年 2 – 月 3 – 一年中的第几周 4 – 一个月中的第几周 5 – 一个月中的第几天(日期)
  • 获取Calendar日历类对象的方法

    • public static Calendar getInstance() : 获取当前时间的日历对象
  • 常用方法

    • final Date getTime() : 获取日期对象
    • final setTime(Date date) : 给日历设置日期对象
    • long getTimeInMillis() : 得到时间毫秒值
    • void setTimeInMillis(long millis) : 给日历设置时间毫秒值
    • int get(int field) : 取日历中的某个字段信息
    • void set(int field, int value) : 修改日历的某个字段信息
    • void add(int field, int amount) : 为某个字段增加/减少指定的值

JDK8新增的时间相关类

  • 代码更简单, 数据更安全==(对象不可变)==

  • 月份范围: 1~12

Date相关

ZoneId

  • 时区

    • 洲名/城市名 国家名/城市名
  • 常用方法

    • static Set<String\> getAvailableZoneIds() : 获取Java中支持的所有时区
    • static ZoneId systemDefault() : 获取系统默认时区
    • static ZoneId of(String zoneId) : 获取一个指定时区

Instant

  • 时间戳

  • 常用方法

    • static Instant now() : 获取当前时间的Instant对象 (标准时间)
    • static Instant ofXxxx(long epochMilli) : 根据 (秒/毫秒/纳秒) 获取Instant对象
    • ZonedDateTime atZone(ZoneId zone) : 指定时区
    • boolean isXxx(Instant otherInstant) : 判断系列的方法
    • Instant minusXxx(long millisToSubtract) : 减少时间系列的方法
    • Instant plusXxx(long millisToSubstract) : 增加时间系列的方法

ZonedDateTime

  • 带时区的时间

  • 常用方法

    • static ZonedDateTime now() : 获取当前时间的ZonedDateTime对象
    • static ZonedDateTime ofXxx(...) : 获取指定时间的ZonedDateTime对象
    • ZonedDateTime withXxx(时间) : 修改时间系列的方法
    • ZonedDateTime minusXxx(时间) : 减少时间系列的方法
    • ZonedDateTime plusXxx(时间) : 增加时间系列的方法

SimpleDateFormat相关

DateTimeFormatter

  • 常用方法

    • static DateTimeFormatter ofPattern(格式) : 获取格式对象
    • String format(时间对象) : 按照指定方式格式化

Calendar相关

LocalDate

  • 年、月、日

LocalTime

  • 时、分、秒

LocalDateTime

  • 年、月、日、时、分、秒

  • 常用方法

    • static XXX now() : 获取当前时间对象
    • static XXX of(...) : 获取指定时间对象
    • get开头方法 : 获取日历中的年、月、日、时、分、秒等信息
    • isBefore, isAfter : 比较两个 LocalDate
    • with开头的 : 修改时间系列的方法
    • minus开头的 : 减少时间系列的方法
    • plus开头的 : 增加时间系列的方法
    • public LocalDate toLocalDate() : LocalDateTime转换成一个LocalDate对象
    • public LocalTime toLocalTime() : LocalDateTime转换成一个LocalTime对象

工具类

Duration

  • 计算时间间隔 (秒, 纳秒)

Period

  • 计算日期间隔 (年、月、日)

ChronoUnit

  • 计算日期间隔

包装类

  • 基本数据类型对应的引用类型

  • 获取Integer对象的方法

    • public Integer(int value)
    • public Integer(String s)
    • public static Integer valueOf(int i)
    • public static Integer valueOf(String s)
    • public static Integer valueOf(String s, int radix)
    • 区别
      • 前两种通过 new 创建对象
      • 后三种当创建 -128~127 的数据对象时, 不会创建新的, 而是调用已经创建好的对象
  • JDK5提出的新机制

    • 自动装箱: 把基本数据类型自动变成其对应的包装类
    • 自动拆箱: 把包装类自动变成其对应的基本数据类型
    • 在底层自动调用静态方法valueOf得到一个Integer对象
    • 即在JDK5以后, int 和 Integer 可以看作同一个东西
  • 常用方法

    • static String toBinaryString(int i)
    • static String toOctalString(int i)
    • static String toHexString(int i)
    • static int parseInt(String s) : 将字符串类型的整数转成int类型的整数
      • 8种包装类, 除了Character都有对应的parseXxx方法, 进行类型转换

Arrays

  • 操作数组的工具类

  • 常用方法

    • static String toString(数组) : 把数组拼接成一个字符串

    • static int binarySearch(数组, 查找的元素) : 二分查找法查找元素

    • static int[] copyOf(原数组, 新数组长度) : 拷贝数组

    • static int[] copyOfRange(原数组, 起始索引, 结束索引) : 拷贝数组 (指定范围)

    • static void fill(数组, 元素) : 填充数组

    • static void sort(数组) : 按照默认方法进行数组排序

    • static void sort(数组, 排序规则) : 按照指定的规则排序

      • 只能给引用数据类型的数组进行排序, 如果数组是基本数据类型的, 需要变成其对应的包装类

        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
        // 底层原理:
        // 利用插入排序 + 二分查找的方式进行排序
        // 默认把0索引的数据当作是有序的序列, 1索引到最后认为是无序的序列
        // 遍历无序序列得到里面的每一个元素, 假设当前遍历得到的元素是A
        // 把A往有序序列中进行插入, 在插入时, 利用二分查找确定A元素的插入点
        // 拿着A元素, 跟插入到的元素进行比较, 比较的规则就compare方法的方法体
        // 如果返回值是负数, 拿着A继续跟前面的数据进行比较
        // 如果返回值是整数, 拿着A继续跟后面的数据进行比较
        // 如果返回值是0, 也拿着A跟后面的数据进行比较

        // 匿名内部类
        Arrays.sort(arr, new Comparator<Integer>() {
        // compare方法的形式参数:
        // 参数一 o1: 表示在无序序列中, 遍历得到的每一个元素
        // 参数二 o2: 有序序列中的元素
        // 返回值:
        // 负数: 表示当前要插入的元素o1放在前面
        // 正数: 表示当前要插入的元素o1放在后面
        // 0: 表示当前要插入的元素o1跟现在的元素o2是一样的, 也放在后面
        @Override
        public int compare(Integer o1, Integer o2) {
        return 0;
        }
        });

        // 简单理解:
        // o1 - o2 : 升序排列
        // o2 - o1 : 降序排列

Lambda表达式

  • 函数式编程 (Functional programming)

    • 是一种思想特点, 忽略面向对象的复杂语法, 强调做什么, 而不是谁去做
  • JDK8后出现的新语法形式

    • ( ) -> { }
      • ( ) : 对应着方法的形参
      • -> : 固定格式
      • { } : 对应着方法的方法体
  • 注意点

    • 可以用来简化匿名内部类内部类的书写
    • 但只能简化函数式接口的匿名内部类写法
      • 有且仅有一个抽象方法的接口叫做函数式接口, 接口上方可以加@FunctionalInterface注释
    1
    2
    3
    4
    5
    // Lambda完整格式
    Arrays.sort(arr, (Integer o1, Integer o2) -> {
    return o1 - o2;
    }
    );
  • 省略规则

    • 参数类型可以省略
    • 如果只有一个参数, 参数类型和( )都可以省略
    • 如果Lambda表达式的方法体只有一行, 大括号, 分号, return可以省略不写, 需要同时省略
    1
    2
    // Lambda省略写法
    Arrays.sort(arr, (o1, o2) -> o1 - o2);