Map集合复习
掌握HashMap、TreeMap和LinkedHashMap的特点与使用场景
HashMap
- 基于哈希表实现
- 无序存储,不保证顺序
- 允许null键和null值
- 查找效率高:O(1)
TreeMap
- 基于红黑树实现
- 按键的自然顺序或Comparator排序
- 不允许null键
- 查找效率:O(log n)
LinkedHashMap
- 继承自HashMap
- 维护插入顺序或访问顺序
- 允许null键和null值
- 查找效率:O(1)
Map集合使用示例
import java.util.*;
public class MapExample {
public static void main(String[] args) {
// HashMap示例
Map
hashMap = new HashMap<>();
hashMap.put("Alice", 25);
hashMap.put("Bob", 30);
hashMap.put(null, 0); // 允许null键
System.out.println("HashMap: " + hashMap);
// TreeMap示例
Map
treeMap = new TreeMap<>();
treeMap.put("Charlie", 35);
treeMap.put("Alice", 25);
treeMap.put("Bob", 30);
// treeMap.put(null, 0); // 抛出NullPointerException
System.out.println("TreeMap (自然排序): " + treeMap);
// LinkedHashMap示例(插入顺序)
Map
linkedHashMap = new LinkedHashMap<>();
linkedHashMap.put("Bob", 30);
linkedHashMap.put("Alice", 25);
linkedHashMap.put("Charlie", 35);
System.out.println("LinkedHashMap (插入顺序): " + linkedHashMap);
}
}
常见错误
错误: 在TreeMap中使用不可比较的键
原因: 如果键没有实现Comparable接口且没有提供Comparator
解决: 确保键实现Comparable接口或提供Comparator
// 错误示例
Map
map = new TreeMap<>(); // Person未实现Comparable
// 正确解决方案1:实现Comparable
class Person implements Comparable
{
// 实现compareTo方法
}
// 正确解决方案2:提供Comparator
Map map = new TreeMap<>(Comparator.comparing(Person::getName));
Collections工具类
掌握集合排序、查找、同步等操作
常用Collections方法
方法 | 描述 | 示例 |
---|---|---|
sort() | 对List进行排序 | Collections.sort(list) |
binarySearch() | 二分查找已排序列表 | Collections.binarySearch(list, key) |
reverse() | 反转List中元素顺序 | Collections.reverse(list) |
shuffle() | 随机打乱List中元素 | Collections.shuffle(list) |
synchronizedXxx() | 创建同步集合 | Collections.synchronizedList(list) |
集合排序示例
import java.util.*;
public class CollectionsExample {
public static void main(String[] args) {
List
numbers = new ArrayList<>();
numbers.add(5);
numbers.add(2);
numbers.add(8);
numbers.add(1);
// 自然排序
Collections.sort(numbers);
System.out.println("自然排序: " + numbers);
// 自定义排序(降序)
Collections.sort(numbers, (a, b) -> b - a);
System.out.println("降序排序: " + numbers);
// 对象排序
List
people = new ArrayList<>();
people.add(new Person("Alice", 25));
people.add(new Person("Bob", 30));
people.add(new Person("Charlie", 22));
// 按年龄排序
Collections.sort(people, Comparator.comparingInt(Person::getAge));
System.out.println("按年龄排序: " + people);
// 按姓名排序
Collections.sort(people, Comparator.comparing(Person::getName));
System.out.println("按姓名排序: " + people);
}
static class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
@Override
public String toString() {
return name + "(" + age + ")";
}
}
}
File文件操作
掌握Java文件与目录操作的核心方法
File类核心方法
方法 | 描述 | 返回值 |
---|---|---|
exists() | 检查文件/目录是否存在 | boolean |
isFile() | 检查是否为文件 | boolean |
isDirectory() | 检查是否为目录 | boolean |
length() | 获取文件大小(字节) | long |
mkdir() | 创建单级目录 | boolean |
mkdirs() | 创建多级目录 | boolean |
listFiles() | 获取目录内容 | File[] |
delete() | 删除文件或目录 | boolean |
文件操作示例
import java.io.File;
import java.io.IOException;
public class FileExample {
public static void main(String[] args) {
// 创建File对象
File file = new File("test.txt");
// 检查文件是否存在
if (!file.exists()) {
try {
// 创建新文件
if (file.createNewFile()) {
System.out.println("文件创建成功: " + file.getName());
}
} catch (IOException e) {
System.err.println("创建文件失败: " + e.getMessage());
}
}
// 获取文件信息
System.out.println("文件路径: " + file.getAbsolutePath());
System.out.println("文件大小: " + file.length() + " bytes");
System.out.println("是否可读: " + file.canRead());
System.out.println("是否可写: " + file.canWrite());
// 目录操作
File dir = new File("my_directory");
if (!dir.exists()) {
// 创建多级目录
if (dir.mkdirs()) {
System.out.println("目录创建成功: " + dir.getName());
}
}
// 列出目录内容
if (dir.isDirectory()) {
System.out.println("目录内容:");
File[] files = dir.listFiles();
if (files != null) {
for (File f : files) {
System.out.println(f.getName() + (f.isDirectory() ? " [目录]" : " [文件]"));
}
}
}
// 删除文件
if (file.delete()) {
System.out.println("文件删除成功");
}
}
}
字节流与字符流
掌握InputStream/OutputStream和Reader/Writer的使用
字节流
- 操作原始字节数据
- 核心类:InputStream/OutputStream
- 适合处理二进制文件
- 实现类:FileInputStream, ByteArrayInputStream等
字符流
- 操作字符数据
- 核心类:Reader/Writer
- 自动处理字符编码
- 适合处理文本文件
文件复制示例
import java.io.*;
public class StreamExample {
// 使用字节流复制文件
public static void copyFileWithByteStream(String source, String dest) throws IOException {
try (InputStream in = new FileInputStream(source);
OutputStream out = new FileOutputStream(dest)) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
}
}
// 使用字符流复制文本文件
public static void copyTextFileWithCharStream(String source, String dest) throws IOException {
try (Reader reader = new FileReader(source);
Writer writer = new FileWriter(dest)) {
char[] buffer = new char[4096];
int charsRead;
while ((charsRead = reader.read(buffer)) != -1) {
writer.write(buffer, 0, charsRead);
}
}
}
public static void main(String[] args) {
try {
// 复制二进制文件(如图片)
copyFileWithByteStream("source.jpg", "copy_byte.jpg");
// 复制文本文件
copyTextFileWithCharStream("source.txt", "copy_char.txt");
System.out.println("文件复制成功");
} catch (IOException e) {
System.err.println("文件复制失败: " + e.getMessage());
}
}
}
缓冲流、转换流、打印流
掌握高级I/O流的使用与组合
缓冲流
- 提高I/O效率
- BufferedInputStream/BufferedOutputStream
- BufferedReader/BufferedWriter
- 特有方法:readLine(), newLine()
转换流
- 字节流与字符流的桥梁
- InputStreamReader/OutputStreamWriter
- 处理字符编码转换
打印流
- 提供格式化输出
- PrintStream/PrintWriter
- 自动调用toString()
- 不会抛出I/O异常
高级流组合示例
import java.io.*;
import java.nio.charset.StandardCharsets;
public class AdvancedStreamExample {
public static void main(String[] args) {
// 读取UTF-8编码文件(使用缓冲和转换流)
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(
new FileInputStream("utf8_file.txt"),
StandardCharsets.UTF_8))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
// 写入格式化数据(使用缓冲和打印流)
try (PrintWriter writer = new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream("output.txt"),
StandardCharsets.UTF_8)))) {
writer.println("===== 数据报告 =====");
writer.printf("时间: %tF %n", System.currentTimeMillis());
writer.printf("系统用户: %s %n", System.getProperty("user.name"));
writer.printf("内存使用: %.2f MB %n",
Runtime.getRuntime().totalMemory() / (1024.0 * 1024));
// 检查错误
if (writer.checkError()) {
System.err.println("写入过程中发生错误");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
对象序列化与反序列化
掌握Java对象持久化技术
序列化核心概念
- Serializable接口:标记接口,表示可序列化
- transient关键字:标记不序列化的字段
- serialVersionUID:版本控制标识
- ObjectOutputStream:序列化对象
- ObjectInputStream:反序列化对象
序列化示例
import java.io.*;
public class SerializationExample {
public static void main(String[] args) {
// 创建可序列化对象
Person person = new Person("Alice", 30, "alice@example.com");
// 序列化对象到文件
try (ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("person.ser"))) {
oos.writeObject(person);
System.out.println("对象序列化成功");
} catch (IOException e) {
e.printStackTrace();
}
// 从文件反序列化对象
try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("person.ser"))) {
Person deserializedPerson = (Person) ois.readObject();
System.out.println("反序列化对象: " + deserializedPerson);
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
static class Person implements Serializable {
// 显式声明serialVersionUID
private static final long serialVersionUID = 1L;
private String name;
private int age;
private transient String email; // 不序列化
public Person(String name, int age, String email) {
this.name = name;
this.age = age;
this.email = email;
}
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age +
", email='" + (email != null ? email : "null") + "'}";
}
}
}
序列化常见错误
错误1: 序列化非Serializable对象
解决: 确保所有序列化对象实现Serializable接口
错误2: serialVersionUID不匹配
解决: 显式声明serialVersionUID保持版本一致
错误3: 序列化后修改类结构
解决: 避免修改已序列化类的结构,或使用兼容性策略
综合测试题
检验Java第二阶段知识掌握情况
题目1:Map集合应用
编写一个程序,统计一段文本中每个单词出现的次数,并按出现次数从高到低排序输出。
要求:
- 使用HashMap存储单词和出现次数
- 使用Collections.sort进行排序
- 忽略大小写(将所有单词转为小写)
- 过滤掉标点符号
题目2:文件操作与I/O流
实现一个文件加密工具,要求:
- 使用字节流读取文件
- 使用简单的异或加密算法(每个字节与密钥异或)
- 使用缓冲流提高性能
- 提供加密和解密功能
- 支持大文件处理(分块处理)
题目3:对象序列化应用
设计一个学生管理系统,要求:
- 定义Student类(包含学号、姓名、成绩)
- 实现Serializable接口
- 提供添加、删除、查询学生功能
- 将学生列表序列化保存到文件
- 程序启动时从文件加载学生数据
- 使用TreeMap按学号排序存储学生
题目4:综合应用
实现一个日志分析工具:
- 从多个日志文件读取数据(不同编码格式)
- 使用转换流处理不同编码
- 提取包含"ERROR"的日志条目
- 按时间排序所有错误日志
- 将结果写入HTML格式的报告
- 使用PrintWriter生成格式化输出