02.API
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
3char[] chs = {'a', 'b', 'c', 'd'};
String s4 = new String(chs);
sout(s4); // abcd 
 - 
 - 
String name = new String(byte[] chs)- 
应用场景: 在网络当中传输的数据都是字节信息, 一般要将字节信息进行转换, 转成字符串, 此时就要用到这个构造
1
2
3byte[] bytes = {97, 98, 99, 100};
String s5 = new String(bytes);
sout(s5); // abcd 
 - 
 
 - 
 - 
内存模型
- 
当使用双引号直接赋值时, 系统会检查该字符串在串池中是否存在,不存在则创建新的, 存在则复用 (节约内存)
 - 
每次 new 都会创造一个新空间, 这种方式创建对象不会复用 (占内存)
 
 - 
 - 
常用方法
- 字符串比较
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 出来不会复用, 而是开辟一个新空间
 
 - 
==比较的到底是什么- 基本数据类型比较数据值
 - 引用数据类型比较地址值
 
 - 
字符串拼接的底层原理
- 
无变量直接拼接: 会复用串池中的字符串
 - 
有变量拼接
- 
JDK8前:
String s2 = s1 + "b"相当于new StringBuilder().append(s1).append("b").toString() - 
JDK8后: 预估空间, 创建数组
 
 - 
 - 
结论: 如果很多字符串变量拼接, 不要直接 + , 在底层会创建多个对象, 浪费时间, 浪费空间 (建议使用StringBuilder)
 
 - 
 - 
StringBuilder提高效率原理图
 - 
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
12String 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
6BigInteger 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向下舍)
 
 
- 舍入模式(RoundingMode)
 
 
正则表达式
- 
作用
- 校验字符串是否满足规则
 - 在一段文本中查找满足要求的内容
 
 - 
用法
 - 
[] : 只匹配其中的一个
 - 
(?i)xxx : 忽略xxx的大小写
 - 
贪婪爬取
- 
ab+ 或 ab*
- 贪婪(尽可能多): abbbbbbbbbbb…
 
 - 
java默认的是贪婪爬取
 
 - 
 - 
非贪婪
- ab+? 或 ab*?
- 非贪婪(尽可能少): 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是一样的, 也放在后面
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); 
















