从 TypeScript 到 Java(7):泛型与集合框架 —类型安全的数据结构设计
从 TypeScript 到 Java(7):泛型与集合框架 — 类型安全的数据结构设计
系列导读:
TypeScript 的泛型让我们习惯了灵活的Array<T>、Map<K,V>;
而 Java 的泛型与集合框架,则是以“类型安全 + 性能稳定”为核心设计的。这篇文章将帮你理解:为什么 Java 的集合看似复杂,却能支撑大型系统的稳定性。
☕ 一句话理解
Java 的泛型体系,是一种 编译期类型保护机制。
它不影响运行性能,却在编译阶段就能防止类型混乱。
配合集合框架(Collections Framework),
让数据的存储、遍历、查找、转换都有了标准化的方式。
🧱 泛型(Generics)的出现:从 Object 到类型安全
在早期 Java(1.5 之前),集合都是这样的:
List list = new ArrayList();
list.add("hello");
list.add(123); // 合法,但潜藏问题
String s = (String) list.get(1); // 运行时才报错
❌ 问题:类型不安全。任何对象都能放入集合。
从 Java 5 开始,引入泛型:
List<String> list = new ArrayList<>();
list.add("hello");
// list.add(123); // 编译时报错
✅ 编译期就能检查类型,运行时更安全。
🧩 泛型的基本语法
class Box<T> {
private T value;
public void set(T value) { this.value = value; }
public T get() { return value; }
}
使用:
Box<Integer> box = new Box<>();
box.set(100);
System.out.println(box.get());
📘 关键点:
T是“类型参数”,在使用时指定;- 泛型只在编译期存在,运行时会被擦除(称为“类型擦除”);
- 因此不能直接写:
new T()或T.class。
🧠 类型擦除(Type Erasure)
Java 的泛型不会在运行时保留类型信息:
List<String> a = new ArrayList<>();
List<Integer> b = new ArrayList<>();
System.out.println(a.getClass() == b.getClass()); // true
输出:
true
这是因为 JVM 不区分泛型类型,泛型仅是编译器的语法糖。
运行时,所有泛型信息都被擦除成Object。
与 TypeScript 对比:
- TypeScript 的泛型是 编译时约束;
- 编译为 JS 后,同样会被擦除;
- 因此两者在这点上非常相似。
📦 Java 集合框架(Collections Framework)
Java 提供了一整套接口 + 实现类结构:
Collection
├── List
│ ├── ArrayList
│ ├── LinkedList
│ └── Vector
├── Set
│ ├── HashSet
│ ├── TreeSet
│ └── LinkedHashSet
└── Queue
├── PriorityQueue
└── ArrayDeque
Map
├── HashMap
├── TreeMap
└── LinkedHashMap
🎫 List:有序集合(类似 TypeScript Array)
List<String> fruits = new ArrayList<>();
fruits.add("apple");
fruits.add("banana");
fruits.add("cherry");
for (String f : fruits) {
System.out.println(f);
}
输出:
apple
banana
cherry
特点:
-
保持插入顺序;
-
可通过索引访问;
-
常见实现:
ArrayList:基于动态数组;LinkedList:基于双向链表。
🧩 Set:不重复集合(类似 TypeScript Set)
Set<String> names = new HashSet<>();
names.add("Tom");
names.add("Jerry");
names.add("Tom"); // 自动去重
System.out.println(names);
输出:
[Jerry, Tom]
特点:
- 无序;
- 不允许重复;
- 底层使用哈希结构;
- 若要排序,可用
TreeSet。
⚙️ Map:键值对(类似 TypeScript Map)
Map<String, Integer> ages = new HashMap<>();
ages.put("Alice", 20);
ages.put("Bob", 25);
System.out.println(ages.get("Bob"));
输出:
25
常见实现:
| 类名 | 特点 |
|---|---|
HashMap |
无序,性能高 |
LinkedHashMap |
保留插入顺序 |
TreeMap |
按键排序 |
💡 Java 没有字面量对象
{},一切键值结构都来自Map。
🧭 遍历方式汇总
1. For-each
for (String f : fruits) {
System.out.println(f);
}
2. Iterator(手动控制)
Iterator<String> it = fruits.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
3. Stream(函数式风格)
fruits.stream()
.filter(f -> f.startsWith("b"))
.forEach(System.out::println);
输出:
banana
Stream 是 Java 8 引入的“声明式数据处理”方案,
类似 TypeScript 的array.filter().map().forEach()。
🧮 TypeScript 对比表
| 功能 | TypeScript | Java |
|---|---|---|
| 动态数组 | Array<T> |
ArrayList<T> |
| 键值集合 | Map<K,V> |
HashMap<K,V> |
| 去重集合 | Set<T> |
HashSet<T> |
| 过滤映射 | .filter() .map() |
.stream().filter().map() |
| 类型检查 | 编译期(宽松) | 编译期(严格) |
| 执行期类型 | 保留 | 被擦除 |
⚖️ 工程哲学
- TypeScript 的集合更轻量、灵活;
- Java 的集合体系更规范、强类型、可扩展;
- 泛型与集合结合后,使大型项目的结构稳定且可维护;
- Stream API 让 Java 逐渐具备了“函数式”的表达力。
总结:
TypeScript 更像“前端的便利贴”;
Java 集合则是“后端的地基钢筋”。
🚀 实战建议
-
使用
Map<String, List<String>>构建一个 “学生-课程” 对照表; -
使用
stream()过滤出学习 “Java” 的学生; -
尝试封装成一个泛型方法:
public static <T> List<T> filter(List<T> list, Predicate<T> predicate)模仿 TypeScript 的
array.filter()。
🔮 下一篇预告
第 8 篇:《异常处理与错误机制 —— 让程序稳定地失败》
我们将深入:
try...catch...finallythrows与throw- 自定义异常类
- 以及 Java 异常体系的设计哲学
(Checked vs Unchecked)
更多推荐



所有评论(0)