Java序列化文件去重求和:读取.ser对象并合并重复条目
问题描述
已将Person对象数组写入object.ser文件,需求为读取这些对象后,实现每位人员仅出现一次并累加其对应参与小时数。目前已实现逐行输出单条记录的数值,但不清楚如何完成去重求和的逻辑。
当前代码
public class IOStream { /** * @param args the command line arguments */ public static void main(String[] args) throws ClassNotFoundException { Person[] people = new Person[14]; people[0] = new Professor("Professor", "Issac", "Newton", "Physcis", 6); people[1] = new TA("TA", "Marie", "Curie", "Physics", 6); people[2] = new Professor("Professor", "Issac", "Newton", "Calculus", 4); people[3] = new Student("Student", "Amy", "Adams", "Calculus", 4); people[4] = new Student("Student", "Will", "Smith", "Calculus", 4); people[5] = new Student("Student", "Brad", "Pitt", "Physics", 6); people[6] = new Student("Student", "Will", "Smith", "Physics", 6); people[7] = new Professor("Professor", "Dimitri", "Mendeleev", "Chemistry", 6); people[8] = new TA("TA", "Carl", "Gauss", "Calculus", 4); people[9] = new Student("Student", "Amy", "Adams", "Economics", 3); people[10] = new Professor("Professor", "Adam", "Smith", "Economics", 3); people[11] = new TA("TA", "Marie", "Curie", "Chemistry", 6); people[12] = new Student("Student", "Brad", "Pitt", "Chemistry", 6); people[13] = new Student("Student", "Will", "Smith", "Chemistry", 6); //WRITING try ( ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("object.ser"))) { for (int i = 0; i < people.length; i++) { out.writeObject(people[i]); } out.close(); } catch (IOException e) { e.printStackTrace(); } //READING INPUT try ( ObjectInputStream in = new ObjectInputStream(new FileInputStream("object.ser"))) { ObjectOutputStream writer = new ObjectOutputStream(new FileOutputStream("output.ser")); Person lol; Person [] list; int i; while ((lol = (Person) in.readObject()) != null) { writer.writeObject(lol.title + " " + lol.fName + " " + lol.lName + " " + lol.getParticipatingHours(lol.courseHours)); } } catch (EOFException i) { //System.out.println("lol"); } catch (IOException e) { e.printStackTrace(); System.out.println("Error"); } try { ObjectInputStream reader = new ObjectInputStream(new FileInputStream("output.ser")); Object line; while ((line = reader.readObject()) != null) { System.out.println(line); } } catch (EOFException i) { //System.out.println("lol"); } catch (IOException e) { e.printStackTrace(); } } }
当前输出
run: Professor Issac Newton 4 TA Marie Curie 2 Professor Issac Newton 3 Student Amy Adams 4 Student Will Smith 4 Student Brad Pitt 6 Student Will Smith 6 Professor Dimitri Mendeleev 4 TA Carl Gauss 1 Student Amy Adams 3 Professor Adam Smith 2 TA Marie Curie 2 Student Brad Pitt 6 Student Will Smith 6
解决方案
要实现人员去重并累加小时数,核心是用Map集合存储人员与累计小时数的映射,同时确保Person类能正确判断“同一人”。
步骤1:重写Person类的equals和hashCode方法
判断同一人的依据是title、fName和lName,需在Person类中重写这两个方法(子类若未覆盖,需确保父类实现符合需求):
import java.util.Objects; public class Person { protected String title; protected String fName; protected String lName; protected String course; protected int courseHours; // 构造方法、getParticipatingHours等已实现的方法... @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return Objects.equals(title, person.title) && Objects.equals(fName, person.fName) && Objects.equals(lName, person.lName); } @Override public int hashCode() { return Objects.hash(title, fName, lName); } }
步骤2:修改读取逻辑,用Map实现去重求和
替换原代码中读取object.ser的部分,改用HashMap<Person, Integer>存储累计数据,处理完成后再写入输出文件:
// 修改后的READING INPUT部分 try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("object.ser"))) { // 用Map存储人员与累计小时数的映射 Map<Person, Integer> personHourMap = new HashMap<>(); Person currentPerson; try { while (true) { currentPerson = (Person) in.readObject(); // 计算当前记录的参与小时数 int currentHours = currentPerson.getParticipatingHours(currentPerson.courseHours); // 更新Map:存在则累加,不存在则新增 personHourMap.put(currentPerson, personHourMap.getOrDefault(currentPerson, 0) + currentHours); } } catch (EOFException e) { // 读取到文件末尾,正常结束循环 } // 将处理后的结果写入output.ser try (ObjectOutputStream writer = new ObjectOutputStream(new FileOutputStream("output.ser"))) { for (Map.Entry<Person, Integer> entry : personHourMap.entrySet()) { Person p = entry.getKey(); String result = p.title + " " + p.fName + " " + p.lName + " " + entry.getValue(); writer.writeObject(result); } } } catch (IOException | ClassNotFoundException e) { e.printStackTrace(); System.out.println("Error"); }
步骤3:验证输出
修改后读取output.ser的逻辑不变,最终输出会是每位人员仅出现一次,且数值为累计后的总小时数,例如:
Professor Issac Newton 7 TA Marie Curie 4 Student Amy Adams 7 Student Will Smith 16 Student Brad Pitt 12 Professor Dimitri Mendeleev 4 TA Carl Gauss 1 Professor Adam Smith 2
内容的提问来源于stack exchange,提问作者Avi
相关产品推荐
相关产品推荐

