Python数据结构 - 从Java集合到Python容器
1. Python的主要数据结构概览
作为Java开发者,您已经熟悉了ArrayList、HashMap等集合类。Python也有类似的数据结构,但更加简洁和灵活。
Python数据结构关系图
graph TD
A[Python数据结构] --> B[可变数据结构]
A --> C[不可变数据结构]
B --> D[列表 List]
B --> E[字典 Dictionary]
B --> F[集合 Set]
C --> G[元组 Tuple]
C --> H[冻结集合 Frozenset]
D --> I[有序]
D --> J[可索引]
D --> K[可重复元素]
E --> L[键值对]
E --> M[无序]
E --> N[键唯一]
F --> O[无序]
F --> P[唯一元素]
F --> Q[可进行集合运算]
G --> R[有序]
G --> S[可索引]
G --> T[可重复元素]
G --> U[不可修改]
H --> V[唯一元素]
H --> W[不可修改]
H --> X[可作为字典键或集合元素]
style A fill:#f9f,stroke:#333,stroke-width:2px
style B fill:#bbf,stroke:#333,stroke-width:2px
style C fill:#dfd,stroke:#333,stroke-width:2px
style D fill:#fdd,stroke:#333,stroke-width:2px
style E fill:#ddf,stroke:#333,stroke-width:2px
style F fill:#ffd,stroke:#333,stroke-width:2px
style G fill:#dff,stroke:#333,stroke-width:2px
style H fill:#fdf,stroke:#333,stroke-width:2px
2. 列表(List) - Python的"ArrayList"
列表是Python中最常用的数据结构,类似于Java的ArrayList。
创建列表
# 创建空列表
empty_list = []
# 创建带初始值的列表
numbers = [1, 2, 3, 4, 5]
mixed = [1, "Hello", 3.14, True]
列表操作
fruits = ["apple", "banana", "cherry"]
# 访问元素
print(fruits[0]) # 输出: apple
# 修改元素
fruits[1] = "blueberry"
print(fruits) # 输出: ['apple', 'blueberry', 'cherry']
# 添加元素
fruits.append("orange") # 在末尾添加
fruits.insert(1, "mango") # 在指定位置插入
print(fruits) # 输出: ['apple', 'mango', 'blueberry', 'cherry', 'orange']
# 删除元素
fruits.remove("cherry") # 删除指定元素
popped = fruits.pop() # 删除并返回最后一个元素
del fruits[0] # 删除指定位置的元素
print(fruits) # 输出: ['mango', 'blueberry']
# 列表长度
print(len(fruits)) # 输出: 2
# 检查元素是否存在
print("mango" in fruits) # 输出: True
列表切片
Python的切片操作非常强大,没有直接的Java等价物:
numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# 基本切片: [start:end] (不包括end)
print(numbers[2:5]) # 输出: [2, 3, 4]
# 省略起始索引,默认为0
print(numbers[:5]) # 输出: [0, 1, 2, 3, 4]
# 省略结束索引,默认到列表末尾
print(numbers[5:]) # 输出: [5, 6, 7, 8, 9]
# 负索引表示从末尾开始计数
print(numbers[-3:]) # 输出: [7, 8, 9]
# 步长切片: [start:end:step]
print(numbers[::2]) # 输出: [0, 2, 4, 6, 8]
print(numbers[1::2]) # 输出: [1, 3, 5, 7, 9]
# 负步长可以反转列表
print(numbers[::-1]) # 输出: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
列表推导式
列表推导式是Python的一个强大特性,可以简洁地创建新列表:
# 创建平方数列表
squares = [x**2 for x in range(10)]
print(squares) # 输出: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
# 带条件的列表推导式
even_squares = [x**2 for x in range(10) if x % 2 == 0]
print(even_squares) # 输出: [0, 4, 16, 36, 64]
# Java等价写法
/*
List<Integer> squares = new ArrayList<>();
for (int i = 0; i < 10; i++) {
squares.add(i * i);
}
*/
3. 元组(Tuple) - 不可变列表
元组类似于列表,但是不可修改(immutable)。Java中没有直接等价物,最接近的可能是使用final的数组或List。
# 创建元组
coordinates = (10, 20)
person = ("John", 30, "New York")
# 访问元素
print(coordinates[0]) # 输出: 10
print(person[1]) # 输出: 30
# 尝试修改会引发错误
# coordinates[0] = 15 # TypeError: 'tuple' object does not support item assignment
# 单元素元组需要逗号
singleton = (1,) # 这是一个元组
not_tuple = (1) # 这只是一个被括号包围的整数
# 元组解包
name, age, city = person
print(name) # 输出: John
print(city) # 输出: New York
# 交换变量值
a, b = 1, 2
a, b = b, a # 现在a=2, b=1
4. 字典(Dictionary) - Python的"HashMap"
字典类似于Java的HashMap,存储键值对。
# 创建字典
empty_dict = {}
user = {
"name": "John",
"age": 30,
"city": "New York"
}
# 访问值
print(user["name"]) # 输出: John
# 修改值
user["age"] = 31
print(user) # 输出: {'name': 'John', 'age': 31, 'city': 'New York'}
# 添加新键值对
user["email"] = "john@example.com"
print(user) # 输出: {'name': 'John', 'age': 31, 'city': 'New York', 'email': 'john@example.com'}
# 删除键值对
del user["city"]
email = user.pop("email") # 删除并返回值
print(user) # 输出: {'name': 'John', 'age': 31}
# 检查键是否存在
print("name" in user) # 输出: True
print("city" in user) # 输出: False
# 获取所有键和值
print(user.keys()) # 输出: dict_keys(['name', 'age'])
print(user.values()) # 输出: dict_values(['John', 31])
print(user.items()) # 输出: dict_items([('name', 'John'), ('age', 31)])
# 安全获取值(不存在时返回默认值)
print(user.get("city", "Unknown")) # 输出: Unknown
字典推导式
# 创建平方映射字典
squares = {x: x**2 for x in range(6)}
print(squares) # 输出: {0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
# 反转键值对
inverted = {v: k for k, v in squares.items()}
print(inverted) # 输出: {0: 0, 1: 1, 4: 2, 9: 3, 16: 4, 25: 5}
5. 集合(Set) - Python的"HashSet"
集合是无序的、不重复元素的集合,类似于Java的HashSet。
# 创建集合
empty_set = set() # 注意:{}创建的是空字典,不是空集合
fruits = {"apple", "banana", "cherry"}
# 添加元素
fruits.add("orange")
fruits.add("apple") # 重复元素不会被添加
print(fruits) # 输出: {'orange', 'banana', 'cherry', 'apple'}
# 删除元素
fruits.remove("banana") # 如果元素不存在,会引发KeyError
fruits.discard("mango") # 如果元素不存在,不会引发错误
print(fruits) # 输出: {'orange', 'cherry', 'apple'}
# 集合操作
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}
# 并集
print(set1 | set2) # 输出: {1, 2, 3, 4, 5, 6, 7, 8}
print(set1.union(set2)) # 同上
# 交集
print(set1 & set2) # 输出: {4, 5}
print(set1.intersection(set2)) # 同上
# 差集
print(set1 - set2) # 输出: {1, 2, 3}
print(set1.difference(set2)) # 同上
# 对称差集(在一个集合中但不在两个集合中)
print(set1 ^ set2) # 输出: {1, 2, 3, 6, 7, 8}
print(set1.symmetric_difference(set2)) # 同上
# 检查子集和超集
set3 = {4, 5}
print(set3.issubset(set1)) # 输出: True
print(set1.issuperset(set3)) # 输出: True
6. Java集合与Python数据结构对比
| Java | Python | 主要区别 |
|---|---|---|
| ArrayList | List | Python列表更灵活,可以存储不同类型的元素 |
| LinkedList | collections.deque | Python没有内置的链表,但deque提供类似功能 |
| HashMap | Dictionary | Python字典的键可以是任何不可变类型 |
| HashSet | Set | 功能基本相同 |
| TreeMap | collections.OrderedDict | Python 3.7+的字典默认保持插入顺序 |
| Arrays | List/Tuple | Python没有固定大小的数组 |
7. 练习:数据结构转换
将以下Java代码转换为Python:
import java.util.*;
public class StudentManager {
public static void main(String[] args) {
// 创建学生列表
List<String> students = new ArrayList<>();
students.add("Alice");
students.add("Bob");
students.add("Charlie");
// 创建成绩映射
Map<String, Integer> scores = new HashMap<>();
scores.put("Alice", 95);
scores.put("Bob", 85);
scores.put("Charlie", 90);
// 打印所有学生的成绩
for (String student : students) {
System.out.println(student + ": " + scores.get(student));
}
// 计算平均分
int sum = 0;
for (Integer score : scores.values()) {
sum += score;
}
double average = (double) sum / scores.size();
System.out.println("Average score: " + average);
}
}
Python解决方案:
def main():
# 创建学生列表
students = ["Alice", "Bob", "Charlie"]
# 创建成绩映射
scores = {
"Alice": 95,
"Bob": 85,
"Charlie": 90
}
# 打印所有学生的成绩
for student in students:
print(f"{student}: {scores[student]}")
# 计算平均分
average = sum(scores.values()) / len(scores)
print(f"Average score: {average}")
if __name__ == "__main__":
main()
8. 今日总结
- Python的列表(List)类似于Java的ArrayList,但更灵活
- 元组(Tuple)是不可变的列表,适合表示固定结构的数据
- 字典(Dictionary)类似于Java的HashMap,但键可以是任何不可变类型
- 集合(Set)类似于Java的HashSet,用于存储唯一元素
- Python的列表切片和推导式是非常强大的特性,没有直接的Java等价物
9. 明日预告
明天我们将学习Python的控制流和函数,包括条件语句、循环、函数定义和Lambda表达式,以及它们与Java的对比。