02-Java工程师的Python第二课-数据结构对比

0 阅读4分钟

Java集合框架 vs Python数据结构:一张表格搞定转换

摘要:Java有ArrayList、HashMap、HashSet,Python有list、dict、set。看似相似的数据结构,API设计却大相径庭。


写在前面

Java的标准集合框架设计精巧但略显复杂,需要区分List/Set/Map三大接口,每种又有多种实现。Python的设计思路完全不同——简单、直观。

对Java工程师来说,最大的挑战不是"怎么用",而是"忘掉Java的习惯"。


一、整体对比一览

JavaPython说明
List<T>list有序可重复
Set<T>set无序不重复
Map<K,V>dict键值对
Queuequeue/collections.deque队列
Stacklist栈(用append/pop)
LinkedList<T>collections.deque双端队列

二、List列表对比

2.1 创建与初始化

// Java
List<String> list = new ArrayList<>();
list.add("apple");
list.add("banana");
List<Integer> nums = Arrays.asList(1, 2, 3);
# Python
lst = []
lst = list()
lst = ["apple", "banana"]
nums = [1, 2, 3]
nums = list(range(5))  # [0, 1, 2, 3, 4]

2.2 常用操作对比

操作JavaPython
添加元素list.add(item)list.append(item) / list.insert(i, item)
获取元素list.get(i)list[i]
设置元素list.set(i, item)list[i] = item
删除元素list.remove(i)list.remove(obj)del list[i] / list.remove(obj)
切片无直接对应list[start:stop:step]
长度list.size()len(list)
遍历for (String item : list)for item in list:
索引list.indexOf(item)list.index(item)
包含检查list.contains(item)item in list
排序Collections.sort(list)list.sort()sorted(list)
反转Collections.reverse(list)list.reverse()
清空list.clear()list.clear()

2.3 切片操作(Python独有)

lst = [0, 1, 2, 3, 4, 5]

lst[1:4]    # [1, 2, 3] - 切片
lst[::2]    # [0, 2, 4] - 步长为2
lst[::-1]   # [5, 4, 3, 2, 1, 0] - 反转
lst[2:]     # [2, 3, 4, 5] - 从索引2到最后
lst[:3]     # [0, 1, 2] - 从开头到索引3(不包含)

2.4 列表推导式(Python特色)

# Java 8之前的写法
List<Integer> squares = new ArrayList<>();
for (int i = 0; i < 10; i++) {
    squares.add(i * i);
}

// Java 8之后的写法
List<Integer> squares = IntStream.range(0, 10)
    .map(i -> i * i)
    .collect(Collectors.toList());
# Python一行搞定
squares = [i * i for i in range(10)]

# 带条件过滤
evens = [i for i in range(10) if i % 2 == 0]

# 多层循环
pairs = [(x, y) for x in range(3) for y in range(3)]

三、Map字典对比

3.1 创建与初始化

// Java
Map<String, Integer> map = new HashMap<>();
map.put("apple", 1);
map.put("banana", 2);

// Java 9+ 可以用简洁写法
Map<String, Integer> map = Map.of("apple", 1, "banana", 2);
# Python
d = {}
d = dict()
d = {"apple": 1, "banana": 2}

# fromkeys - 快速创建默认值字典
d = dict.fromkeys(["a", "b", "c"], 0)

# dict with comprehension
d = {k: v for k, v in [("apple", 1), ("banana", 2)]}

3.2 常用操作对比

操作JavaPython
添加/更新map.put(k, v)map[k] = vmap.update({k: v})
获取值map.get(k)map[k](键不存在会抛异常)或 map.get(k, default)
获取值(安全)map.getOrDefault(k, default)map.get(k, default)
删除map.remove(k)del map[k]map.pop(k)
检查键map.containsKey(k)k in map
检查值map.containsValue(v)v in map.values()
遍历键map.keySet()for k in map:
遍历值map.values()for v in map.values():
遍历键值对map.entrySet()for k, v in map.items():
长度map.size()len(map)
清空map.clear()map.clear()

3.3 遍历对比

// Java
for (Map.Entry<String, Integer> entry : map.entrySet()) {
    System.out.println(entry.getKey() + " = " + entry.getValue());
}

// Java 8+ lambda
map.forEach((k, v) -> System.out.println(k + " = " + v));
# Python - 更简洁
for k, v in map.items():
    print(f"{k} = {v}")

# dict comprehension
squares = {x: x*x for x in range(5)}

四、Set集合对比

4.1 创建与初始化

// Java
Set<String> set = new HashSet<>();
set.add("apple");
set.add("banana");
# Python
s = set()
s = {"apple", "banana"}  # 注意:空{}是dict不是set
s = set(["apple", "banana"])

4.2 常用操作对比

操作JavaPython
添加set.add(item)set.add(item)
删除set.remove(item)(不存在抛异常)set.remove(item)(不存在抛异常)或 set.discard(item)
交集set1.retainAll(set2)set1 & set2set1.intersection(set2)
并集set1.addAll(set2)set1 | set2set1.union(set2)
差集set1.removeAll(set2)set1 - set2set1.difference(set2)
包含set.contains(item)item in set
子集set1.containsAll(set2)set1 <= set2set1.issubset(set2)
超集set1.containsAll(set2)set1 >= set2set1.issuperset(set2)

五、Queue队列对比

5.1 Java的Queue体系

// Java - 接口明确,实现多样
Queue<String> queue = new LinkedList<>();
queue.offer("first");  // 添加
String head = queue.poll();  // 取出并移除

// PriorityQueue - 优先队列
Queue<Integer> pq = new PriorityQueue<>(Comparator.reverseOrder());

5.2 Python的队列

# Python - 用法更直接
from collections import deque

queue = deque()
queue.append("first")  # 入队
queue.append("second")
head = queue.popleft()  # 出队(从左边)

# deque作为栈也很方便
stack = deque()
stack.append("a")
stack.append("b")
top = stack.pop()  # "b"

5.3 队列操作对比

操作JavaPython
入队queue.offer(item)queue.append(item)
出队queue.poll()queue.popleft()
查看队首queue.peek()queue[0]
长度queue.size()len(queue)
是否为空queue.isEmpty()not queue

六、实战对比

6.1 词频统计

// Java
public Map<String, Integer> wordCount(List<String> words) {
    Map<String, Integer> counts = new HashMap<>();
    for (String word : words) {
        counts.merge(word, 1, Integer::sum);
    }
    return counts;
}
# Python - 简洁到极致
from collections import Counter

def word_count(words):
    return Counter(words)

# 或者不用Counter
def word_count(words):
    counts = {}
    for word in words:
        counts[word] = counts.get(word, 0) + 1
    return counts

6.2 去重并保持顺序

// Java - 需要 LinkedHashSet
public <T> List<T> distinct(List<T> list) {
    return new ArrayList<>(new LinkedHashSet<>(list));
}
# Python - 简单直接
def distinct(lst):
    return list(dict.fromkeys(lst))

七、避坑指南

7.1 可变默认参数陷阱

# ❌ 错误写法
def add_item(item, result=[]):
    result.append(item)
    return result

print(add_item("a"))  # ['a']
print(add_item("b"))  # ['a', 'b'] - 预期外的结果!

# ✅ 正确写法
def add_item(item, result=None):
    if result is None:
        result = []
    result.append(item)
    return result
// Java不存在这个问题,因为参数是不可变的

7.2 引用传递注意事项

# Python的list/dict/set都是引用传递
original = [1, 2, 3]
copied = original  # 不是拷贝!
copied.append(4)
print(original)  # [1, 2, 3, 4] - original也被改了

# 正确拷贝方式
shallow_copy = original.copy()
deep_copy = copy.deepcopy(original)

八、总结

场景Java写法Python写法
创建列表new ArrayList<>()[]list()
快速判断包含list.contains()item in list
字典遍历for (Map.Entry...)for k, v in dict.items()
集合交集set1.retainAll(set2)set1 & set2
过滤元素Stream APIlist comprehension
统计词频HashMap手动累加Counter

Python的数据结构设计追求"最简单的操作就用最简单的方式"。Java强调接口抽象和实现分离,Python强调直觉和简洁。