Java 没有脚本语言那样的全局内置函数——对应物是 java.lang 与 java.util 的核心类库。本篇按「每个类一个词条」覆盖最常用 API,每条给签名与坑。
1. Object – 万物基类与 equals/hashCode 契约
描述
所有类的根。四个关键方法:equals(内容相等)、hashCode(哈希)、toString(文本表示)、getClass(运行时类型)。契约:equals 相等则 hashCode 必须相等,否则 HashMap/HashSet 会静默失效。
语法和示例
class Money {
private final long cents;
Money(long c) { cents = c; }
@Override public boolean equals(Object o) {
if (this == o) return true; // 快路径
if (!(o instanceof Money m)) return false; // 16+ 模式匹配
return cents == m.cents;
}
@Override public int hashCode() {
return Long.hashCode(cents); // 必须与 equals 一致
}
@Override public String toString() {
return "Money(" + cents + ")";
}
}
new Money(100).equals(new Money(100)); // true
new Money(100).hashCode() == new Money(100).hashCode(); // true注意事项
- 只重写 equals 不重写 hashCode:HashSet 里同一值会存两份,HashMap get 返回 null
- equals 必须满足自反/对称/传递/一致/非空五条契约
- hashCode 用 Objects.hash(a, b) 或 Long/Integer.hashCode(x),别手写乘法易溢出
- toString 默认输出「类名@十六进制哈希」,日志里无法读——生产必重写
- clone() 是浅拷贝且需实现 Cloneable,优先用拷贝构造器或 record
2. String – 不可变字符串
描述
不可变字符序列,任何「修改」都返回新对象。字面量进常量池(同内容复用同一对象)。方法极多,这里按用途分组。
语法和示例
String s = "Hello";
// 判等与查找
s.equals("Hello"); s.equalsIgnoreCase("HELLO");
s.isEmpty(); s.isBlank(); // isBlank 认全空白(11+)
s.indexOf("l"); s.lastIndexOf("l");
s.contains("ell"); s.startsWith("He"); s.endsWith("lo");
// 截取与转换
s.substring(1); s.substring(1, 3); // 含头不含尾
s.replace("l", "L"); s.replaceAll("\\d", "#");
s.toUpperCase(); s.trim(); s.strip(); // strip 认 Unicode 空白(11+)
s.repeat(3); s.lines(); // 11+
// 拆分与连接
"a,b,c".split(","); String.join("-", "a", "b");
// 编码
s.getBytes(StandardCharsets.UTF_8);
new String(bytes, StandardCharsets.UTF_8);
// 格式化
String.format("%s=%d", "k", 1);注意事项
- 判等永远用 equals 不用 ==(== 比引用,字面量碰巧相等,new String 就不等了)
- substring 在 Java 7 后是真正的拷贝(不复用底层数组,无内存泄漏问题)
- 循环内用 + 拼接会多次创建对象——把 StringBuilder 提到循环外
- split 的参数是正则:split(“.”) 会按任意字符切,切点号要 split(“\\.”)
- String 的 length() 是 UTF-16 代码单元数,emoji 算 2;要字符数用 codePointCount
3. StringBuilder / StringBuffer – 可变字符串
描述
StringBuilder 非线程安全但快(单线程首选);StringBuffer 加 synchronized(多线程共享时才用)。二者 API 一致。
语法和示例
var sb = new StringBuilder(64); // 预估容量避免扩容
sb.append("a").append(1).append(',');
sb.insert(0, "前").deleteCharAt(0);
sb.replace(0, 1, "X");
sb.reverse();
sb.length(); sb.setLength(0); // 复用清空(比 new 省)
sb.toString();
// 循环拼接的正确姿势
var out = new StringBuilder();
for (var w : words) out.append(w).append('\n');
// String.join 更简洁(无中间状态时优先)
String.join(", ", list);注意事项
- 单线程场景永远用 StringBuilder,StringBuffer 的锁开销白给
- 初始容量给足(预估最终长度)能避免多次数组扩容拷贝
- setLength(0) 复用实例,但注意多线程共享时仍不安全
- append(char) 比 append(String) 快,别为单个字符建字符串
- 链式 append 返回 this,可连续调用,但别在 lambda 里共享 builder
4. Integer/Long/Double – 包装类
描述
基本类型的对象包装。关键点:自动装箱/拆箱、缓存范围、parseXxx 与 valueOf 的区别。用于泛型、集合、可空场景。
语法和示例
Integer.parseInt("42"); // 返回 int
Integer.parseInt("ff", 16); // 255
Integer.valueOf("42"); // 返回 Integer(走缓存)
Integer i = 42; // 自动装箱
int n = i; // 自动拆箱
Integer.MAX_VALUE; Integer.MIN_VALUE;
Integer.compare(a, b); // -1/0/1(避免 a-b 溢出)
Integer.toBinaryString(255); Long.toHexString(255L);
Double.isNaN(x); Double.isInfinite(x);
Integer.toString(42); String.valueOf(42);
// 缓存陷阱
Integer a = 127, b = 127; a == b; // true(缓存 -128~127)
Integer c = 128, d = 128; c == d; // false!
Boolean.TRUE; Character.valueOf('a');注意事项
- == 比较包装类只在缓存范围(-128~127)内碰巧为 true——永远用 equals
- 为 null 的包装类自动拆箱会抛 NPE(三元表达式混用 Integer/int 时尤其隐蔽)
- 集合里存基本类型只能装箱,大数量(如百万 Integer)内存是 int[] 的 4-6 倍
- valueOf 走缓存,new Integer()(已废弃)不缓存——用 valueOf 或自动装箱
- parseInt 遇溢出抛 NumberFormatException,超 long 范围用 BigInteger
5. Math – 数学函数
描述
全静态工具类。注意负数取整与除法的语义差异:/ 向零取整,floorDiv 向下取整。溢出用 addExact 系列检测。
语法和示例
Math.abs(-3); Math.abs(Integer.MIN_VALUE); // 后者仍是负数(溢出)
Math.max(1, 2); Math.min(3L, 4L);
Math.floor(1.8); // 1.0 向下
Math.ceil(1.2); // 2.0 向上
Math.round(1.5); // 2 四舍五入(.5 向正无穷)
Math.round(-1.5); // -1 !不是 -2
Math.pow(2, 10); Math.sqrt(16); Math.cbrt(27);
Math.hypot(3, 4); // 5.0 斜边(防溢出)
Math.floorDiv(-7, 2); // -4 向下取整除
Math.floorMod(-7, 2); // 1 符号跟除数
Math.addExact(Integer.MAX_VALUE, 1); // 抛 ArithmeticException
Math.multiplyExact(a, b);
Math.toRadians(180);注意事项
- Math.round 用「四舍五入到正无穷」,负数 .5 会往大的取(-1.5 → -1)
- Math.abs(Integer.MIN_VALUE) 返回仍是负数——对绝对值负的 int 无解,先转 long
- 金额/精确计算不用 Math,用 BigDecimal
- addExact/multiplyExact 比事后检查更可靠,适合外部输入参与的运算
- Math.random() 返回 [0,1) double,线程共享 Random 有竞争——并发用 ThreadLocalRandom
6. Arrays – 数组工具
描述
排序、查找、填充、拷贝、比较、转字符串。binarySearch 要求数组已排序,否则结果未定义。
语法和示例
int[] a = {3, 1, 2};
Arrays.sort(a); // [1,2,3]
Arrays.sort(a, 1, 3); // 只排区间
Arrays.toString(a);
Arrays.binarySearch(a, 2); // 需先排序
Arrays.copyOf(a, 5); // 扩容(补 0)
Arrays.copyOfRange(a, 0, 2);
Arrays.fill(a, 0);
Arrays.equals(a, b); Arrays.hashCode(a);
int[][] g = new int[3][4]; // 二维数组
Arrays.deepToString(g); // 多维用 deep
Arrays.stream(a).sum();
// 对象数组按字段排序
Arrays.sort(users, Comparator.comparing(User::age));注意事项
- binarySearch 未排序时返回结果不可信(可能负值也可能误命中)
- Arrays.asList 返回定长视图,add/remove 抛 UnsupportedOperationException;要可变用 new ArrayList(Arrays.asList(…))
- 基本类型数组用 Arrays.sort 是双轴快排;对象数组是归并(稳定)
- Arrays.asList(int[]) 会得到 List 而不是 List(基本类型不装箱)
- copyOf 长度变大时新元素是默认值(0/false/null)
7. Collections – 集合工具
描述
静态工具类:排序、反转、打乱、不可变视图、查找极值、频率统计。
语法和示例
List<String> l = new ArrayList<>(List.of("b", "a"));
Collections.sort(l);
Collections.reverse(l);
Collections.shuffle(l);
Collections.swap(l, 0, 1);
Collections.max(l); Collections.min(l);
Collections.frequency(l, "a");
Collections.binarySearch(sortedList, "x");
Collections.unmodifiableList(l); // 只读视图(原表仍可变)
Collections.synchronizedList(l); // 线程安全包装(粗粒度锁)
Collections.emptyList(); Collections.singletonList("x");
Collections.nCopies(3, "x");注意事项
- unmodifiable 是视图不是拷贝——原集合被改时只读视图内容也跟着变
- synchronizedList 只保证单方法原子,复合操作用 synchronized(list) 包
- Collections.sort 已可被 list.sort() 替代(Java 8+)
- emptyList/singletonList 是不可变且共享实例,别往里 add
- 9+ 优先用 List.of/Map.of(不可变工厂),比 Collections 包装更轻
8. ArrayList – 动态数组
描述
随机访问 O(1),尾部追加均摊 O(1),中间插删 O(n)。默认容量 10,扩容约 1.5 倍。是 List 的事实默认实现。
语法和示例
var list = new ArrayList<String>(100); // 预估容量
list.add("a"); // 尾部 O(1)
list.add(0, "head"); // 中间 O(n)
list.get(0); list.set(0, "A");
list.remove(0); // 按下标
list.remove("a"); // 按值(首次匹配)
list.size(); list.isEmpty(); list.clear();
list.contains("a"); // O(n)
for (String s : list) {}
list.removeIf(s -> s.isEmpty());
list.subList(0, 2); // 视图!
List<String> copy = new ArrayList<>(list);注意事项
- remove(int) 与 remove(Object) 是两个重载:list.remove(1) 删下标 1,删值 “1” 要 remove(“1”)
- subList 返回视图,原 list 结构变动后视图失效(ConcurrentModificationException)
- for 循环里 remove 会抛异常——用 iterator.remove 或 removeIf
- 预估容量能避免多次扩容拷贝,批量添加时收益明显
- ArrayList 不是线程安全的;并发用 CopyOnWriteArrayList(读多写少)或加锁
9. HashMap – 哈希映射
描述
键值对,get/put 均摊 O(1)。允许一个 null 键与多个 null 值。不保证顺序(遍历顺序不稳定)。键必须正确实现 hashCode/equals。
语法和示例
var m = new HashMap<String, Integer>();
m.put("a", 1);
m.get("a"); // 1
m.getOrDefault("b", 0);
m.putIfAbsent("c", 3);
m.merge("a", 1, Integer::sum); // 计数惯用法
m.computeIfAbsent("k", this::load); // 缓存惯用法
m.compute("x", (k, v) -> v == null ? 1 : v + 1);
m.containsKey("a"); m.containsValue(1);
m.remove("a");
for (var e : m.entrySet()) { e.getKey(); e.getValue(); }
m.keySet(); m.values();
new HashMap<>(16, 0.75f); // 容量与负载因子
// 保序替代
var ordered = new LinkedHashMap<String, Integer>();
var sorted = new TreeMap<String, Integer>();注意事项
- 键是可变对象(如 ArrayList)且改内容后,hashCode 变化会导致 get 找不到
- 遍历时 remove 抛 ConcurrentModificationException——用 entrySet().iterator().remove()
- 并发场景用 ConcurrentHashMap;Collections.synchronizedMap 锁太粗
- 负载因子默认 0.75,容量应为预计元素数的 1.5 倍左右(避免频繁 rehash)
- TreeMap 要求键可比较(Comparable 或传 Comparator),不允许 null 键
10. List.of / Map.of / Set.of – 不可变工厂(9+)
描述
一行构造不可变集合,不接受 null,任何修改抛 UnsupportedOperationException。适合常量与配置,比 Collections 包装更轻量。
语法和示例
List<String> xs = List.of("a", "b");
Map<String, Integer> m = Map.of("go", 1, "php", 2);
Set<Integer> s = Set.of(1, 2, 3);
Map<String, Integer> m10 = Map.ofEntries(
Map.entry("a", 1), Map.entry("b", 2));
// 拷贝可变集合为不可变
List.copyOf(mutableList);
Map.copyOf(mutableMap);
Set.copyOf(mutableSet);
// 取第一个元素
xs.getFirst(); xs.getLast(); // 21+ SequencedCollection注意事项
- List.of(null) 直接抛 NPE——不可变集合禁止 null 元素
- Map.of 最多 10 对,超出用 Map.ofEntries
- 不可变是深还是浅?只保证集合本身结构不可变,元素对象仍可改
- List.copyOf 若入参已是不可变则直接返回原引用(不拷贝)
- 顺序:List.of 保参数顺序;Set.of 不保证顺序,Map.of 不保证
11. Optional – 可能缺席的容器
描述
表达「有值或无值」的返回值容器。设计意图是替代返回 null,不是替代所有判空。
语法和示例
Optional<User> u = repo.findById(id);
u.isPresent(); u.isEmpty();
u.get(); // 不推荐裸用
u.orElse(new User());
u.orElseGet(() -> createDefault()); // 惰性
u.orElseThrow(() -> new NotFoundException(id));
u.map(User::name); // 有值才映射
u.filter(User::isActive);
u.ifPresent(this::send); // 有值才执行
u.ifPresentOrElse(this::send, this::skip);
repo.find(id).or(() -> repo.findBackup(id)); // 备用来源
Optional.of("x"); // 不能为 null(否则 NPE)
Optional.ofNullable(maybeNull);注意事项
- 不要用作字段/方法参数/集合元素(只适合返回值)
- get() 与 isPresent() 组合等于老式判空,没有发挥 Optional 价值——用 map/orElseThrow
- Optional 是值对象,不能序列化(别放 DTO 字段)
- 集合不应返回 Optional,返回空集合更清晰
- Optional 的链式调用本身有对象开销,高频路径慎用
12. Stream – 声明式管道
描述
集合的函数式操作链。中间操作惰性(不触发计算),终端操作才执行一次。流只能消费一次。
语法和示例
List<String> top = orders.stream()
.filter(o -> o.amount() > 100)
.sorted(Comparator.comparing(Order::amount).reversed())
.limit(5)
.map(Order::customer)
.toList(); // 16+(不可变)
// 分组与统计
Map<String, List<Order>> byCust = orders.stream()
.collect(Collectors.groupingBy(Order::customer));
Map<String, Long> counts = orders.stream()
.collect(Collectors.groupingBy(Order::customer, Collectors.counting()));
String joined = names.stream().collect(Collectors.joining(", "));
int total = orders.stream().mapToInt(Order::amount).sum();
IntSummaryStatistics st = orders.stream()
.mapToInt(Order::amount).summaryStatistics();
// 扁平化
Stream.of(List.of(1,2), List.of(3)).flatMap(List::stream).toList();
// 创建流
Stream.of("a","b"); Arrays.stream(arr); IntStream.range(0, 10);
Files.lines(path); Stream.iterate(0, x -> x + 1).limit(10);注意事项
- 流只能消费一次,终端操作后再用会抛 IllegalStateException
- 中间操作惰性——没有终端操作时什么都不会发生(调试常见困惑)
- parallelStream 只适合大数据量 CPU 密集;小数据或 IO 会变慢
- 在流里修改外部可变集合是反模式(并发流更危险)
- mapToInt 等原始流避免装箱,大数据量性能差异显著
13. Comparator – 比较器
描述
定义排序规则。comparing 链式组合、thenComparing 处理多级排序、reversed 反转、nullsFirst/Last 处理空值。
语法和示例
Comparator<User> byName = Comparator.comparing(User::name);
users.sort(byName);
// 多级
users.sort(Comparator.comparing(User::dept)
.thenComparing(User::age, Comparator.reverseOrder())
.thenComparing(User::name));
// 反转
Comparator<User> desc = byName.reversed();
// 空值安全
Comparator.comparing(User::name,
Comparator.nullsLast(Comparator.naturalOrder()));
// 原始类型避免装箱
Comparator.comparingInt(String::length);
// 自定义
Comparator<String> byLen = (a, b) -> Integer.compare(a.length(), b.length());注意事项
- (a, b) -> a – b 有整数溢出风险,用 Integer.compare(a, b)
- reversed() 作用于整条链时需要括号注意优先级:comparing(…).reversed() 只反最后一个键
- thenComparing 的第二个键用 reverseOrder 才是独立反转,别整体 reversed
- Collections.sort 与 list.sort 都稳定排序(相等元素保原序)
- 对 null 排序必须显式 nullsFirst/Last,否则 NPE
14. java.time – 日期时间 API
描述
不可变、线程安全的时间 API。四大类型:LocalDate(无时间)、LocalTime、LocalDateTime(无时区)、ZonedDateTime/Instant(有时区/绝对时刻)。
语法和示例
LocalDate d = LocalDate.of(2026, 10, 29);
LocalDate.parse("2026-10-29"); // ISO 默认
LocalDateTime dt = LocalDateTime.of(d, LocalTime.of(15, 30));
Instant now = Instant.now(); // UTC 绝对时刻
ZonedDateTime z = dt.atZone(ZoneId.of("Asia/Shanghai"));
// 运算(都返回新对象)
d.plusDays(7).minusMonths(1);
dt.plus(Duration.ofMinutes(30));
Duration.between(t1, t2).toMinutes(); // 时刻差
Period.between(d1, d2).getYears(); // 日期差
// 格式化
dt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
DateTimeFormatter.ISO_LOCAL_DATE;
// 比较
d.isBefore(e); d.isAfter(e); d.isEqual(e);
// 转旧 API
java.util.Date legacy = java.util.Date.from(now);注意事项
- LocalDateTime 不含时区——存数据库/跨时区比较必须用 Instant 或 ZonedDateTime
- DateTimeFormatter 线程安全(老的 SimpleDateFormat 不是),可作静态常量复用
- 月份从 1 开始(不是老的 Calendar 从 0),别写错
- Duration 是时间量(时分秒),Period 是日期量(年月日),别混用
- 系统默认时区随环境变——跨时区业务显式指定 ZoneId
15. BigDecimal – 精确小数
描述
任意精度十进制,金额/汇率/税率必须用它。不可变,运算返回新对象。构造器必须用字符串。
语法和示例
var price = new BigDecimal("19.99"); // 必须字符串构造
var tax = new BigDecimal("0.13");
var total = price.multiply(BigDecimal.ONE.add(tax))
.setScale(2, RoundingMode.HALF_UP);
price.add(new BigDecimal("0.01"));
price.subtract(qty); price.divide(new BigDecimal("3"), 2, RoundingMode.HALF_UP);
price.compareTo(other) == 0; // 比大小
price.equals(new BigDecimal("19.990")); // false!equals 连 scale 比
price.stripTrailingZeros();
price.toPlainString(); // 不用科学计数法
price.setScale(2, RoundingMode.HALF_UP);注意事项
- new BigDecimal(0.1) 会得到 0.1000000000000000055511…,必须 new BigDecimal(“0.1”)
- equals 比较时连 scale 一起比(19.9 与 19.90 不等),比大小用 compareTo
- divide 不指定 scale 且除不尽时抛 ArithmeticException
- BigDecimal 不可变,每次运算产生新对象——大循环里注意开销
- toString 可能输出科学计数法,展示/存储用 toPlainString
16. Objects – 空安全工具
描述
静态工具:requireNonNull 快速校验、equals/hash 空安全、requireNonNullElse 提供默认值。
语法和示例
Objects.requireNonNull(user, "user 必填"); // null 抛 NPE 带消息
Objects.requireNonNullElse(input, "默认值");
Objects.requireNonNullElseGet(input, () -> compute());
Objects.equals(a, b); // 两个 null 也算相等
Objects.hash(a, b, c); // 生成 hashCode
Objects.hashCode(x);
Objects.isNull(x); Objects.nonNull(x); // 可作方法引用
// 方法引用场景
list.stream().filter(Objects::nonNull);注意事项
- requireNonNull 抛 NPE 而非 IllegalArgumentException——想用后者需自己抛
- Objects.equals 只做 equals 调用,不做类型转换
- Objects.hash 每次创建数组有开销,高频路径手写更划算
- isNull/nonNull 主要为方法引用存在,普通判空用 x == null 更直观
17. Random / ThreadLocalRandom / SecureRandom
描述
三个随机源:Random(可复现,多线程共享有竞争)、ThreadLocalRandom(并发首选)、SecureRandom(密码学安全,慢)。
语法和示例
var r = new Random(42); // 种子可复现
r.nextInt(); r.nextInt(100); // [0,100)
r.nextLong(); r.nextDouble(); r.nextBoolean();
ThreadLocalRandom.current().nextInt(1, 101); // 并发场景
SecureRandom sr = new SecureRandom(); // 令牌/盐
sr.nextInt(1000);
// 唯一 ID
UUID.randomUUID().toString();注意事项
- Random 实例被多线程共享时性能下降且结果有竞争——并发用 ThreadLocalRandom
- 密码、令牌、盐必须用 SecureRandom,普通 Random 可预测
- Math.random() 内部是共享 Random,别在并发热点用
- nextInt(bound) 不含 bound,要含用 nextInt(a, b)
- 固定种子的 Random 结果可复现(测试友好),但绝不能用于安全场景
18. Record – 不可变数据载体(16+)
描述
一行声明不可变数据类,自动生成构造器、equals/hashCode/toString、访问器。可带紧凑构造器校验、静态工厂、额外方法。
语法和示例
record Point(int x, int y) {
Point { // 紧凑构造器
if (x < 0) throw new IllegalArgumentException("x 不能为负");
}
static Point origin() { return new Point(0, 0); }
int sum() { return x + y; }
}
var p = new Point(1, 2);
p.x(); p.y(); // 访问器(不是 getX)
p.equals(new Point(1, 2)); // true
new Point(1, 2, 3); // 编译错:只有两个组件
// 泛型 record
record Pair<A, B>(A left, B right) {}
// 实现接口
record Range(int lo, int hi) implements Comparable<Range> {
public int compareTo(Range o) { return Integer.compare(lo, o.lo); }
}注意事项
- record 不可继承,也不能被继承(没有 extends 空间)
- 组件字段隐式 private final,无 setter——要改只能造新实例
- record 不能声明实例字段(只能是组件),但可有静态字段
- 紧凑构造器里赋值可用字段名直接引用(无需 this.x = x)
- record 适合 DTO/值对象;有可变状态或大量派生属性时用普通类