0459 0497 第十三章 常用类
13.1 包装类(Wrapper)¶
13.1.1 包装类的分类¶
- 针对八种基本数据类型相应的引用类型—包装类
- 有了类的特点,就可以调用类中的方法。
| 基本数据类型 | 包装类 | 父类 |
|---|---|---|
| boolean | Boolean | |
| char | Character | |
| byte | Byte | Number |
| short | Short | Number |
| int | Integer | Number |
| long | Long | Number |
| float | Float | Number |
| double | Doubke | Number |
13.1.2 包装类和基本数据的转换¶
-
jdk 5 前的手动装箱和拆箱方式,
- 包装: 基本类型 -> 包装类型
- 拆箱:
-
jdk 5 以后 (含 jdk 5) 的自动装箱和拆箱方式
-
自动装箱后层调用的是
valueOf方法,Integer.valueOf ()
4. 其它包装类的用法类似,不一举例¶
13.1.3 案例演示¶
public class Integer01 {
public static void main(String[] args) {
//演示 int <--> Integer 的装箱和拆箱
//jdk5 前是手动装箱和拆箱//手动装箱 int->Integer int n1 = 100;
Integer integer = new Integer(n1); Integer integer1 = Integer.valueOf(n1);
//手动拆箱//Integer -> int
int i = integer.intValue();
//jdk5 后,就可以自动装箱和自动拆箱int n2 = 200;
//自动装箱 int->Integer
Integer integer2 = n2; //底层使用的是 Integer.valueOf(n2)
//自动拆箱 Integer->int
int n3 = integer2; //底层仍然使用的是 intValue()方法
}
}
13.1.5 包装类型和 String 类型的相互转换¶
public class WrapperVSString {
public static void main(String[] args) {
//包装类(Integer)->String
Integer i = 100;//自动装箱//方式 1
String str1 = i + "";
//方式 2
String str2 = i.toString();
//方式 3
String str3 = String.valueOf(i);
//String -> 包装类(Integer)
String str4 = "12345";
Integer i2 = Integer.parseInt(str4);//使用到自动装箱
Integer i3 = new Integer(str4);//构造器
System.out.println("ok~~");
}
}
13.1.6 Integer 类和 Character 类的常用方法¶
public class WrapperMethod {
public static void main(String[] args) {
System.out.println(Integer.MIN_VALUE); //返回最小值
System.out.println(Integer.MAX_VALUE);//返回最大值
System.out.println(Character.isDigit('a'));//判断是不是数字
System.out.println(Character.isLetter('a'));//判断是不是字母
System.out.println(Character.isUpperCase('a'));//判断是不是大写
System.out.println(Character.isLowerCase('a'));//判断是不是小写
System.out.println(Character.isWhitespace('a'));//判断是不是空格
System.out.println(Character.toUpperCase('a'));//转成大写
System.out.println(Character.toLowerCase('A'));//转成小写
}
}
13.1.7 Integer 类面试题¶
public class WrapperExercise02 {
public static void main(String[] args) {
Integer i = new Integer(1);
Integer j = new Integer(1);
System.out.println(i == j); //False
//所以,这里主要是看范围 -128 ~ 127 就是直接返回
/*
老韩解读
//1. 如果 i 在 IntegerCache.low(-128)~IntegerCache.high(127),就直接从数组返回
//2. 如果不在 -128~127,就直接 new Integer(i)
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
*/
Integer m = 1; //底层 Integer.valueOf(1); -> 阅读源码
Integer n = 1;//底层 Integer.valueOf(1);
System.out.println(m == n); //T
//所以,这里主要是看范围 -128 ~ 127 就是直接返回
//,否则,就 new Integer(xx);
Integer x = 128;//底层 Integer.valueOf(1);
Integer y = 128;//底层 Integer.valueOf(1);
System.out.println(x == y);//False
}
}
public class WrapperExercise03 {
public static void main(String[] args) {
//示例一
Integer i1 = new Integer(127);
Integer i2 = new Integer(127);
System.out.println(i1 == i2);//F
//示例二
Integer i3 = new Integer(128);
Integer i4 = new Integer(128);
System.out.println(i3 == i4);//F
//示例三
Integer i5 = 127;//底层 Integer.valueOf(127)
Integer i6 = 127;//-128~127
System.out.println(i5 == i6); //T
//示例四
Integer i7 = 128; Integer i8 = 128;
System.out.println(i7 == i8);//F
//示例五
Integer i9 = 127; //Integer.valueOf(127)
Integer i10 = new Integer(127);
System.out.println(i9 == i10);//F
//示例六
Integer i11 = 127;
int i12 = 127;
//只有有基本数据类型,判断的是
//值是否相同
System.out.println(i11 == i12); //T
//示例七
Integer i13 = 128;
int i14 = 128;
System.out.println(i13 == i14); //T
}
}
13.2 String 类¶
13.2.1 String 类的理解和创建对象¶
-
String 对象用于保存字符串,也就是一组字符序列
-
字符串常量对象是用双引号括起的字符序列。例如:"你好"、"12.97"、"boy"等
-
字符串的字符使用 Unicode 字符编码,一个字符 (不区分字母还是汉字) 占两个字节。
-
String 类较常用构造器 (其它看手册):
String s1 = new String ();String s2 = new String(String original);String s3 = new String(char[] a);String s4 = new String(char[] a,int startlndexjnt count)
-
String 类实现了接口 Serializable
- String 可以串行化:可以在网络传输
- 接口 Comparable :String 对象可以比较大小
-
String 是 final 类,不能被其他的类继承
-
String 有属性
private final char value[]; 用于存放字符串内容 -
value 是一个 final 类型,不可以修改 (需要功力):
- 即 value 不能指向新的地址
- 但是单个字符内容是可以变化
13.2.2 创建 String 对象的两种方式¶
-
方式一:直接赋值
String s = "123";
-
方式二:调用构造器
String s = new String("234")
13.2.3 两种创建 String 对象的区别¶
-
方式一:先从常量池直看是否有 "123" 数据空间,如果有,直接指向;
- 如果没有则重新创建,然后指向。
- s 最终指向的是常量池的空间地址
-
方式二:先在堆中创建空间,里面维护了 value 属性,
- 指向常量池的 123 空间。
- 如果常量池没有"hsp", 重新创建
- 如果有,直接通过 value 指向。
- 最终指向的是堆中的空间地址
13.3 String 字符串的特性¶
- String 是一个 final 类,代表不可变的字符序列
- 字符串是不可变的。一个字符串对象一旦被分配,其内容是不可变的
13.4 String 类的常见用法¶
13.4.1 创建新字符串的方法¶
这些方法会返回一个新的 String 对象,而不会修改原始字符串。
- substring (int beginIndex) / substring (int beginIndex, int endIndex)
- 功能:提取子字符串。
substring(int beginIndex):从beginIndex开始到字符串末尾。substring(int beginIndex, int endIndex):从beginIndex到endIndex-1。
- 返回值:新的子字符串。
- 异常:如果索引越界,抛出
IndexOutOfBoundsException。 -
示例:
-
concat (String str)
- 功能:将指定字符串连接到当前字符串的末尾。
- 返回值:新的字符串(原字符串 + 指定字符串)。
-
示例:
-
replace (char oldChar, char newChar) / replace (CharSequence target, CharSequence replacement)
- 功能:
replace(char oldChar, char newChar):将字符串中的oldChar替换为newChar。replace(CharSequence target, CharSequence replacement):将字符串中的target子串替换为replacement。
- 返回值:新的字符串(替换后的结果)。
-
示例:
-
toUpperCase () / toLowerCase ()
- 功能:
toUpperCase():将字符串转换为全大写。toLowerCase():将字符串转换为全小写。
- 返回值:新的字符串(转换后的结果)。
-
示例:
-
trim ()
- 功能:去除字符串首尾的空白字符(空格、制表符、换行符等,ASCII 码 <= 32)。
- 返回值:新的字符串(去除首尾空白后的结果)。
-
示例:
-
replaceAll (String regex, String replacement) / replaceFirst (String regex, String replacement)
- 功能:
replaceAll:使用正则表达式替换所有匹配的子串。replaceFirst:仅替换第一个匹配的子串。
- 返回值:新的字符串(替换后的结果)。
- 异常:如果正则表达式无效,抛出
PatternSyntaxException。 -
示例:
-
split (String regex) / split (String regex, int limit)
- 功能:根据正则表达式将字符串分割为字符串数组。
limit:控制分割次数(数组的最大长度)。
- 返回值:新的字符串数组。
- 异常:如果正则表达式无效,抛出
PatternSyntaxException。 -
示例:
-
strip () / stripLeading () / stripTrailing ()(Java 11 及以上)
- 功能:
strip():去除字符串首尾的空白字符(包括 Unicode 空白字符)。stripLeading():仅去除首部空白字符。stripTrailing():仅去除尾部空白字符。
- 返回值:新的字符串。
- 示例:
13.4.2 不创建新字符串的方法¶
这些方法不修改原始字符串,也不返回新的字符串对象,而是返回其他类型的结果(如布尔值、整数、字符等)。
- length ()
- 功能:返回字符串的长度(字符数)。
- 返回值:
int类型。 -
示例:
-
charAt (int index)
- 功能:返回指定索引处的字符。
- 返回值:
char类型。 - 异常:如果索引越界,抛出
IndexOutOfBoundsException。 -
示例:
-
isEmpty ()
- 功能:检查字符串是否为空(长度为 0)。
- 返回值:
boolean类型。 -
示例:
-
equals (Object obj) / equalsIgnoreCase (String anotherString)
- 功能:
equals:比较字符串内容是否相等。equalsIgnoreCase:忽略大小写比较字符串内容。
- 返回值:
boolean类型。 -
示例:
-
contains (CharSequence s)
- 功能:检查字符串是否包含指定子串。
- 返回值:
boolean类型。 -
示例:
-
startsWith (String prefix) / endsWith (String suffix)
- 功能:
startsWith:检查字符串是否以指定前缀开头。endsWith:检查字符串是否以指定后缀结尾。
- 返回值:
boolean类型。 -
示例:
-
indexOf (int ch) / indexOf (String str) / lastIndexOf (int ch) / lastIndexOf (String str)
- 功能:
indexOf:返回指定字符或子串第一次出现的索引。lastIndexOf:返回指定字符或子串最后一次出现的索引。
- 返回值:
int类型(未找到返回 -1)。 -
示例:
-
isBlank ()(Java 11 及以上)
- 功能:检查字符串是否为空或仅包含空白字符(包括 Unicode 空白字符)。
- 返回值:
boolean类型。 - 示例:
13.4.3 总结¶
- 创建新字符串的方法(返回新的
String对象): substring、concat、replace、replaceAll、replaceFirst、toUpperCase、toLowerCase、trim、split、strip、stripLeading、stripTrailing。- 这些方法因
String的不可变性,总是返回新的字符串对象。 - 不创建新字符串的方法(返回非
String类型,如boolean、int、char): length、charAt、isEmpty、equals、equalsIgnoreCase、contains、startsWith、endsWith、indexOf、lastIndexOf、isBlank。- 这些方法仅查询或比较字符串内容,不涉及字符串内容的修改。
- 注意事项:
String不可变,任何修改操作都会生成新对象,需注意性能(频繁操作可能导致内存开销)。- 使用
StringBuilder或StringBuffer可优化频繁的字符串拼接操作。 - 某些方法(如
substring、replaceAll)可能抛出异常,需注意异常处理。
13.4.4 综合示例¶
public class StringMethodsExample {
public static void main(String[] args) {
String str = " Hello, World! ";
// 创建新字符串的方法
System.out.println("substring: " + str.substring(2, 7)); // "Hello"
System.out.println("concat: " + str.concat(" Java")); // " Hello, World! Java"
System.out.println("replace: " + str.replace("World", "Java")); // " Hello, Java! "
System.out.println("toUpperCase: " + str.toUpperCase()); // " HELLO, WORLD! "
System.out.println("trim: " + str.trim()); // "Hello, World!"
// 不创建新字符串的方法
System.out.println("length: " + str.length()); // 16
System.out.println("charAt: " + str.charAt(3)); // 'H'
System.out.println("isEmpty: " + str.isEmpty()); // false
System.out.println("contains: " + str.contains("World")); // true
System.out.println("startsWith: " + str.startsWith(" H")); // true
System.out.println("indexOf: " + str.indexOf("o")); // 4
}
}
13.5 StringBuffer 类¶
13.5.1 基本介绍¶
- java. Iang. StringBuffe 代表可变的字符序列,可以对字符串内容进行增删。
- 很多方法与 String 相同,但 StringBuffer 是可变长度的。
- StringBuffer 是一个容器
StringBuffer是 Java 提供的一个可变字符串类,位于java.lang包中,设计用于在多线程环境中安全地进行字符串操作。
13.5.2 基本特性¶
- 可变性:
StringBuffer的内容可以动态增删改,适合频繁的字符串操作。 - 线程安全:
StringBuffer的方法大多是同步的(synchronized),因此在多线程环境下是线程安全的。 - 性能:由于线程同步的开销,
StringBuffer的性能略低于非线程安全的StringBuilder。 - 初始容量:默认初始容量为 16 个字符(可以指定初始容量),当内容超出容量时会自动扩容(通常为当前容量的两倍加 2)。
StringBuffer的直接父类是 `AbstractStringBuilder- StringBuffer 实现了 Serializable, 即 StringBuffer 的对象可以串行化
- 在父类中 AbstractStringBuilder 有属性 char[] value, 不是 final 该 value 数组存放字符串内容,引出存放在堆中的
- StringBuffer 是一个 final 类,不能被继承
- 因为 StringBuffer 字符内容是存在
char[] value, 所以在变化 (增加/删除) 不用每次都更换地址 (即不是每次创建新对象), 所以效率高于 String
13.5.3 常用构造方法¶
StringBuffer():构造一个空的StringBuffer,初始容量为 16。StringBuffer(int capacity):指定初始容量。StringBuffer(String str):用给定的字符串初始化。StringBuffer(CharSequence seq):用字符序列初始化。
StringBuffer sb1 = new StringBuffer(); // 空,容量 16
StringBuffer sb2 = new StringBuffer(32); // 空,容量 32
StringBuffer sb3 = new StringBuffer("Hello"); // 初始化为 "Hello"
13.5.4 常用方法¶
StringBuffer 提供了丰富的字符串操作方法,大多直接修改对象本身并返回 StringBuffer(支持链式调用)。以下是常用方法:
添加内容¶
append(...):在末尾追加内容(支持多种类型:String、char、int、boolean等)。insert(int offset, ...):在指定位置插入内容。
删除内容¶
delete(int start, int end):删除从start到end-1的字符。deleteCharAt(int index):删除指定索引的字符。
修改内容¶
replace(int start, int end, String str):用str替换从start到end-1的内容。setCharAt(int index, char ch):将指定索引的字符替换为ch。
反转¶
reverse():反转字符串内容。
查询与获取¶
length():返回当前字符串长度。capacity():返回当前容量。charAt(int index):获取指定索引的字符。substring(int start)/substring(int start, int end):提取子字符串(返回新的String)。
13.5.5 StringBuffer 与 String 的对比¶
| 特性 | String | StringBuffer |
|---|---|---|
| 可变性 | 不可变(immutable),修改生成新对象 | 可变(mutable),直接修改原对象 |
| 线程安全 | 线程安全(因不可变性) | 线程安全(方法同步) |
| 性能 | 频繁修改时性能差(生成多个对象) | 适合频繁修改的场景,性能优于 String |
| 内存占用 | 每次修改产生新对象,占用内存多 | 修改在原对象上,内存占用少 |
| 适用场景 | 字符串内容固定或少量修改 | 频繁拼接、修改(多线程环境) |
| 常用方法 | concat, substring, replace 等 |
append, delete, reverse 等 |
| 初始容量 | 无(固定大小) | 默认 16,可扩容 |
性能分析¶
-
String:每次修改(如
+或concat)都会创建新对象,导致内存分配和垃圾回收开销。例如:上述代码会生成大量临时对象,效率低下。 - StringBuffer:修改操作(如
append)直接在内部字符数组上进行,避免频繁创建对象:
使用场景¶
- String:适合多线程环境下少量字符串操作,或字符串内容不经常变化的场景(如常量字符串)。
- StringBuffer:适合多线程环境下频繁进行字符串操作的场景(如日志拼接、动态构建字符串)。
13.5.6 StringBuffer 与 String 的相互转换¶
String 转换为 StringBuffer¶
有以下几种方式:
-
通过构造方法:
-
通过
append方法:
StringBuffer 转换为 String¶
有以下方式:
-
通过
toString()方法: -
通过
substring()方法(间接): -
通过构造器
示例代码(综合)¶
public class StringBufferExample {
public static void main(String[] args) {
// String 转 StringBuffer
String str = "Hello";
StringBuffer sb1 = new StringBuffer(str);
System.out.println("String to StringBuffer: " + sb1); // Hello
// StringBuffer 操作
sb1.append(", World").insert(5, "!").replace(7, 12, "Java");
System.out.println("After operations: " + sb1); // Hello!, Java
// StringBuffer 转 String
String result = sb1.toString();
System.out.println("StringBuffer to String: " + result); // Hello!, Java
// 性能对比
String s = "";
StringBuffer sb2 = new StringBuffer();
long start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
s += "a";
}
long stringTime = System.currentTimeMillis() - start;
System.out.println("String time: " + stringTime + "ms");
start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
sb2.append("a");
}
long bufferTime = System.currentTimeMillis() - start;
System.out.println("StringBuffer time: " + bufferTime + "ms");
}
}
13.5.7 与 StringBuilder 的简要对比¶
StringBuffer:线程安全,适合多线程环境,但性能稍低。StringBuilder(Java 5 引入):非线程安全,适合单线程环境,性能更高。- 选择建议:
- 多线程:优先
StringBuffer。 - 单线程或线程安全由外部控制:优先
StringBuilder。 - 少量修改或不可变需求:使用
String。
- 多线程:优先
13.6 StringBuilder 类¶
13.6.1 基本介绍¶
- 一个可变的字符序列
- 此类提供一个与 StringBuffer 兼容的 API, 但不保证同(StringBuilder 不是线程安全)。
- 该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候。
- 如果可能,建议优先采用该类, 因为在大多数实现中,它比 StringBuffer 要快
- 在 StringBuilder 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。
13.6.2 StringBuilder 常用方法¶
StringBuilder 和 StringBuffer 均代表可变的字符序列,方法是一样的,所以使用和 StringBuffer 一样
- StringBuilder 是 final 类, 不能被继承
- 继承了 AbstractStringBuilder, 属性
char[] value, 内容存到value,因此,字符序列是堆中 - 实现了 Serializable ,说明 StringBuilder 对象是可以串行化 (对象可以网络传输, 可以保存到文件)
- StringBuilder 继承 AbstractStringBuilder 类
- StringBuilder 的方法,没有做互斥的处理, 即没有 synchronized 关键字, 因此在单线程的情况下使用
13.6.3 String、 StringBuffer 和 StringBuilder 的比较¶
- StringBuilder 也一样 StringBuffer 非常类似,均代表可变的字符序列,而且方法也一样
- String: 不可变字符序列, 效率低,但是复用率高。
- StringBuffer: 可变字符序列、效率较高 (增删)、线程安全, 看源码
- StringBuilder: 可变字符序列、效率最高、线程不安全
- String 使用注意说明:
string s=”a"; 〃创建了一个字符串s+= "b";〃实际上原来的”a”字符串对象已经丢弃了,现在又产生了一个字符 s+”b” 也就是 "ab"- 如果多次执行这些改变事内容的操作,会导致大量副本字符串对象存留在内存中,降低效率
- 如果这样的操作放到循环中,会极大影响程序的性能
- 如果我们对 String 做大量修改,不要使用 String
13.6.4 String、 StringBuffer 和 StringBuilder 的效率测试¶
效率 : StringBuilder > StringBuffer > String
- 原因:
StringBuilder比StringBuffer快是因为它不使用同步机制,避免了锁的获取和释放开销。 - 选择建议:
- 单线程或性能优先:选择
StringBuilder。 - 多线程且需要线程安全:选择
StringBuffer。
- 单线程或性能优先:选择
public class StringVsStringBufferVsStringBuilder {
public static void main(String[] args) {
long startTime = 0L;
long endTime = 0L;
StringBuffer buffer = new StringBuffer("");
startTime = System.currentTimeMillis();
for (int i = 0; i < 80000; i++) {//StringBuffer 拼接 20000 次
buffer.append(String.valueOf(i));
}
endTime = System.currentTimeMillis();
System.out.println("StringBuffer 的执行时间: " + (endTime - startTime));
StringBuilder builder = new StringBuilder("");
startTime = System.currentTimeMillis();
for (int i = 0; i < 80000; i++) {//StringBuilder 拼接 20000 次
builder.append(String.valueOf(i));
}
endTime = System.currentTimeMillis();
System.out.println("StringBuilder 的执行时间: " + (endTime - startTime));
String text = "";
startTime = System.currentTimeMillis();
for (int i = 0; i < 80000; i++) {//String 拼接 20000
text = text + i;
}
endTime = System.currentTimeMillis();
System.out.println("String 的执行时间: " + (endTime - startTime));
}
}
13.7 Math 类¶
13.7.1 基本介绍¶
Math类包含用于基本数学运算的静态方法和常量,涵盖初等指数、对数、平方根、三角函数等操作。由于构造方法是私有的,无法实例化对象,方法通过Math.<方法名>调用。常用场景包括数值计算、随机数生成和几何运算等。
13.7.3 Math 类常见常量和方法¶
常用常量¶
Math.PI:圆周率,约等于 \(π≈3.141592653589793\)。Math.E:自然对数的底数,约等于 \(e≈2.718281828459045\)。
常见方法¶
绝对值与比较¶
Math.abs(double a):返回参数的绝对值,支持int、long、float、double。Math.max(double a, double b):返回两数中的较大值,支持多种类型。Math.min(double a, double b):返回两数中的较小值,支持多种类型。
取整操作¶
Math.ceil(double a):向上取整,返回大于或等于a的最小整数。Math.floor(double a):向下取整,返回小于或等于a的最大整数。Math.round(double a):四舍五入,返回最接近的long(float返回int)。Math.rint(double a):返回最接近的整数(若两个整数等距,返回偶数)。
指数与对数¶
Math.pow(double a, double b):计算 \(a^b\),返回 \(a\) 的 \(b\) 次幂。Math.exp(double a):计算 \(e^a\),返回自然底数的指数。Math.log(double a):计算以 \(e\) 为底的对数 \(ln(a)\)。Math.log10(double a):计算以 10 为底的对数 \(log_{10} (a)\) 。Math.sqrt(double a):计算平方根 \(\sqrt a\) 。Math.cbrt(double a):计算立方根 \(\sqrt[3] a\) 。
三角函数¶
参数以弧度为单位(可用 Math.toRadians 转换角度)。
Math.sin(double a):计算正弦 \(sin(a)\)。Math.cos(double a):计算余弦 \(cos(a)\)。Math.tan(double a):计算正切 \(tan(a)\)。Math.asin(double a):计算反正弦 \(arcsin(a)\),范围 \([ \frac {−π}{2},\frac{π}{2}]\)。Math.acos(double a):计算反余弦 \(arccos(a)\),范围 \([0,π]\)。Math.atan(double a):计算反正切 \(arctan(a)\),范围 \([ \frac {−π}{2},\frac{π}{2}]\)。
随机数¶
Math.random():生成 \([0.0,1.0)\) 之间的随机double值。
其他方法¶
Math.toRadians(double angdeg):将角度转换为弧度。Math.toDegrees(double angrad):将弧度转换为角度。Math.hypot(double x, double y):计算 \(\sqrt{{x^2} +{y^2}}\) ,避免溢出。Math.IEEEremainder(double f1, double f2):计算 IEEE 余数 \(f1 - f2 \times n\),其中 \(n\) 是最接近 \(\frac{f1}{f2}\) 的整数。
注意事项¶
- 精度问题:浮点运算可能存在精度误差(如
Math.sin(Math.PI/2)可能接近但不精确等于 1.0)。 - 参数单位:三角函数以弧度为单位,需用
Math.toRadians转换角度。 - 性能:
Math方法为静态方法,调用方便,但高精度计算建议使用StrictMath类。 - 随机数:对于更复杂的随机数需求,推荐使用
java.util.Random或ThreadLocalRandom。
13.8 Arrays 类¶
java.util.Arrays是一个工具类,提供了大量静态方法用于操作数组,如排序、查找、复制、填充和转换等。无需实例化,直接通过类名调用。其方法适用于基本数据类型和引用类型的数组,广泛应用于数据处理、算法实现等场景。
13.8.1 Arrays 类常见方法应用案例¶
1. toString 和 deepToString¶
- 功能:将数组转换为字符串表示。
toString适用于一维数组,deepToString适用于多维数组。 - 应用场景:调试或输出数组内容。
- 案例:打印一维和多维数组。
输出:便于检查数组内容,避免直接打印数组对象地址(如 [I@123456)
2. sort¶
- 功能:对数组排序,默认升序,支持全部或部分排序,可通过
Comparator自定义排序规则。[[Comparator]] - 应用场景:数据排序、排行榜、预处理二分查找。
- 案例:对学生成绩升序排序,部分降序排序。
int[] scores = {85, 70, 90, 65, 95};
Arrays.sort(scores); // 升序
System.out.println(Arrays.toString(scores)); // [65, 70, 85, 90, 95]
Integer[] scores2 = {85, 70, 90, 65, 95};
Arrays.sort(scores2, 0, 3, (a, b) -> b - a); // 前 3 个降序
System.out.println(Arrays.toString(scores2)); // [90, 85, 70, 65, 95]
输出:排序后的成绩便于统计最高/最低分。
3. binarySearch¶
- 功能:在有序数组中进行二分查找,返回目标元素的索引,未找到返回负数(
-(插入点+1))。 - 应用场景:快速查找元素,如查找学生 ID。
- 案例:查找有序数组中的元素。
int[] sorted = {1, 3, 5, 7, 9};
int index = Arrays.binarySearch(sorted, 5); // 找到 5
System.out.println(index); // 2
index = Arrays.binarySearch(sorted, 4); // 未找到 4
System.out.println(index); // -3(插入点为 2)
注意:数组必须先排序,否则结果不可预测。
4. copyOf 和 copyOfRange¶
- 功能:
copyOf复制整个数组到指定长度,copyOfRange复制指定范围。 - 应用场景:备份数组、截取子数组。
- 案例:复制成绩数组并截取部分数据。
int[] scores = {85, 70, 90, 65, 95};
int[] copy = Arrays.copyOf(scores, 3); // 前 3 个
int[] range = Arrays.copyOfRange(scores, 1, 4); // 索引 1 到 3
System.out.println(Arrays.toString(copy)); // [85, 70, 90]
System.out.println(Arrays.toString(range)); // [70, 90, 65]
输出:复制结果可用于数据分析或临时存储。
5. fill¶
- 功能:用指定值填充整个数组或指定范围。
- 应用场景:初始化数组、设置默认值。
- 案例:初始化考试分数为 0。
int[] scores = new int[5];
Arrays.fill(scores, 0); // 全填充
System.out.println(Arrays.toString(scores)); // [0, 0, 0, 0, 0]
Arrays.fill(scores, 1, 3, 100); // 部分填充
System.out.println(Arrays.toString(scores)); // [0, 100, 100, 0, 0]
6. equals 和 deepEquals¶
- 功能:比较两个数组是否相等。
equals用于一维数组,deepEquals用于多维数组。 - 应用场景:验证数组内容一致性。
- 案例:比较两组学生成绩。
int[] scores1 = {85, 70, 90};
int[] scores2 = {85, 70, 90};
int[][] matrix1 = {{1, 2}, {3, 4}};
int[][] matrix2 = {{1, 2}, {3, 4}};
System.out.println(Arrays.equals(scores1, scores2)); // true
System.out.println(Arrays.deepEquals(matrix1, matrix2)); // true
7. asList¶
- 功能:将数组转换为固定大小的
List。 - 应用场景:将数组与集合操作结合使用。
- 案例:将字符串数组转为 List 处理。
String[] names = {"Alice", "Bob", "Charlie"};
List<String> list = Arrays.asList(names);
System.out.println(list); // [Alice, Bob, Charlie]
// list.add("Dave"); // 抛出 UnsupportedOperationException
注意:返回的 List 是只读的,不支持 add 或 remove 操作。
注意事项¶
- 类型一致性:
asList要求数组元素类型一致(如Integer[]而非int[]),否则可能导致意外行为。 - 排序前提:
binarySearch要求数组已排序,否则结果不可靠。 - 只读 List:
asList返回的 List 不支持增删操作,需转为java.util.ArrayList才能修改。 - 性能考虑:
sort使用双轴快速排序,适合大部分场景;parallelSort适用于大数组并行排序。
13.8.2 手动实现 Comparator 的冒泡¶
import java.util.Comparator;
class Main{
public static void main(String[] args) {
int[] arr = {1, 5, 3, 9, 7, 2};
bubble(arr);
System.out.println("排序后:");
for (int j : arr) {
System.out.print(j + " ");
}
System.out.println("从大到小");
enhanceBubble(arr, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return (int) o2 - (int) o1;
}
});
System.out.println("排序后:");
for (int j : arr) {
System.out.print(j + " ");
}
}
public static void bubble(int[] arr){
int temp = 0;
for (int i = 0; i < arr.length -1 ; i++) {
for (int j = 0; j < arr.length - 1 - i; j++){
// 从小到大
if (arr[j] > arr[j+1]){
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
public static void enhanceBubble(int[] arr, Comparator c){
int temp = 0;
for (int i = 0; i < arr.length -1 ; i++){
for (int j = 0; j < arr.length - 1 - i; j++){
if (c.compare(arr[j], arr[j+1]) > 0){
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
}
[[Comparator#升序降序|调整升序和降序]]
13.9 System 类¶
-
exit: 退出当前程序
-
arraycopy : 复制数组元素,比较适合底层调用,一般使用
Arrays.copyOf完成复制数组.int[] src={1,2,3};int[] dest = new int[3];System.arraycopy(src, 0, dest, 0, 3);- 方法签名
public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
- 参数说明
src:源数组。srcPos:源数组的起始位置(从 0 开始)。dest:目标数组。destPos:目标数组的起始位置。length:要复制的元素个数。
- 功能
- 将源数组
src从srcPos开始的length个元素,复制到目标数组dest的destPos位置开始处。 - 支持任意类型数组(基本类型或引用类型)。
- 将源数组
- 方法签名
-
currentTimeMillens: 返回当前时间距离 \(1970-1-1\) 的毫秒数
-
gc : 运行垃圾回收机制
System.gc().
13.10 BigInteger 和 BigDecimal 类¶
Biginteger 适合保存比较大的整型 BigDecimal 适合保存精度更高的浮点型 (小数)
13.10.2 BigInteger 和 BigDecimal 常见方法¶
BigInteger 常见方法¶
BigInteger 用于表示任意精度的整数,常用于大数运算。
-
构造方法
BigInteger(String val):从字符串创建大整数,如new BigInteger("123456789")。BigInteger(byte[] val):从字节数组创建大整数。valueOf(long val):从long值创建,如BigInteger.valueOf(123)。
-
基本运算
add(BigInteger val):加法,返回this + val。subtract(BigInteger val):减法,返回this - val。multiply(BigInteger val):乘法,返回this * val。divide(BigInteger val):除法(整除),返回this / val。remainder(BigInteger val):取余,返回this % val。pow(int exponent):幂运算,返回this^exponent。
-
比较
compareTo(BigInteger val):比较大小,<0表示this < val,=0表示相等,>0表示this > val。equals(Object x):判断是否相等。min(BigInteger val)/max(BigInteger val):返回较小/较大值。
-
其他实用方法
abs():返回绝对值。negate():返回相反数。gcd(BigInteger val):返回最大公约数。mod(BigInteger m):模运算,返回this mod m(常用于加密算法)。toString():转换为字符串表示。intValue()/longValue():转换为int或long(可能丢失精度)。
示例:
BigInteger a = new BigInteger("123");
BigInteger b = new BigInteger("456");
System.out.println(a.add(b)); // 579
System.out.println(a.multiply(b)); // 56088
System.out.println(a.compareTo(b)); // -1 (123 < 456)
BigDecimal 常见方法¶
BigDecimal 用于高精度浮点运算,适合金融计算等需要精确小数的场景。
-
构造方法
BigDecimal(String val):从字符串创建,如new BigDecimal("123.456")。BigDecimal(double val):从double创建(不推荐,可能有精度问题)。valueOf(double val):从double创建,推荐使用。
-
基本运算
add(BigDecimal augend):加法,返回this + augend。subtract(BigDecimal subtrahend):减法,返回this - subtrahend。multiply(BigDecimal multiplicand):乘法,返回this * multiplicand。divide(BigDecimal divisor, int scale, RoundingMode roundingMode):除法,指定精度和舍入模式(如RoundingMode.HALF_UP)。
-
比较
compareTo(BigDecimal val):比较大小,<0表示this < val,=0表示相等,>0表示this > val。equals(Object x):判断值和精度是否完全相等。min(BigDecimal val)/max(BigDecimal val):返回较小/较大值。
-
其他实用方法
setScale(int newScale, RoundingMode roundingMode):设置精度和舍入模式。abs():返回绝对值。negate():返回相反数。round(MathContext mc):根据指定上下文舍入。toString():转换为字符串。doubleValue()/floatValue():转换为double或float(可能丢失精度)。
示例:
BigDecimal a = new BigDecimal("123.456");
BigDecimal b = new BigDecimal("7.89");
System.out.println(a.add(b)); // 131.346
System.out.println(a.divide(b, 2, RoundingMode.HALF_UP)); // 15.65
System.out.println(a.setScale(1, RoundingMode.HALF_UP)); // 123.5
注意事项¶
-
BigInteger
- 运算结果仍为
BigInteger,不可变(immutable)。 - 除法和取余需确保除数非零,否则抛
ArithmeticException。 - 适合加密、数学计算等场景。
-
BigDecimal
-
除法必须指定精度和舍入模式,否则可能抛
ArithmeticException(如无法整除)。BigDecimal.ROUND_CEILING保留分子精度BigDecimal.divide (bigdecimal, BigDecimal. ROUND_CEILING)
- 避免用
double构造(如new BigDecimal(0.1)),因double本身不精确,推荐用字符串。或者指定精度 - 适合金融、货币计算,确保精度。
- 性能:两者运算比基本类型慢,适合精度要求高的场景。
- 运算结果仍为
13.11日期类¶
13.11.1 第一代: java.util.Date 和 java.util.Calendar¶
时间:JDK 1.0(1996)引入 Date,JDK 1.1(1997)引入 Calendar。
1. java.util.Date¶
- 概述:表示日期和时间的类,存储毫秒级时间戳(从 1970-01-01 00:00:00 UTC 起)。
- 主要方法:
Date():创建当前时间对象。Date(long time):根据毫秒时间戳创建。getTime():返回毫秒时间戳。setTime(long time):设置时间戳。before(Date when)/after(Date when):比较时间先后。
- 缺点:
- 不支持国际化(时区处理差)。
- 方法混乱(如
getYear()返回年份减 1900)。 - 非线程安全。
- 部分方法(如日期操作)在 JDK 1.1 后废弃,推荐用
Calendar。
2. java.util.Calendar¶
- 概述:抽象类,提供更丰富的日期操作功能,支持时区和字段操作(如年、月、日)。
- 常用实现:
GregorianCalendar(公历实现)。 - 主要方法:
get(int field):获取字段值(如Calendar.YEAR、Calendar.MONTH)。set(int field, int value):设置字段值。add(int field, int amount):增加/减少字段值(如加 1 月)。getTime():转换为Date对象。setTime(Date date):从Date设置时间。
- 缺点:
- API 复杂,易出错(如
MONTH从 0 开始计数)。 - 非线程安全。
- 可变对象,修改可能引发副作用。
- 时区和国际化支持有限。
- 不能处理闰秒
- API 复杂,易出错(如
应用场景:早期 Java 程序,简单日期处理。
示例:
Date date = new Date();
System.out.println(date); // 当前时间
Calendar cal = Calendar.getInstance();
cal.set(2025, Calendar.JULY, 27); // 2025-07-27
System.out.println(cal.getTime()); // Sun Jul 27 00:00:00 CST 2025
13.11.2 第二代:java.text.SimpleDateFormat¶
时间:JDK 1.1(1997)引入。
- 概述:用于格式化和解析日期字符串,常与
Date配合使用,属于java.text包。 - 主要方法:
SimpleDateFormat(String pattern):定义格式,如"yyyy-MM-dd HH:mm:ss"。format(Date date):将Date格式化为字符串。parse(String text):将字符串解析为Date。
- 特点:
- 支持自定义格式(如
"yyyy-MM-dd")。 - 便于日期字符串转换。
- 支持自定义格式(如
- 缺点:
- 非线程安全(多线程需同步或用
ThreadLocal)。 - 依赖
Date,继承其缺点。 - 解析复杂日期字符串时易出错。
- 非线程安全(多线程需同步或用
应用场景:日期格式化、字符串解析。
示例:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date date = sdf.parse("2025-07-27");
System.out.println(sdf.format(date)); // 2025-07-27
13.11.3 第三代:java.time 包(JSR-310)¶
时间:JDK 8(2014)引入。
- 概述:基于 JSR-310 规范的现代日期时间 API,位于
java.time包,设计优雅,解决前两代缺陷。 -
核心类:
LocalDate:仅日期(如 2025-07-27)。LocalTime:仅时间(如 15:01:19)。LocalDateTime:日期+时间(如 2025-07-27T15:01:19)。ZonedDateTime:带时区的日期时间。Instant:时间戳(类似Date的毫秒表示)。可以转换成 Date 类Duration/Period:时间间隔(秒/天级别)。
-
主要方法(以
LocalDate和LocalDateTime为例):now():获取当前日期/时间。of(int year, int month, int day):创建指定日期。plusDays(long days)/minusMonths(long months):加减时间单位。getYear()/getMonth():获取字段值(直观,无偏移)。atTime(int hour, int minute):结合时间(如LocalDate转为LocalDateTime)。format(DateTimeFormatter formatter):格式化。parse(CharSequence text, DateTimeFormatter formatter):解析字符串。
-
特点:
- 不可变:线程安全,每次操作返回新对象。
- 清晰 API:方法名直观,易用。
- 时区支持:
ZonedDateTime和ZoneId处理国际化。 - 高精度:支持纳秒级操作。
- 格式化:
DateTimeFormatter替代SimpleDateFormat,线程安全。
-
优点:
- 解决
Date和Calendar的设计缺陷。 - 支持现代日期时间需求(如 ISO 8601 标准)。
- 代码简洁,易于维护。
- 解决
应用场景:现代 Java 应用,推荐使用,尤其涉及复杂日期、时区、国际化场景。
示例:
LocalDate date = LocalDate.of(2025, 7, 27);
System.out.println(date.plusDays(1)); // 2025-07-28
LocalDateTime dateTime = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(dateTime.format(formatter)); // 如 2025-07-27 15:01:19
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
System.out.println(zdt); // 如 2025-07-27T15:01:19+08:00[Asia/Shanghai]