1.分别持久化基本数据类型以及对象类型到本地文件
ID生成器
package com.sanqi;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
public class IdGenerator {
private static final String DATA_DIR = "current";
private static final String DATA_FILE = DATA_DIR+"/id_generator.dat";
private static final long DEFAULT_VALUE = 1L;
public static long getID() {
synchronized (IdGenerator.class) { // 添加同步锁
long id;
try {
ensureDirectoryExists();
File file = new File(DATA_FILE);
if (!file.exists() || file.length() == 0) {
// 第一次使用或文件为空
id=DEFAULT_VALUE;
write(id + 1);//写入下一个id
return DEFAULT_VALUE;
} else {
id = read(); // 读取当前ID值
write(id + 1); // 更新为下一个ID
return id;
}
} catch (IOException e) {
//Print relevant logs
return -1;
}
}
}
private static void ensureDirectoryExists() throws IOException {
Files.createDirectories(Paths.get(DATA_DIR));
}
private static long read() throws IOException {
long id;
try (DataInputStream dis = new DataInputStream(new FileInputStream(DATA_FILE))) {
id = dis.readLong();
}
return id;
}
private static void write(long id) throws IOException {
try (DataOutputStream dos =
new DataOutputStream(new FileOutputStream(DATA_FILE))) {
dos.writeLong(id);
}
}
}
对象持久化工具类
package com.sanqi;
import java.io.*;
public class ObjectPersistUtil {
private static final String DATA_FILE = "current/employee_data.dat";
public static int persist(Object instance) {
try (ObjectOutputStream oos =
new ObjectOutputStream(
new FileOutputStream(DATA_FILE))) {
oos.writeObject(instance);
return 1;
}catch (IOException e){
//Print relevant logs
}
return -1;
}
public static Employee read(){
Employee stu =null;
File file=new File(DATA_FILE);
if(!file.exists()){
return stu;
}
try (ObjectInputStream ois =
new ObjectInputStream(
new FileInputStream(file));) {
stu=(Employee) ois.readObject();
}catch (IOException |ClassNotFoundException e){
//Print relevant logs
}
return stu;
}
}
对象类
package com.sanqi;
import java.io.Serializable;
import java.time.LocalDate;
import java.util.Objects;
//需要实现Serialization接口
public class Employee implements Serializable {
private long id;
private String name;
private transient String phone;//transient表明不会被序列化
private char gender;
private LocalDate birth;
public long getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
public LocalDate getBirth() {
return birth;
}
public void setBirth(LocalDate birth) {
this.birth = birth;
}
public Employee() {
this.id=IdGenerator.getID();
}
public Employee(String name, String phone, char gender, LocalDate birth) {
this.name = name;
this.phone = phone;
this.gender = gender;
this.birth = birth;
this.id=IdGenerator.getID();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Employee employee = (Employee) o;
return id == employee.id && Objects.equals(name, employee.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
@Override
public String toString() {
final StringBuilder s = new StringBuilder("Employee{");
s.append("id=").append(id);
s.append(", name='").append(name).append(''');
s.append(", phone='").append(phone).append(''');
s.append(", gender=").append(gender);
s.append(", birth=").append(birth);
s.append('}');
return s.toString();
}
}
主方法
package com.sanqi;
import java.io.File;
import java.time.LocalDate;
public class Main {
public static void main(String[] args) {
// 先清理旧文件
cleanOldFiles();
System.out.println("=== 测试ID生成 ===");
for (int i = 0; i < 10; i++) {
long id=IdGenerator.getID();
System.out.println(id);
}
System.out.println("
=== 测试对象持久化 ===");
Employee s=new Employee("37方寸","12345678901",'男', LocalDate.of(2001,8,3));
System.out.println("原始对象: " + s);
//对象持久化
if(ObjectPersistUtil.persist(s)>0){
System.out.println("持久化成功");
}
Employee employee=ObjectPersistUtil.read();
System.out.println("读取到的信息"+employee);
}
private static void cleanOldFiles() {
new File("current/id_generator.dat").delete();
new File("current/employee_data.dat").delete();
System.out.println("已清理旧文件");
}
}
运行结果如下:

2.假定有一个巨大的文件,我们如何快速地读到此文件中的最后一行?
方法类
package com.sanqi;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.charset.StandardCharsets;
public class UseRandomAccessFile {
public String readLastLine(String path) {
try {
RandomAccessFile raf = new RandomAccessFile(new File(path), "r");
long len = raf.length();
if (len == 0) {
return "";
}
// 从最后一个字节开始往回遍历,寻找第一个换行符
long pos = len - 1;
raf.seek(pos);
while (pos > 0) {
pos--;
raf.seek(pos);
if (raf.readByte() == '
') {
break;
}
}
if (pos == 0) {
raf.seek(0);
}
byte[] bytes = new byte[(int) (len - pos)];
raf.read(bytes);
String line = new String(bytes, StandardCharsets.UTF_8);
// 移除末尾的
if (line.endsWith("
")) {
line = line.substring(0, line.length() - 1);
}
return line.trim();
} catch (IOException e) {
// Print logs
return null;
}
}
}
主方法
package com.sanqi;
public class Main {
public static void main(String[] args) {
UseRandomAccessFile reader = new UseRandomAccessFile();
String path = "D:桌面2025_11_02test.txt";
String lastLine = reader.readLastLine(path);
System.out.println("最后一行内容: " + lastLine);
}
}
运行结果如下:


3.实现二叉搜索树的增删改查
节点数据结构:
package com.sanqi;
import java.util.Objects;
public class Node<T extends Comparable<T> > {
private T data;
private Node<T> left;
private Node<T> right;
public Node(T data) {
this.data = data;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public Node<T> getLeft() {
return left;
}
public void setLeft(Node<T> left) {
this.left = left;
}
public Node<T> getRight() {
return right;
}
public void setRight(Node<T> right) {
this.right = right;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Node<?> node = (Node<?>) o;
return Objects.equals(data, node.data);
}
@Override
public int hashCode() {
return Objects.hash(data);
}
}
二叉搜索树的接口:
package com.sanqi;
public interface Tree<T extends Comparable<T>> {
void add(T data);
void remove(T element);
Node<T> findTargetNode(T element);
void preOrder();
void midOrder();
void postOrder();
int size();
}
二叉搜索树的实现类:
package com.sanqi;
public class BinarySearchTree<T extends Comparable<T>> implements Tree<T> {
private Node<T> root;
private int size;
@Override
public void add(T data) {
if (this.root == null) {
this.root = new Node<>(data);
this.size++;
return;
}
Node<T> parent = null;//我们要找的目标节点
Node<T> cur = this.root;//当前的节点,从跟开始找
while (cur != null) {
if (data.compareTo(cur.getData()) > 0) {
parent = cur;
cur = cur.getRight();
} else if (data.compareTo(cur.getData()) < 0) {
parent = cur;
cur = cur.getLeft();
} else {
//说明我们要添加的元素与已有的元素一样了,根据BST的规则,则此元素添加不进来
return;
}
}
//3.在第二步的基础上,决定存放在左边还是右边
if (data.compareTo(parent.getData()) > 0) {
parent.setRight(new Node<>(data));
} else {
parent.setLeft(new Node<>(data));
}
this.size++;
}
@Override
public void remove(T element) {
//获取当前元素所在的节点
Node<T>target=findTargetNode(element);
if(target==null){
System.out.println("没有找到" + element + "元素");
return;
}
//获取当前元素所在节点的父节点
Node<T>targetParent=findParentNode(element);
//获取当前元素的右孩子中,最小的节点
Node<T>minRight_of_target=findMinNodeFromRight(target);
//下面分四种情况讨论
//1.BST中只有一个根节点,并且此根节点就是我们要找的元素
if (this.root == target&& target.getLeft() == null && target.getRight() == null) {
this.root = null;
this.size--;
System.out.println("删除元素" + element + "成功");
}
//2.被删除元素在BST中是叶子节点
if (target.getLeft() == null && target.getRight() == null) {
if (targetParent.getLeft() == target) {
targetParent.setLeft(null);
} else {
targetParent.setRight(null);
}
this.size--;
System.out.println("删除元素" + element + "成功");
}
//3.被删除元素在BST中不是叶子节点,但是只有一个子节点,这个子节点可以是左孩子或是右孩子
//左孩子的情况
else if (target.getLeft() == null || target.getRight() == null) {
//将该节点的父节点指向该节点的子孩子
Node<T>child=target.getLeft()==null?target.getRight():target.getLeft();
if (targetParent!= null) {
if (targetParent.getLeft() == target) {
targetParent.setLeft(child);
} else {
targetParent.setRight(child);
}
}
else {//说明target是根节点
this.root=child;
}
this.size--;
System.out.println("删除元素" + element + "成功");
}
//4.被删除元素在BST中不是叶子节点,而且拥有左右子孩子。
else {
T temp=minRight_of_target.getData();
remove(minRight_of_target.getData());
target.setData(temp);
this.size--;
System.out.println("删除元素" + element + "成功");
}
}
/** 辅助方法一:查询元素,找到的话,返回元素所在的节点,如果找不到,则返回null*/
@Override
public Node<T> findTargetNode(T element) {
Node<T> cur = this.root;//当前的节点,从跟开始找
while (cur != null) {
if (element.compareTo(cur.getData()) > 0) {
//往右边去找
cur = cur.getRight();
} else if (element.compareTo(cur.getData()) < 0) {
//往左边去找
cur = cur.getLeft();
} else {
//查找成功
return cur;
}
}
return null;
}
/** 辅助方法二:查询元素,找到的话,返回元素所在的节点的父节点,如果找不到,则返回null*/
public Node<T> findParentNode(T target){
Node<T> parent = null;//当前的节点,从跟开始找
Node<T> cur = this.root;//当前的节点,从跟开始找
while (cur != null) {
if (target.compareTo(cur.getData()) > 0) {
//往右边去找
parent=cur;
cur = cur.getRight();
} else if (target.compareTo(cur.getData()) < 0) {
//往左边去找
parent=cur;
cur = cur.getLeft();
} else {
//查找成功
return parent;
}
}
return null;
}
/** 辅助方法三://从目标节点的右孩子中,找出最小的节点*/
public Node<T> findMinNodeFromRight(Node<T> target){
if(target!=null&&target.getRight()!=null) {
//定义目标节点的右孩子
Node<T> minright_of_target = target.getRight();
//从目标节点的右孩子中,找出最小的节点
while (minright_of_target.getLeft() != null) {
minright_of_target = minright_of_target.getLeft();
}
return minright_of_target;
}
return null;
}
/**前序遍历*/
@Override
public void preOrder() {
preOrder(this.root);
}
private void preOrder(Node<T> tree) {
if (tree == null) {
return;
}
System.out.println(tree.getData() + " ");
preOrder(tree.getLeft());
preOrder(tree.getRight());
}
/**中序遍历*/
@Override
public void midOrder() {
midOrder(this.root);
}
private void midOrder(Node<T> tree) {
if (tree == null) {
return;
}
midOrder(tree.getLeft());
System.out.println(tree.getData() + " ");
midOrder(tree.getRight());
}
/**后序遍历*/
@Override
public void postOrder() {
postOrder(this.root);
}
private void postOrder(Node<T> tree) {
if (tree == null) {
return;
}
postOrder(tree.getLeft());
postOrder(tree.getRight());
System.out.println(tree.getData() + " ");
}
/**返回树中结点的数量 */
@Override
public int size() {
return this.size;
}
}
模拟实体类
package com.sanqi;
import java.util.Objects;
public class Person implements Comparable<Person> {
private String name;
private int age;
private char sex;
private String phone;
private String address;
public Person(String name, int age, char sex, String phone, String address) {
this.name = name;
this.age = age;
this.sex = sex;
this.phone = phone;
this.address = address;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age && Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public int compareTo(Person other) {
//按照姓名和年龄进行比较,如年龄一样,就按姓名比较,如果都一样,则认为是“一样”的对象。
if(this.getAge()==other.getAge()){
return this.getName().compareTo(other.getName());
}else return this.getAge()-other.getAge();
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("Person{");
sb.append("姓名是'").append(name).append(''');
sb.append(", 年龄是").append(age).append('岁');
sb.append(", 性别是").append(sex);
sb.append(", 电话号码是'").append(phone).append(''');
sb.append(", 地址是'").append(address).append(''');
sb.append('}');
return sb.toString();
}
}
创造实体类对应的业务类,聚合二叉搜索树
package com.sanqi;
public class PersonService {
private final BinarySearchTree<Person> persons;
public PersonService() {
this.persons = new BinarySearchTree<>();
}
public void save(Person p){
persons.add(p);
}
public void printAllPerson() {
persons.midOrder();
}
public void delete(Person p) {
persons.remove(p);
}
public void count(){
System.out.println("目前一共拥有"+persons.size()+"名教师");
}
}
①单独测试二叉搜索树
package com.sanqi;
public class UseBSTree {
public static void main(String[] args) {
BinarySearchTree<Integer> bst=new BinarySearchTree<>();
bst.add(40);
bst.add(14);
bst.add(20);
bst.add(18);
bst.add(65);
bst.add(4);
bst.add(6);
bst.add(17);
bst.add(30);
bst.add(23);
System.out.println("BST中元素的个数:"+bst.size());
System.out.println("-----前序遍历-----");
bst.preOrder();
System.out.println("
-----中序遍历-----");
bst.midOrder();
System.out.println("
-----后序遍历-----");
bst.postOrder();
bst.remove(13);
bst.remove(17);
}
}
②测试聚合二叉搜索树
package com.sanqi;
public class Test {
public static void main(String[] args) {
PersonService personService=new PersonService();
Person p1 = new Person("Alice", 30, '女', "123-456-7890", "123 Main St");
Person p2 = new Person("Bob", 25, '男', "098-765-4321", "456 Elm St");
Person p3 = new Person("Charlie", 35, '男', "555-123-4567", "789 Oak St");
Person p4 = new Person("Diana", 28, '女', "555-765-4321", "321 Maple St");
Person p5 = new Person("Eve", 22, '女', "555-987-6543", "654 Pine St");
Person p6 = new Person("Frank", 40, '男', "555-654-0987", "987 Cedar St");
Person p7 = new Person("Grace", 33, '女', "555-321-8765", "213 Birch St");
Person p8 = new Person("Hank", 45, '男', "555-876-5432", "435 Spruce St");
personService.save(p1);
personService.save(p2);
personService.save(p3);
personService.save(p4);
personService.save(p5);
personService.save(p6);
personService.save(p7);
personService.save(p8);
personService.count();
personService.printAllPerson();
personService.delete(p5);
personService.count();
}
}
4.利用TreeMap实现一个学生成绩管理系统
学生实体记录类
package com.sanqi;
public record Student(String name, int score) {
@Override
public String toString() {
return String.format("%s: %d分", name, score);
}
}
TreeMap实现系统功能
package com.sanqi;
import java.util.*;
public class StudentGradeSystem {
private final TreeMap<String, Student> nameMap; // 按姓名排序
private final TreeMap<Integer, List<Student>> scoreMap; // 按分数排序(倒序)
public StudentGradeSystem() {
nameMap = new TreeMap<>();
scoreMap = new TreeMap<>(Comparator.reverseOrder()); // 分数从高到低
}
public void addStudent(Student student) {
nameMap.put(student.name(), student);
scoreMap.computeIfAbsent(student.score(), k->new ArrayList<>()).add(student);
}
public List<Student> getStudentsByNameRange(String from, String to) {
// 自动比较并交换,确保 from <= to
String actualFrom = from.compareTo(to) <= 0 ? from : to;
String actualTo = from.compareTo(to) <= 0 ? to : from;
SortedMap<String, Student> subMap = nameMap.subMap(actualFrom, true, actualTo, true);
return new ArrayList<>(subMap.values());
}
public List<Student> getStudentsByScoreRange(int minScore, int maxScore) {
List<Student> result = new ArrayList<>();
NavigableMap<Integer, List<Student>> rangeMap =
scoreMap.subMap(maxScore, true, minScore, true);
for (List<Student> students : rangeMap.values()) {
result.addAll(students);
}
return result;
}
public int getStudentRank(String name) {
if (!nameMap.containsKey(name)) return -1;
int targetScore = nameMap.get(name).score();
int rank = 1;
// 遍历分数更高的学生
for (Map.Entry<Integer, List<Student>> entry : scoreMap.entrySet()) {
if (entry.getKey() > targetScore) {
rank += entry.getValue().size();
} else {
break;
}
}
return rank;
}
/**
* 获取前N名学生
*/
public List<Student> getTopNStudents(int n) {
List<Student> topN = new ArrayList<>();
for (List<Student> students : scoreMap.values()) {
for (Student student : students) {
if (topN.size() >= n) break;
topN.add(student);
}
if (topN.size() >= n) break;
}
return topN;
}
/**
* 获取后N名学生(倒数N名)
*/
public List<Student> getBottomNStudents(int n) {
// 创建正序的分数视图
NavigableMap<Integer, List<Student>> ascendingMap = scoreMap.descendingMap();
List<Student> bottomN = new ArrayList<>();
for (List<Student> students : ascendingMap.values()) {
for (Student student : students) {
if (bottomN.size() >= n) break;
bottomN.add(student);
}
if (bottomN.size() >= n) break;
}
return bottomN;
}
public void displayAllByName() {
System.out.println("=== 按姓名排序 ===");
nameMap.values().forEach(System.out::println);
}
public void displayAllByScore() {
System.out.println("=== 按分数排序 ===");
scoreMap.values().stream()
.flatMap(List::stream)
.forEach(System.out::println);
}
}
测试类
package com.sanqi;
public class TreeMapTest {
public static void main(String[] args) {
StudentGradeSystem system = new StudentGradeSystem();
// 添加测试数据
system.addStudent(new Student("张三", 85));
system.addStudent(new Student("李四", 92));
system.addStudent(new Student("王五", 78));
system.addStudent(new Student("赵六", 88));
system.addStudent(new Student("钱七", 95));
system.addStudent(new Student("孙八", 82));
system.addStudent(new Student("周九", 90));
System.out.println("1. 所有学生(按姓名排序):");
system.displayAllByName();
System.out.println("
2. 所有学生(按分数排序):");
system.displayAllByScore();
System.out.println("
3. 查询80-90分的学生:");
system.getStudentsByScoreRange(80, 90).forEach(System.out::println);
System.out.println("
4. 查询姓名在'李'到'孙'之间的学生:");
system.getStudentsByNameRange("李", "孙").forEach(System.out::println);
System.out.println("
5. 学生排名查询:");
System.out.println("张三的排名:" + system.getStudentRank("张三"));
System.out.println("李四的排名:" + system.getStudentRank("李四"));
System.out.println("
6. 前三名学生:");
system.getTopNStudents(3).forEach(System.out::println);
System.out.println("
7. 后两名学生:");
system.getBottomNStudents(2).forEach(System.out::println);
}
}
© 版权声明
文章版权归作者所有,未经允许请勿转载。如内容涉嫌侵权,请在本页底部进入<联系我们>进行举报投诉!
THE END














暂无评论内容