关于 java:3. Java 常用类库与数据结构

一、String

1.1 String 是什么?

public final class String implements java.io.Serializable, Comparable<String>, CharSequence

特点:

  • 不可变对象(immutable)

  • final 类,不能被继承

  • 内部使用 字符数组存储内容

  • 重写了 equals()hashCode()toString() 等方法

  • 实现了 ComparableCharSequence 接口

1.2 不可变特性详解

String s1 = "abc";
s1 = s1 + "d";
System.out.println(s1); // abcd
  • 本质上:s1 + "d" 生成了一个新对象 "abcd"s1 引用被修改,原 "abc" 没变

  • 不可变的好处:

    • 线程安全

    • 可以缓存 hash 值(提高查找效率)

    • 可以作为 HashMap 的 key(哈希值不变)

1.3 内存结构与字符串常量池

String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2); // true
  • "hello" 存在字符串常量池(方法区/元空间)

  • 相同字面量指向同一个对象,节省内存

String s3 = new String("hello");
System.out.println(s1 == s3); // false
  • new 会强制在堆上创建新对象,== 比较的是地址,不相等

intern() 方法

String s = new String("abc").intern();
  • 将字符串加入常量池并返回池中对象的引用

  • 常用于避免重复字符串

1.4 底层实现与源码分析(JDK 8)

private final char value[];
  • 每个 String 对象内部有一个 char[],一旦创建就不能变

  • JDK 9+ 改为使用 byte[] + 编码标识,提升效率

1.5 常用方法分类

>判断类方法

s.equals("abc")       // 是否相等
s.equalsIgnoreCase()  // 忽略大小写比较
s.contains("abc")     // 是否包含子串
s.startsWith("ab")    // 是否以 ab 开头
s.endsWith("bc")      // 是否以 bc 结尾

>查找/提取类方法

s.indexOf("a")         // 第一个 a 出现的位置
s.lastIndexOf("a")     // 最后一个 a 的位置
s.charAt(2)            // 获取第 3 个字符
s.substring(1, 4)      // 截取 [1,4) 子串

>替换/处理类方法

s.replace("a", "b")     // 替换
s.trim()                // 去掉首尾空格
s.toUpperCase()         // 转大写
s.toLowerCase()         // 转小写
s.split(",")            // 拆分字符串为数组

>转换类方法

String.valueOf(123)     // 任意类型转字符串
Integer.parseInt("123") // 字符串转 int
s.toCharArray()         // 字符串转字符数组

1.6 字符串拼接与性能分析

String result = "";
for (int i = 0; i < 1000; i++) {
    result += i;
}

上面每次 += 都会创建新对象,性能低下。

推荐使用:StringBuilder

StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
    sb.append(i);
}
String result = sb.toString();

1.7 字符串比较

String s1 = "abc";
String s2 = new String("abc");

System.out.println(s1 == s2);         // false(引用不同)
System.out.println(s1.equals(s2));    // true(内容相同)
  •  == 比较引用
  • equals() 比较内容
  • compareTo() 用于排序(按 Unicode)

1.8 String 在集合中做 key?

  • String 是不可变的,hashCode 不变,适合作为 HashMap 的 key。

  • equals()hashCode() 都已重写,保证内容相等时哈希一致。

1.9 常见问题

问题简要回答
String 为什么不可变?提高安全性、支持缓存、可作为 Hash key、线程安全
==equals() 区别?== 比地址,equals 比内容
字符串拼接性能问题?多次拼接用 StringBuilder
intern() 的作用?把字符串加入常量池,返回常量池中地址
字符串常量池在哪里?JDK 8 在方法区(元空间),JDK 7+ 移至堆
String 能被继承吗?不能,是 final 类
String 为什么能作为 Map 的 key?不可变、重写了 hashCode 和 equals
new String("abc") 创建了几个对象?常量池中 1 个("abc"),堆中又 1 个(new)

1.10 小结

特性说明
不可变修改就生成新对象,安全,支持哈希
常量池优化相同字面量只创建一次
内部结构JDK 8 是 char[],JDK 9 是 byte[] + 编码
性能优化建议多次拼接用 StringBuilder
与其他类区别与 StringBuilder / Buffer 的线程与性能区别

二、StringBuilder

2.1 什么是 StringBuilder?

public final class StringBuilder extends AbstractStringBuilder implements java.io.Serializable, CharSequence

特点:

  • 可变字符串(mutable)

  • 线程不安全(但性能更高)

  • 使用字符数组维护可变字符串内容

  • 用于大量拼接字符串时的性能优化

2.2 StringBuilder 与 String 的区别

特性StringStringBuilder
是否可变不可变(immutable)可变
线程安全安全不安全
拼接效率低(频繁创建新对象)高(内部数组直接修改)
底层结构char[]char[](可扩容)
用途小量拼接、常量字符串频繁拼接、大量字符串操作

2.3 常用构造函数

StringBuilder sb1 = new StringBuilder();          // 默认容量16
StringBuilder sb2 = new StringBuilder("hello");   // 初始化内容
StringBuilder sb3 = new StringBuilder(100);       // 指定初始容量

2.4 常用方法

方法作用
append()添加内容到末尾
insert(index, str)在指定位置插入字符串
delete(start, end)删除区间内容(左闭右开)
deleteCharAt(index)删除指定位置字符
replace(start, end, s)替换某一段字符串
reverse()反转字符串
toString()转成 String 对象
setCharAt(index, ch)修改指定位置字符
charAt(index)读取指定位置字符
length()当前长度
capacity()当前容量(可容纳的最大字符数)
ensureCapacity(int)手动增加容量
trimToSize()减少容量到实际长度

2.5 append 示例:高性能拼接

StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
    sb.append(i).append(",");
}
String result = sb.toString();
  • append() 会修改原数组,不创建新对象,效率远高于 String +=

2.6 底层原理:char[] + 自动扩容

// JDK 8 中
char[] value;
int count;
  • 初始容量为 16,超过就自动扩容

  • 每次扩容为:newCapacity = oldCapacity * 2 + 2

void expandCapacity(int minimumCapacity) {
    int newCapacity = (value.length << 1) + 2;
    if (newCapacity < minimumCapacity) {
        newCapacity = minimumCapacity;
    }
    value = Arrays.copyOf(value, newCapacity);
}

2.7 扩容机制详解

默认构造:

StringBuilder sb = new StringBuilder();
  • 初始化时创建 char[16] 数组

  • 一旦内容超过 16 个字符,就扩容为 16*2+2 = 34

  • 后续继续超过,又变为 34*2+2 = 70,以此类推

2.8 线程安全性对比:StringBuffer

类名可变线程安全性能使用场景
String最低字符串不变或少量拼接
StringBuilder最高单线程、大量拼接
StringBuffer中等多线程环境拼接字符串

2.9 常见问题

问题解答说明
StringBuilder 适合什么场景?在循环中频繁拼接字符串时使用
append 是怎么实现的?直接往 char[] 数组写,满了就扩容
线程安全吗?不安全(非同步),多线程环境用 StringBuffer
初始容量是多少?默认 16,构造函数可指定
为什么效率比 String 高?不创建新对象,原地修改数组,减少内存和 CPU 开销

2.10 实践建议

建议说明
多次拼接请用 StringBuilder尤其是循环中拼接字符串
如果知道大致容量,建议指定容量构造函数减少扩容次数,提高效率
单线程下推荐使用 StringBuilder比 StringBuffer 快很多
多线程共享字符串拼接建议用 StringBuffer线程安全但稍慢

2.11 示例代码

public class Demo {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder("abc");
        sb.append(123).append(true);
        System.out.println(sb); // abc123true

        sb.insert(3, "XYZ");
        System.out.println(sb); // abcXYZ123true

        sb.delete(3, 6);
        System.out.println(sb); // abc123true

        sb.replace(3, 6, "___");
        System.out.println(sb); // abc___true

        sb.reverse();
        System.out.println(sb); // eurt___cba

        System.out.println(sb.capacity()); // 查看当前容量
    }
}

三、StringBuffer

3.1 什么是 StringBuffer

public final class StringBuffer extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence

特点总结:

  • 可变字符串类(mutable)

  • 线程安全:方法加了 synchronized

  • 底层使用 char[] 存储字符串

  • 实现了 CharSequence 接口,可用于 for-each

3.2 StringBuffer 与其他类对比

类名可变线程安全适合场景性能
String不可变字符串、少量拼接最低
StringBuilder单线程环境拼接字符串最快
StringBuffer多线程环境拼接字符串较快(比 StringBuilder 慢)

3.3 常用构造方法

StringBuffer sb1 = new StringBuffer();               // 默认容量 16
StringBuffer sb2 = new StringBuffer("hello");        // 初始内容
StringBuffer sb3 = new StringBuffer(100);            // 指定容量

3.4 常用方法和功能

添加内容(append)

sb.append("abc");         // 添加字符串
sb.append(123);           // 添加数字
sb.append(true);          // 添加布尔值

插入内容(insert)

sb.insert(1, "xyz");      // 在位置1插入 "xyz"

删除内容(delete)

sb.delete(3, 6);          // 删除从3到6(左闭右开)
sb.deleteCharAt(2);       // 删除第2个字符

替换、反转、设置

sb.replace(1, 4, "ZZZ");  // 替换子串
sb.reverse();             // 反转整个字符串
sb.setCharAt(0, 'X');     // 修改第一个字符

长度与容量

sb.length();              // 当前实际长度
sb.capacity();            // 当前 char[] 容量(默认16)
sb.ensureCapacity(50);    // 预设容量,避免扩容

转换为 String

String s = sb.toString(); // 获取最终字符串

3.5 线程安全实现原理

所有核心方法都加了 synchronized,示例源码如下:

public synchronized StringBuffer append(String str) {
    super.append(str);
    return this;
}
  • 多线程环境中,同一个 StringBuffer 实例的操作是互斥的,防止数据错乱。

  • 缺点是性能稍慢。

3.6 扩容机制(与 StringBuilder 相同)

  • 初始容量是 16。

  • 如果容量不足,会扩容为:

newCapacity = oldCapacity * 2 + 2;

底层使用的数组方式(JDK 8):

char[] value;

3.7 性能对比总结

单线程下:

String str = "";
for (int i = 0; i < 10000; i++) {
    str += i; // 最慢(频繁创建新对象)
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10000; i++) {
    sb.append(i); // 推荐,最快
}
StringBuffer sbf = new StringBuffer();
for (int i = 0; i < 10000; i++) {
    sbf.append(i); // 稍慢,线程安全
}

3.8 常见问题

问题回答简要说明
StringBufferStringBuilder 区别?Buffer 线程安全,Builder 非线程安全
为什么 StringBuffer 慢?方法加了 synchronized,存在锁竞争
StringBuffer 初始容量是多少?默认是 16 字符长度
能否替代 String不能,String 是不可变类,适合做常量、Map key
适合的使用场景?多线程环境下的大量字符串拼接

3.9 示例代码

public class BufferDemo {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Hello");

        sb.append(" World");                // 拼接
        sb.insert(5, ",");                  // 插入
        sb.replace(0, 5, "Hi");             // 替换
        sb.deleteCharAt(2);                 // 删除字符
        sb.reverse();                       // 反转

        System.out.println(sb.toString());  // 输出结果
        System.out.println("Length: " + sb.length());
        System.out.println("Capacity: " + sb.capacity());
    }
}

3.10 小结

特性说明
可变性内容可变,支持追加、插入、替换
线程安全性所有方法加了 synchronized,适合并发场景
拼接效率String 高,单线程略低于 StringBuilder
扩容机制自动扩容为 old * 2 + 2
推荐场景多线程拼接字符串(如日志缓冲区、消息构建)

四、List(ArrayList、LinkedList)

4.1 List 接口简介

基本定义

public interface List<E> extends Collection<E>

特点:

  • 有序集合(元素按插入顺序排列)

  • 允许重复元素

  • 可以通过索引(index)访问元素

  • 提供大量用于插入、删除、替换的操作方法

4.2 常用方法

方法说明
add(E e)添加元素到末尾
add(int index, E e)指定位置插入
remove(int index)删除指定位置元素
get(int index)获取指定位置元素
set(int index, E e)替换指定位置的元素
indexOf(Object o)返回首次出现的索引
contains(Object o)是否包含某个元素
size()集合大小
clear()清空集合

4.3 List 的两大核心实现类对比:ArrayList vs LinkedList

特性ArrayListLinkedList
底层结构动态数组(Object[])双向链表(Node)
查询效率高(O(1))低(O(n))
插入/删除效率中(尾部快,中间慢,O(n))高(O(1) 位置已知)
内存使用少(数组连续内存)多(存指针结构)
线程安全
适合场景多查询、少插入/删除多插入/删除、少查询

4.4 ArrayList 详解

构造函数

List<String> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>(100); // 指定初始容量

底层实现

  • 内部使用 Object[] 数组存储元素

  • 容量不够时自动扩容(扩容机制为原容量的 1.5倍

  • 随机访问元素效率高:list.get(i) 时间复杂度 O(1)

添加元素

list.add("A");           // 添加到末尾
list.add(1, "B");        // 插入到下标1

删除元素

list.remove(0);          // 删除指定下标
list.remove("A");        // 删除首次匹配元素

查询元素

list.get(0);             // 获取第一个元素
list.contains("X");      // 是否存在

遍历

for (String s : list) { System.out.println(s); }

4.5 LinkedList 详解

构造函数

List<String> list = new LinkedList<>();

底层实现

private static class Node<E> {
    E item;
    Node<E> next;
    Node<E> prev;
}
  • 每个元素是一个节点,节点包含指向前一个、后一个的引用

  • 插入、删除元素时只需改指针,不需要数组拷贝

  • 访问指定位置时,需要从头/尾顺序遍历,效率低

特有方法(作为队列和栈)

方法类型说明
addFirst()栈/队列从头部添加元素
addLast()队列从尾部添加元素
removeFirst()栈/队列移除头部元素
removeLast()队列移除尾部元素
peekFirst()队列/栈查看头部元素但不删除

4.6 应用场景对比总结

使用场景推荐使用的实现类
查询操作频繁ArrayList(效率高)
插入/删除操作频繁LinkedList(无需位移)
实现队列(FIFO)LinkedList
实现栈(LIFO)LinkedList
数据结构较小,无需考虑性能任意都可以

4.7 实战示例

import java.util.*;

public class ListDemo {
    public static void main(String[] args) {
        // ArrayList 示例
        List<String> arrayList = new ArrayList<>();
        arrayList.add("Java");
        arrayList.add("Python");
        arrayList.add("C++");
        System.out.println("ArrayList: " + arrayList);

        // LinkedList 示例(队列)
        LinkedList<String> linkedList = new LinkedList<>();
        linkedList.addFirst("A");
        linkedList.addLast("B");
        linkedList.add("C"); // 默认加在尾部
        System.out.println("LinkedList: " + linkedList);

        linkedList.removeFirst();
        System.out.println("After removeFirst: " + linkedList);
    }
}

4.8 常见问题

问题简要解答
ArrayList 和 LinkedList 区别?底层结构、增删查性能差异
ArrayList 如何扩容?原容量的 1.5 倍(newCapacity = old + old >> 1
LinkedList 插入为什么效率高?改链表指针即可,无需数组移动
ArrayList 删除中间元素性能差在哪里?后续元素要整体前移,O(n)
是否线程安全?默认都不是,需使用 Collections.synchronizedList

4.9 线程安全的 List

List<String> safeList = Collections.synchronizedList(new ArrayList<>());

或者使用 JDK 1.5 之后的:

List<String> copyOnWriteList = new CopyOnWriteArrayList<>();

适用于读多写少的并发场景。


五、Map(HashMap、TreeMap、LinkedHashMap)

5.1 Map 接口简介

特点:

  • 存储的是「键值对 key-value

  • key 不可重复,value 可重复

  • 常用于:缓存、对象映射、参数传递等

  • 提供查询、添加、删除、遍历等操作

5.2 常用 Map 实现类对比

实现类底层结构是否有序是否线程安全是否允许 null key/value排序方式
HashMap数组 + 链表 + 红黑树(JDK8) 无序 允许无顺序
LinkedHashMapHashMap + 双向链表 插入顺序 允许按插入顺序
TreeMap红黑树(Tree) 排序 不允许 null key按 key 自然顺序 或 Comparator

5.3 Map 常用方法

方法说明
put(K key, V value)添加或替换键值对
get(K key)根据 key 获取 value
remove(K key)删除指定 key 的项
containsKey(K key)是否包含某个 key
containsValue(V value)是否包含某个 value
keySet()获取所有 key 的集合
values()获取所有 value 的集合
entrySet()获取所有键值对(Map.Entry)集合
size()获取元素个数

5.4 HashMap 详解

底层结构(JDK 1.8)

Node<K,V>[] table; // 数组
  • 每个桶(table[i])是一个链表或红黑树

  • 默认初始容量:16

  • 负载因子:0.75(容量达到 75% 时触发扩容)

  • 触发红黑树条件:

    • 链表长度 ≥ 8 且 table.length ≥ 64,才转换为红黑树

    • 否则仍使用链表(节省空间)

put 原理简述:

hash(key) -> 计算 hash 值
index = hash & (table.length - 1) -> 计算桶位置
插入链表 or 红黑树 or 替换已有 key 的值

示例代码:

Map<String, Integer> map = new HashMap<>();
map.put("A", 1);
map.put("B", 2);
System.out.println(map.get("A")); // 输出 1

5.5 LinkedHashMap 详解

特点:

  • 保持插入顺序(也可配置为访问顺序)

  • 基于 HashMap + 双向链表 实现

  • 常用于实现 LRU 缓存

结构图示:

HashMap 提供存取性能
双向链表维护元素顺序

LRU 缓存示例

LinkedHashMap<String, String> lruCache = new LinkedHashMap<>(16, 0.75f, true) {
    protected boolean removeEldestEntry(Map.Entry eldest) {
        return size() > 100;
    }
};

5.6 TreeMap 详解(有序)

特点:

  • 内部基于红黑树实现

  • 元素按 key 的自然顺序Comparator 指定顺序排序

  • 查询、插入、删除复杂度为 O(log n)

适合场景:

  • 要求 key 有序,如:排行榜、时间线

  • 需要按区间查询数据

示例代码:

TreeMap<Integer, String> treeMap = new TreeMap<>();
treeMap.put(3, "C");
treeMap.put(1, "A");
treeMap.put(2, "B");
System.out.println(treeMap); // 按 key 升序输出

5.7 三者使用场景对比

场景推荐 Map 实现类
快速存取、无序HashMap
保留插入顺序LinkedHashMap
要求 key 排序或区间查询TreeMap
实现 LRU 缓存LinkedHashMap(访问顺序)
线程安全要求ConcurrentHashMap(推荐)

5.8 线程安全 Map 替代品

类名特点
Hashtable线程安全,方法加 synchronized,效率低
Collections.synchronizedMap包装同步 Map,对每个方法加锁
ConcurrentHashMap高并发环境下的 Map,分段锁或 CAS,更高性能

5.9 遍历方式

// 遍历键值对
for (Map.Entry<String, Integer> entry : map.entrySet()) {
    System.out.println(entry.getKey() + ": " + entry.getValue());
}

// 遍历 key
for (String key : map.keySet()) {
    System.out.println(key);
}

// 遍历 value
for (Integer value : map.values()) {
    System.out.println(value);
}

5.10 常见问题

问题解答简要
HashMap 如何解决哈希冲突?链地址法(链表)+ JDK8 后转为红黑树
HashMap 扩容机制?扩容为原容量的2倍,重新计算 hash 和索引
HashMap 的线程不安全性体现?并发 put 可能导致死循环、数据丢失等
HashMap 和 TreeMap 区别?HashMap 无序,TreeMap 有序(红黑树)
LinkedHashMap 如何实现 LRU?构造函数设为访问顺序 + 重写 removeEldestEntry
HashMap 初始容量设多少最合适?预计大小 / 0.75(负载因子)

5.11 小结

实现类底层结构是否有序主要用途
HashMap数组 + 链表/红黑树无序常规场景,性能好
LinkedHashMapHashMap + 双向链表插入序顺序访问、LRU 缓存等
TreeMap红黑树排序有序数据存储、区间查询

六、Set(HashSet、TreeSet)

6.1 Set 接口简介

特点:

  • 元素不可重复(底层通过比较是否相等来判断)

  • 不保证元素顺序(除非用 TreeSet

  • 适用于去重、集合运算、判重等场景

6.2 Set 常用实现类对比

实现类底层结构是否有序是否线程安全null 是否允许排序依据
HashSetHashMap 实现 无序允许一个 null无序(依赖 hash 值)
TreeSetTreeMap(红黑树)有序不允许 null按照 Comparable 或 Comparator

6.3 HashSet 详解

底层原理

  • HashSet 底层使用了一个 HashMap 来实现,值存在 Map 的 key 里

  • 本质:HashSet<E> set = new HashSet<>(); 其实是 Map<E, Object> map = new HashMap<>();

特点:

  • 插入顺序不保证

  • 元素唯一性通过 hashCode()equals() 决定

  • 插入效率高,适合查重、快速去重

示例:

Set<String> set = new HashSet<>();
set.add("A");
set.add("B");
set.add("A");  // 被忽略,不重复
System.out.println(set); // [A, B],无序

重要方法:

方法作用
add(E e)添加元素(若重复返回 false)
remove(E e)删除元素
contains(E e)判断元素是否存在
size()获取元素数量
clear()清空集合
isEmpty()判断是否为空

6.4 TreeSet 详解(排序用)

底层原理:

  • TreeSet 是基于 TreeMap 实现的,内部维护的是一棵红黑树

  • 元素自动排序(升序)

特点:

  • 有序:默认按自然顺序(Comparable),也可自定义排序器(Comparator)

  • 查询/插入/删除时间复杂度为 O(log n)

  • 不允许添加 null 元素

示例:

Set<Integer> treeSet = new TreeSet<>();
treeSet.add(5);
treeSet.add(1);
treeSet.add(3);
System.out.println(treeSet); // [1, 3, 5],有序

自定义排序:

Set<String> sortedSet = new TreeSet<>((a, b) -> b.compareTo(a)); // 降序
sortedSet.add("apple");
sortedSet.add("banana");
System.out.println(sortedSet); // [banana, apple]

6.5 Set 相关问题

1)Set 为什么不能存重复元素?

因为底层在 HashSet 中是使用 hashCode()equals() 来判断两个元素是否“相同”。一旦认为相同,新的元素就不会被加入。重点:重写 equals 一定要同时重写 hashCode

2)HashSet 添加自定义对象无效,怎么解决?

class Person {
    String name;
    int age;

    // 忘记重写 equals 和 hashCode 会导致 set 无法正确去重
}
@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Person person = (Person) o;
    return age == person.age && name.equals(person.name);
}

@Override
public int hashCode() {
    return Objects.hash(name, age);
}

3)TreeSet 是否能存 null?

  • 不可以!

  • 插入 null 会抛出 NullPointerException(因为无法与其他元素进行比较)

4)Set 如何实现排序功能?

  • 使用 TreeSet(默认升序)

  • 或者使用 List + Collections.sort() 来手动排序

6.6 遍历方式(适用于所有 Set)

Set<String> set = new HashSet<>();
set.add("A");
set.add("B");

// 方式1:增强 for 循环
for (String s : set) {
    System.out.println(s);
}

// 方式2:迭代器
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}

6.7 Set vs List 对比

特点SetList
是否可重复
是否有序TreeSet 有序,HashSet 无序有序(ArrayList)
查询性能TreeSet 慢于 HashSetArrayList 查询快
应用场景去重、集合运算排序、位置访问操作

6.8 小结

实现类底层结构是否排序是否允许 null典型用途
HashSetHashMap无序允许一个去重、无序集合
TreeSet红黑树(TreeMap)自动排序不允许有序集合、排序需求

七、Collection

7.1 Collection 简介

定义:Collection 是 Java 集合框架中最基本的接口,是 List、Set、Queue 的父接口。用于存储一组对象(元素),是单值集合的顶层接口(不同于 Map)。

public interface Collection<E> extends Iterable<E>

常用子接口:

          Collection
             ↑
     ┌───────┼────────┐
     ↓       ↓        ↓
   List     Set     Queue

7.2 Collection 的常用方法

方法说明
boolean add(E e)添加元素
boolean addAll(Collection c)添加集合中的所有元素
void clear()清空集合
boolean contains(Object o)是否包含某元素
boolean containsAll(Collection c)是否包含所有元素
boolean isEmpty()是否为空集合
Iterator<E> iterator()返回迭代器
boolean remove(Object o)删除指定元素
boolean removeAll(Collection c)删除所有与集合相同的元素
boolean retainAll(Collection c)取交集(只保留同时存在的)
int size()获取元素个数
Object[] toArray()转为 Object 数组
<T> T[] toArray(T[] a)转为指定类型数组

7.3 Collection 常见使用示例

Collection<String> coll = new ArrayList<>();
coll.add("apple");
coll.add("banana");

System.out.println(coll.contains("apple"));  // true
System.out.println(coll.size());            // 2

for (String item : coll) {
    System.out.println(item);
}

coll.remove("banana");
System.out.println(coll);  // [apple]

7.4 Collection 接口 VS Arrays

对比项Collection 接口数组(Array)
大小可变固定大小
类型存储对象基本类型或对象
方法支持有大量操作方法无操作方法,结构简单
性能较低(要平衡功能)高(但功能有限)

7.5 Collection 接口的实现体系

接口/类类型特点/说明
List接口有序、可重复元素
Set接口无序、不可重复元素
Queue接口队列,先进先出
Deque接口双端队列
ArrayListList 实现动态数组结构,查询快
LinkedListList & Deque 实现链表结构,增删快
HashSetSet 实现无序、基于哈希表
TreeSetSet 实现有序、基于红黑树
PriorityQueueQueue 实现优先队列,可自定义优先级

7.6 增强 for 和 Iterator 遍历

Collection<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");

// 增强 for
for (String lang : list) {
    System.out.println(lang);
}

// Iterator
Iterator<String> it = list.iterator();
while (it.hasNext()) {
    System.out.println(it.next());
}

7.7 与泛型结合使用

避免强制类型转换,提高代码安全性与可读性:

Collection<Integer> nums = new ArrayList<>();
nums.add(10);
nums.add(20);

for (int num : nums) {
    System.out.println(num);
}

7.8 常见问题

Collection 与 Collections 区别?

名称类型说明
Collection接口是集合类的顶层接口,用于存储一组对象
Collections工具类提供各种集合相关的静态方法,如排序、复制、线程安全包装等

为什么 Collection 接口没有 get(int index) 方法?

因为不是所有集合都有顺序(如 Set),因此不提供按下标访问的统一定义。只有 List(有序)提供此能力。

7.9 小结

特点说明
接口层级Collection 是 List、Set 的父接口
主要功能单值集合(增删查遍历等)
常见实现类ArrayList, LinkedList, HashSet 等
与 Map 区别Collection 只能存单值,Map 是键值对
与数组对比集合功能强大,数组结构简单

八、Iterator

8.1 什么是 Iterator?

定义:Iterator 是一个迭代器接口,用于遍历集合中的元素。它是 Collection 接口的一个成员方法返回的对象。

public interface Iterator<E> {
    boolean hasNext();
    E next();
    void remove(); // 可选操作
}

8.2 Iterator 能做什么?

方法作用
hasNext()判断是否还有下一个元素
next()返回下一个元素
remove()删除当前迭代到的元素(调用 next() 后才能调用)

8.3 常见使用方式

List<String> list = new ArrayList<>();
list.add("Java");
list.add("Python");
list.add("C++");

Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    String lang = iterator.next();
    System.out.println(lang);
}

8.4 与增强 for 的区别

特点增强 forIterator
语法简洁否,需显式声明
遍历安全性否,不能安全删除元素是,可以安全删除元素
适用范围Iterable 接口(如 Collection)同样适用
是否能修改元素是 可通过 remove() 删除

8.5 使用 Iterator 删除元素(正确方式)

不要在增强 for 中删除元素!会报 ConcurrentModificationException

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);

Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
    int num = it.next();
    if (num == 2) {
        it.remove(); // 安全删除
    }
}
System.out.println(list); // [1, 3]

8.6 fail-fast机制(快速失败)

现象:如果在使用 Iterator 遍历集合时,集合结构被外部修改(非通过 Iterator.remove()),就会抛出:

java.util.ConcurrentModificationException

示例(错误写法):

List<String> list = new ArrayList<>();
list.add("a");
list.add("b");

for (String s : list) {
    if (s.equals("b")) {
        list.remove(s); // 修改结构,触发 fail-fast
    }
}

正确做法:

Iterator<String> it = list.iterator();
while (it.hasNext()) {
    if (it.next().equals("b")) {
        it.remove(); // 安全删除
    }
}

原因分析:ArrayListHashSet 等集合中维护了一个 modCount 字段,记录结构修改次数。Iterator 内部也保存了一个期望的 expectedModCount,两者不一致就抛异常。

8.7 Iterable 接口与 for-each 本质

Collection 实现了 Iterable:

public interface Iterable<T> {
    Iterator<T> iterator();
}

所以增强 for 本质上就是调用了 iterator()

for (String s : list) {
    System.out.println(s);
}
// 相当于:
for (Iterator<String> it = list.iterator(); it.hasNext(); ) {
    String s = it.next();
    System.out.println(s);
}

8.8 使用场景总结

场景是否适合使用 Iterator
遍历元素
删除元素是(比 for 循环更安全)
随机访问(按下标)否(用 List 的 get 更合适)

8.9 与 ListIterator 区别(只用于 List)

方法IteratorListIterator
支持向前遍历不支持支持 hasPrevious()previous()
支持添加元素不支持支持 add()
支持替换元素不支持支持 set()
适用集合Collection只能用于 List

8.10 小结

关键点内容
核心方法hasNext()next()remove()
删除方式推荐使用 Iterator.remove()
fail-fast非法修改集合结构会抛异常
遍历替代方式增强 for(简单,但不能安全删除元素)
适配接口CollectionMapkeySet()/entrySet()

九、泛型

9.1 什么是泛型?

泛型(Generic)允许在定义类、接口、方法时使用类型参数,使代码在编译时就进行类型检查,避免强制类型转换。

例子:

List<String> list = new ArrayList<>();
list.add("Java");
String s = list.get(0); // 不需要强制类型转换

没有泛型前:

List list = new ArrayList();
list.add("Java");
String s = (String) list.get(0); // 需要强转,易出错

9.2 泛型的好处

优势说明
编译期类型检查提前发现错误,避免 ClassCastException
消除强制类型转换简化代码
提高代码复用性写一次泛型类,可适用于多种类型

9.3 泛型使用位置

1)泛型类

public class Box<T> {
    private T value;
    public void set(T value) { this.value = value; }
    public T get() { return value; }
}

使用:

Box<String> stringBox = new Box<>();
stringBox.set("Hello");
System.out.println(stringBox.get()); // Hello

2)泛型接口

public interface Converter<F, T> {
    T convert(F from);
}

实现类:

public class StringToIntegerConverter implements Converter<String, Integer> {
    public Integer convert(String from) {
        return Integer.parseInt(from);
    }
}

3)泛型方法

public class Util {
    public static <T> void printArray(T[] array) {
        for (T item : array) {
            System.out.println(item);
        }
    }
}

调用:

String[] arr = {"A", "B", "C"};
Util.printArray(arr);

9.4 常见泛型写法

写法说明
<T>单个类型参数,常见
<K, V>多个类型参数,如 Map
<E>常用于集合(Element)

9.5 泛型通配符 ?

1)<?> 表示任意类型

public void printList(List<?> list) {
    for (Object o : list) {
        System.out.println(o);
    }
}

不能往 List<?> 添加任何元素(除了 null),因为编译器不知道真实类型。

2)<? extends T> 上界通配符:T 及其子类

public void printUpper(List<? extends Number> list) {
    // list 可能是 List<Integer>, List<Double>...
}

特点:可读不可写(写入时类型不明确)

3)<? super T> 下界通配符:T 及其父类

public void printLower(List<? super Integer> list) {
    list.add(10); // 可以添加 Integer 或其子类
}

特点:可写不可读(读取时只能当 Object)

9.6 泛型擦除(类型擦除)

Java 泛型只在编译期有效,编译后会擦除类型信息,称为 Type Erasure

List<String> list = new ArrayList<>();
List<Integer> list2 = new ArrayList<>();

System.out.println(list.getClass() == list2.getClass()); // true

9.7 泛型的限制

限制说明
不能使用基本类型(int、double 等)用包装类代替,如 Integer
泛型类中不能创建泛型数组new T[] 不允许
不能在泛型中使用 instanceof 判断类型instanceof T 不合法

9.8 类型变量命名规范

符号含义
TType 类型
EElement 元素(集合常用)
KKey 键(Map 常用)
VValue 值(Map 常用)
NNumber 数值类型

9.9 示例:泛型与集合结合使用

Map<String, List<Integer>> map = new HashMap<>();
List<Integer> scores = new ArrayList<>();
scores.add(90);
map.put("Tom", scores);

System.out.println(map.get("Tom").get(0)); // 90

9.10 泛型 VS Object 的对比

特性使用 Object使用泛型
类型检查运行时检查,风险高编译时检查,安全
可读性低,需要强转高,清晰直观
类型转换必须强转自动完成

9.11 小结

概念关键点
泛型类<T> 定义类中的类型
泛型方法<T> 返回类型 方法名(...)
通配符<?>, <? extends T>, <? super T>
泛型擦除编译后泛型信息被擦除
编译期安全性最大优势是避免 ClassCastException

十、Arrays 工具类

10.1 Arrays 工具类简介

  • 包名java.util.Arrays

  • 作用:提供数组的排序、搜索、复制、填充、比较、转字符串等静态方法

  • 特点:全部是静态方法(static),不需要创建对象,直接用类名调用即可。

10.2 常用方法总览(分类汇总)

方法分类常用方法简介
排序sort()排序数组(默认升序)
查找binarySearch()使用二分查找定位元素(排序后使用)
比较equals()判断两个数组是否相等(元素逐一比较)
复制copyOf(), copyOfRange()拷贝数组
填充fill()用指定值填充整个数组
输出toString()转换为字符串(调试友好)
并行操作parallelSort()多线程快速排序(大数组更快)

10.3 各方法详细讲解

1)sort() – 数组排序

int[] arr = {3, 1, 5, 2};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr)); // [1, 2, 3, 5]

支持对基本类型和对象数组排序。对象数组需实现 Comparable 或传入 Comparator

String[] names = {"Bob", "Alice", "Eve"};
Arrays.sort(names); // 按字母排序

2)binarySearch() – 二分查找(数组必须已排序)

int[] arr = {1, 2, 3, 5};
int index = Arrays.binarySearch(arr, 3); // 返回索引:2
int indexNotFound = Arrays.binarySearch(arr, 4); // 返回插入点位置的负值 -4(-插入位置 -1)

使用前必须排序,否则结果不可预测。

3)equals() – 比较两个数组是否完全相等

int[] a = {1, 2, 3};
int[] b = {1, 2, 3};
System.out.println(Arrays.equals(a, b)); // true

对于二维数组(多维),需要用 deepEquals()

int[][] x = {{1, 2}, {3, 4}};
int[][] y = {{1, 2}, {3, 4}};
System.out.println(Arrays.deepEquals(x, y)); // true

4)copyOf()copyOfRange() – 数组复制

int[] arr = {1, 2, 3};
int[] copy = Arrays.copyOf(arr, 5); // 多余位置填 0: [1, 2, 3, 0, 0]

int[] part = Arrays.copyOfRange(arr, 1, 3); // 复制索引1到3(不含3):[2, 3]

5)fill() – 填充数组

int[] arr = new int[5];
Arrays.fill(arr, 7); // 所有元素变成 7: [7, 7, 7, 7, 7]

也可以指定范围:

Arrays.fill(arr, 1, 4, 99); // 填充索引 1~3(不含4):[7, 99, 99, 99, 7]

6)toString() – 数组转字符串

int[] arr = {1, 2, 3};
System.out.println(Arrays.toString(arr)); // [1, 2, 3]

二维数组使用 deepToString()

int[][] matrix = {{1,2}, {3,4}};
System.out.println(Arrays.deepToString(matrix)); // [[1, 2], [3, 4]]

7)asList() – 将数组转为 List(固定长度)

String[] array = {"A", "B", "C"};
List<String> list = Arrays.asList(array); // 支持列表操作

list.set(1, "Z"); // 修改元素
System.out.println(list); // [A, Z, C]

// list.add("D"); // 会抛异常:UnsupportedOperationException

返回的 List 是固定长度的,不支持 add/remove 操作。

8)parallelSort() – 并行排序(Java 8+)

int[] largeArray = new int[1000000];
// 填充数据...
Arrays.parallelSort(largeArray);

它使用多线程对大数组排序,速度比 sort() 更快(当数据量大时),但小数组效果不明显。

10.4 Arrays 工具类的使用建议

场景建议方法
简单排序Arrays.sort()
大数据排序(Java 8+)Arrays.parallelSort()
拷贝数组Arrays.copyOf()
找元素(已排序)Arrays.binarySearch()
填充默认值Arrays.fill()
调试输出数组Arrays.toString()

10.5 与集合框架联动

可以通过 Arrays.asList() 将数组转为 List,适配 Java 集合操作:

String[] arr = {"a", "b", "c"};
List<String> list = Arrays.asList(arr);
Collections.reverse(list); // 反转
System.out.println(list);  // [c, b, a]

10.6 常见注意事项

注意点说明
asList() 返回的是固定长度 List不能添加/删除元素
copyOf() 目标长度不够会截断,过长会补零
binarySearch() 必须在排序后使用
排序为原地排序(会修改原数组)

10.7 小结

方法说明
sort()升序排序
parallelSort()多线程排序(Java 8+)
binarySearch()二分查找(必须排序)
equals()判断是否内容相等
copyOf()拷贝数组
fill()填充数组
toString()转字符串
asList()数组转 List
deepToString()多维数组转字符串
deepEquals()多维数组比较

十一、Collections 工具类

11.1 Collections 工具类简介

  • 包名java.util.Collections

  • 作用:提供对集合对象进行排序、查找、填充、线程安全化、反转、打乱顺序等操作的静态方法集合

  • Arrays 类似:它是用于集合的工具类,而 Arrays 是数组的工具类。

11.2 常用方法总览(分类整理)

功能分类方法举例
排序sort(List)reverseOrder()
查找binarySearch(List, key)max()min()
修改reverse()shuffle()fill()replaceAll()
同步synchronizedList()synchronizedMap()
不可变集合unmodifiableList()singletonList()
线程安全集合synchronizedXxx()
其他frequency()disjoint()

11.3 各方法详细讲解

1)排序:Collections.sort()

List 进行排序,要求元素实现了 Comparable 接口:

List<Integer> list = Arrays.asList(3, 1, 2);
Collections.sort(list);
System.out.println(list); // [1, 2, 3]

自定义排序规则(传入 Comparator):

Collections.sort(list, (a, b) -> b - a); // 降序
System.out.println(list); // [3, 2, 1]

2)查找:binarySearch()max()min()

List<String> names = Arrays.asList("Bob", "Alice", "Tom");
Collections.sort(names); // 先排序
int idx = Collections.binarySearch(names, "Tom");
System.out.println(idx); // 查找 Tom 的索引

System.out.println(Collections.max(names)); // Tom(字典序最大)
System.out.println(Collections.min(names)); // Alice(最小)

3)修改内容

reverse():反转列表顺序

Collections.reverse(list);

shuffle():打乱顺序(常用于洗牌)

Collections.shuffle(list);

fill():将所有元素替换为指定值

Collections.fill(list, 99); // 全部改为 99

replaceAll():将某值替换为另一个值

Collections.replaceAll(list, 99, 0); // 把所有99替换为0

4)线程安全包装:synchronizedXxx()

将集合包装为线程安全版本:

List<String> safeList = Collections.synchronizedList(new ArrayList<>());
Map<String, String> safeMap = Collections.synchronizedMap(new HashMap<>());

注意:虽然线程安全,但遍历时仍需要外部同步锁

synchronized (safeList) {
    for (String s : safeList) {
        // 遍历
    }
}

5)不可变集合(只读集合)

List<String> readonly = Collections.unmodifiableList(new ArrayList<>());
readonly.add("X"); // 会抛出 UnsupportedOperationException

可用于 API 返回值,防止外部修改。

6)单元素集合:singletonList()singletonMap()

List<String> onlyOne = Collections.singletonList("hello");
Map<String, String> map = Collections.singletonMap("key", "value");

生成只能包含一个元素的集合。

7)工具方法

frequency():统计某个元素出现的次数

List<String> list = Arrays.asList("a", "b", "a", "c");
int freq = Collections.frequency(list, "a"); // 2

disjoint():判断两个集合是否没有交集

boolean result = Collections.disjoint(list1, list2);

11.4 实战场景

场景方法
快速排序 ListCollections.sort()
洗牌算法Collections.shuffle()
线程安全 ListCollections.synchronizedList()
防止外部修改返回值Collections.unmodifiableList()
查询最大/最小值Collections.max() / min()
查找元素位置Collections.binarySearch()(排序后)

11.5 注意事项

注意点说明
binarySearch() 必须排序后使用否则结果不准确
synchronizedXxx() 不等于绝对线程安全遍历时仍需加锁
unmodifiableXxx() 只是包装,不可修改调用 add() 会抛异常
singletonList() 集合固定长度不可扩展不支持添加多个元素

11.6 与 Arrays 工具类的对比

工具类用于对象常用操作
Arrays数组排序、复制、比较、查找等
Collections集合(List等)排序、线程安全、不可变、打乱等

11.7 小结

方法名功能简介
sort(List)升序排序
reverse(List)反转顺序
shuffle(List)打乱顺序
binarySearch(List, x)二分查找
max(List) / min()最大 / 最小值
replaceAll()替换所有匹配元素
frequency()某元素出现次数
disjoint()判断是否无交集
synchronizedList()转线程安全 List
unmodifiableList()转只读 List

十二、包装类

12.1 什么是包装类(Wrapper Class)

包装类是 Java 为 每个基本数据类型 提供的 类类型封装,用于将 基本类型转换为对象类型,以便在需要对象的场合中使用。

基本类型包装类
byteByte
shortShort
intInteger 
longLong
floatFloat
doubleDouble
charCharacter 
booleanBoolean 

12.2 为什么需要包装类

  • 集合不能直接存储基本类型
    Java 集合如 ArrayList<int> 是不允许的,但 ArrayList<Integer> 是可以的。

  • 对象方法调用需要对象
    基本类型没有方法,但包装类可以调用 equals()compareTo() 等方法。

  • 工具类支持
    如:Collections.max(List<Integer>) 只能处理对象。

  • 与泛型协同工作
    Java 泛型只支持对象类型。

12.3 如何使用包装类

创建包装类对象

Integer a = new Integer(10);      // 旧写法,不推荐
Integer b = Integer.valueOf(10);  // 推荐

Double d = Double.valueOf(3.14);
Character ch = Character.valueOf('A');

12.4 自动装箱 / 自动拆箱(Java 5 引入)

自动装箱(Auto Boxing)

将基本类型 自动转换为对应的包装类对象

int x = 5;
Integer obj = x; // 自动装箱:等同于 Integer.valueOf(x)

自动拆箱(Auto Unboxing)

将包装类对象 自动转换为基本类型

Integer obj = 10;
int y = obj; // 自动拆箱:等同于 obj.intValue()

12.5 常用方法(以 Integer 举例)

Integer x = Integer.valueOf("123");   // 字符串转 Integer
int y = x.intValue();                 // 拆箱为 int
String s = Integer.toString(456);     // int 转字符串
int z = Integer.parseInt("789");      // 字符串转 int

类似的方法也适用于 Double.parseDouble(), Boolean.parseBoolean() 等。

12.6 包装类中的常量与缓存

Integer 缓存机制

Integer a = 100;
Integer b = 100;
System.out.println(a == b); // true 

Integer c = 200;
Integer d = 200;
System.out.println(c == d); // false 

原因:

  • Java 缓存了 -128 到 127 的整数,所以这段范围内的包装类对象不会创建新对象,而是从缓存中取出同一个对象。

  • 超出范围就会创建新的对象。

12.7 包装类的不可变性(Immutable)

包装类对象是不可变的,一旦创建,值就不能更改。

Integer x = 10;
x = x + 1; // 实际上创建了一个新的 Integer 对象

12.8 包装类和 == / .equals() 的区别

Integer a = 128;
Integer b = 128;

System.out.println(a == b);      // false,比较的是引用
System.out.println(a.equals(b)); // true,比较的是值

结论:

  • 比较数值内容,使用 .equals()

  • == 比较的是对象引用地址,只有在 缓存区 -128~127 内才可能是 true

12.9 包装类使用场景总结

场景示例
集合中使用基本类型List<Integer>
解析字符串为数字Integer.parseInt("12")
比较两个数字大小Integer.compare(a, b)
与泛型协同使用Map<String, Double>
与 Stream/Optional 协作Optional<Integer>

12.10 八个包装类概览

包装类常用静态方法特点 / 注意事项
IntegervalueOf(), parseInt()有缓存区 -128~127 
DoublevalueOf(), parseDouble()没有缓存
BooleanparseBoolean(), valueOf()Boolean.TRUE/FALSE 单例
CharacterisDigit(), isLetter()方法用于判断字符类型
LongvalueOf(), parseLong()也有缓存(默认 -128~127)
FloatvalueOf(), parseFloat()没有缓存
ShortvalueOf(), parseShort()有缓存
BytevalueOf(), parseByte()有缓存

12.11 与基本类型的区别对比

对比项基本类型 int包装类 Integer
是否是对象是 
是否可为空可以为 null 
占用内存多(有对象开销)
支持泛型/集合是 
默认值0null

十三、自动装箱与拆箱

13.1 什么是自动装箱与自动拆箱?

这是 Java 从 JDK 1.5(Java 5) 引入的特性,目的是让 基本数据类型与包装类之间的转换更自然、更简洁,从而方便与集合、泛型等机制协作。

名称作用
自动装箱基本类型 ➜ 包装类对象
自动拆箱包装类对象 ➜ 基本类型

13.2 基本使用示例

自动装箱

int num = 10;
Integer obj = num;  // 自动装箱,相当于:Integer obj = Integer.valueOf(num);

自动拆箱

Integer obj = 20;
int num = obj;      // 自动拆箱,相当于:int num = obj.intValue();

13.3 装箱与拆箱的实际过程

操作代码实际编译后的代码
Integer x = 1;Integer x = Integer.valueOf(1);
int y = x;int y = x.intValue();

自动装箱就是调用包装类的静态方法 valueOf()
自动拆箱就是调用包装类实例的方法 xxxValue()

13.4 自动装箱 & 拆箱在表达式中的表现

Integer a = 100;
Integer b = 100;
System.out.println(a == b); // true(缓存范围内)

Integer c = 200;
Integer d = 200;
System.out.println(c == d); // false(超出缓存)

System.out.println(c == 200); // true,c 自动拆箱为 int 后比较
  • c == 200:包装类 Integer 会拆箱为 int,与 int 进行数值比较。

13.5 自动拆箱带来的潜在问题(空指针)

注意!拆箱 null 会抛异常:

Integer obj = null;
int num = obj; // NullPointerException!

原因:尝试执行 obj.intValue(),而 objnull,所以抛出异常。

13.6 在集合与泛型中的应用

集合(如 List)不能存储基本类型,但可以通过自动装箱存储包装类对象:

List<Integer> list = new ArrayList<>();
list.add(1);       // 自动装箱为 Integer.valueOf(1)
int x = list.get(0); // 自动拆箱为 int

13.7 自动装箱缓存机制(Integer 缓存池)

Integer 缓存池范围:-128 ~ 127

Integer a = 127;
Integer b = 127;
System.out.println(a == b); // true 

Integer x = 128;
Integer y = 128;
System.out.println(x == y); // false 
  • Integer.valueOf(int i) 会使用缓存池:-128 ~ 127 范围内直接返回缓存对象。

  • 超出范围会创建新对象,因此不是同一个引用。

这也解释了为什么 == 比较时结果不一致。

13.8 自动装箱的性能问题

装箱会创建对象,在高频操作中会影响性能。

public static void main(String[] args) {
    long start = System.nanoTime();
    Long sum = 0L; // Long 类型:会频繁装箱拆箱

    for (long i = 0; i < 1_000_000; i++) {
        sum += i;
    }
    long end = System.nanoTime();
    System.out.println("耗时: " + (end - start) / 1e6 + " ms");
}

优化建议: 使用基本类型:

long sum = 0L; // 更快更轻

13.9 总结对比

特性自动装箱自动拆箱
转换方向基本类型 ➜ 包装类对象包装类对象 ➜ 基本类型
原理方法valueOf()xxxValue()(如 intValue)
应用场景集合、泛型、方法参数运算表达式、返回值
可能问题创建过多对象,影响性能空对象拆箱抛出 NullPointerException
缓存机制有(Integer 等)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值