Java-集合与泛型:List、Set、Map及其实现类
一、包装类(Wrapper Classes)
集合(如ArrayList)只能存储对象,不能存储基本类型(如int)。
包装类就是为每个基本类型提供的对应引用类型,实现“基本类型 <-> 对象”的转换。
| 基本类型 | 包装类 |
| int | Integer |
| double | Double |
| char | Character |
| boolean | Boolean |
-
装箱(Boxing):将基本类型转换为包装类对象。例如:
Integer i = Integer.valueOf(10); -
拆箱(Unboxing):将包装类对象转换为基本类型。例如:
int num = i.intValue(); -
自动装箱/拆箱(Auto-boxing/Unboxing):Java 5+ 开始支持直接赋值,编译器会自动转换。例如:
Integer i = 10;和int num = i;
public class WrapperDemo { public static void main(String[] args) { // 1. 手动装箱和拆箱 Integer numObj = Integer.valueOf(100); // 装箱 int num = numObj.intValue(); // 拆箱 // 2. 自动装箱和拆箱 Integer autoBox = 200; // 自动装箱:int -> Integer int autoUnbox = autoBox; // 自动拆箱:Integer -> int // 3. 字符串与基本类型的转换 // parseInt()将字符串解析为基本类型 int parsedInt = Integer.parseInt("123"); // 字符串 -> int double parsedDouble = Double.parseDouble("3.14"); // toString():将包装类对象转为字符串 String str = Integer.toString(456); // int -> 字符串 // 4. 常量,MAX_VALUE获取该类型的最大值 System.out.println("int最大值:" + Integer.MAX_VALUE); } }
二、集合框架(Collection Framework)
集合用于保存数量不确定或具有映射关系的对象,包括Collection 接口(单列集合)、Map 接口(双列集合,键值对);
主要用于替代传统的数组,解决数组长度固定、无法保存复杂映射关系等局限性。
|
Collection 接口(单列集合、每个元素是1个对象)
|
Map 接口(双列集合,键值对保存对象)
实现原理介绍:哈希表是一个封装好的工具,是实现键值对操作的核心。
|
List 接口(最常用)核心操作: 添加、获取、删除、修改、遍历。 ArrayList:适合多读、插入删除少的场景。 LinkedList:适合频繁进行头部/中间插入删除。 import java.util.ArrayList; import java.util.Iterator; public class ListDemo { public static void main(String[] args) { // 使用泛型指定只能存储 String 类型 ArrayList<String> list = new ArrayList<>(); // 1. 添加元素 list.add("Java"); list.add("Python"); list.add(1, "C++"); // 在索引1处插入 // 2. 获取和修改 String lang = list.get(0); // 获取索引0的元素 list.set(2, "Go"); // 将索引2的元素改为"Go" // 3. 删除 list.remove("Python"); // 删除指定元素(第一个匹配的) // list.remove(1); // 删除索引1的元素 // 4. 遍历方式(三种) // 方式一:for-each(最简洁,不能删除元素) for (String s : list) { System.out.println(s); } // 方式二:迭代器(可以安全删除) Iterator<String> it = list.iterator(); // hasNext()判断是否有下一个元素 while (it.hasNext()) { String s = it.next(); //next()获取下一个元素 if (s.equals("Go")) { it.remove(); // 安全删除 } } // 方式三:普通for(带索引,只适用于List) for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } } } |
Map 接口(键值对)核心操作: 存(put)、取(get)、删(remove)、遍历键/值/键值对。 import java.util.HashMap; import java.util.Map; import java.util.Set; public class MapDemo { public static void main(String[] args) { HashMap<String, Integer> scores = new HashMap<>(); // 1. 添加键值对 scores.put("Alice", 90); scores.put("Bob", 85); scores.put("Alice", 95); // 键相同,新值覆盖旧值 // 2. 获取值 int aliceScore = scores.get("Alice"); // 95 Integer bobScore = scores.get("Bob"); // 85 // 3. 检查键是否存在 if (scores.containsKey("Alice")) { System.out.println("Alice exists"); } // 4. 遍历方式 // 遍历所有键 for (String key : scores.keySet()) { System.out.println(key + " -> " + scores.get(key)); } // 遍历所有键值对(推荐) for (Map.Entry<String, Integer> entry : scores.entrySet()) { System.out.println(entry.getKey() + " : " + entry.getValue()); } } }
|
Set 接口(保证元素唯一)核心: 存入
import java.util.HashSet; public class SetDemo { public static void main(String[] args) { HashSet<String> set = new HashSet<>(); set.add("apple"); set.add("banana"); set.add("apple"); // 重复元素,不会被加入 System.out.println(set.size()); // 输出 2 for (String s : set) { System.out.println(s); // 输出顺序可能是 banana, apple(无序) } } } |
三、泛型(Generic)
泛型用来限制类、接口、方法中能够操作的数据类型(保证类型转换的绝对安全)
- 类型擦除:泛型信息在编译后会被移除,运行时
List<String>和List<Integer>是同一类型。
T、定义时用的类型参数:
- 泛型类:class Box<T> { private T item; ... }
- 泛型方法:public <T> void print(T t) { ... }
?、通配符、使用时用的未知类型:
- <?>:未知类型(只能读,不能写),不关心具体类型
- 上界通配符:<? extends T>:T或T的子类,能读为T,但不确定具体子类型,所以不能写。
- 应用场景:取数据场景(比如遍历、复制)。
- 下界通配符:<? super T>:T或T的父类。能写T及其子类,但不确定具体父类型,所以只能读为Object。
- 应用场景:存数据场景(比如添加、填充)。
|
无边界通配符
|
// 无边界通配符:可以接收任何类型的 List
public static void printList(List<?> list) {
// 1. 可以读取,但只能赋值给 Object
for (Object obj : list) {
System.out.print(obj + " ");
}
System.out.println();
// 2. 不能写入(除 null 外)
// list.add("hello"); // 编译错误
// list.add(123); // 编译错误
// list.add(new Object()); // 编译错误
list.add(null); // 只能添加 null
}
|
List<?>:未知类型 1、不能写: 如果是List<Dog>,添加Cat对象是非法的 2、可以读: 只能赋值给 Object
|
| 上界通配符 |
// 上界通配符:可以接收 Animal或其子类的 List
public static void print(List<? extends Animal> list) {
// 1. 可以读:读取的元素可以赋值给 Animal
for (Animal animal : list) {
System.out.println(animal.getName());
}
// 2. 不能写:不能添加元素(null 除外)
// list.add(new Cat("小白")); // 编译错误!
// list.add(new Animal("动物")); // 编译错误!
list.add(null); // 只能添加 null
}
|
List<? extends Animal>: 可能类型: 1、不能写:如果是 List<Dog>,添加Cat对象是非法的 ---编译器为了绝对的类型安全,必须假设最坏的情况 2、可以读:取出的元素都一定是 Animal 或其子类的对象 Animal a = list.get(0); // 完全安全!
|
下界通配符 |
// 下界通配符:可以接收 Cat 或其父类的 List
public static void addCat(List<? super Cat> list) {
// 1. 可以写:添加 Cat 或其子类对象
list.add(new Cat("小白"));
// list.add(new Dog("小黑"));
|
List<? super Cat>:Cat的某个未知父类型列表 可能类型: 1、可以写:添加任意的子类型都能向上转型为对应父类型, 2、不能读:编译器无法确定读取到的具体类型,只能是Object |
本文来自博客园,作者:Fēngwèi,转载请注明原文链接:https://www.cnblogs.com/fengwei-blogs/p/22301764

浙公网安备 33010602011771号