【Java】实验五 容器框架与泛型

实验名称    实验五 容器框架与泛型

实验目的   

1. 深刻理解容器框架包含的核心接口。

2. 熟练使用常用容器类的API和遍历方式。

3. 熟练使用泛型容器存储和操作常用数据结构。  

实验内容

  1. 集合A={1, 2, 3, 4}、B={1, 3, 5, 9, 11},选择合适的容器类,编写程序求A与B的交、并、差。

package jset;



import java.util.HashSet;

import java.util.Set;



public class SetOperations {

    public static void main(String[] args) {

        Set<Integer> A = new HashSet<>();

        A.add(1);

        A.add(2);

        A.add(3);

        A.add(4);



        Set<Integer> B = new HashSet<>();

        B.add(1);

        B.add(3);

        B.add(5);

        B.add(9);

        B.add(11);



        // 交集

        Set<Integer> intersection = new HashSet<>(A);

        intersection.retainAll(B);

        System.out.println("Intersection: " + intersection);



        // 并集

        Set<Integer> union = new HashSet<>(A);

        union.addAll(B);

        System.out.println("Union: " + union);



        // 差集 (A - B)

        Set<Integer> difference = new HashSet<>(A);

        difference.removeAll(B);

        System.out.println("Difference (A - B): " + difference);

    }

}

  1. CPU类有型号、单价、主频等属性,通过循环构造10个CPU对象并添加到泛型TreeMap中,然后分别按单价和主频降序输出(要求使用Comparable或Comparator实现排序逻辑)。
import java.util.*;

import java.util.concurrent.ThreadLocalRandom;



class CPU {

    private String model;

    private double price;

    private double frequency;



    public CPU(String model, double price, double frequency) {

        this.model = model;

        this.price = price;

        this.frequency = frequency;

    }



    public String getModel() {

        return model;

    }



    public double getPrice() {

        return price;

    }



    public double getFrequency() {

        return frequency;

    }



    @Override

    public String toString() {

        return "Model: " + model + ", Price: " + price + ", Frequency: " + frequency;

    }

}



class CPUPriceComparator implements Comparator<CPU> {

    @Override

    public int compare(CPU cpu1, CPU cpu2) {

        return Double.compare(cpu2.getPrice(), cpu1.getPrice()); // 降序排列

    }

}



class CPUFrequencyComparator implements Comparator<CPU> {

    @Override

    public int compare(CPU cpu1, CPU cpu2) {

        return Double.compare(cpu2.getFrequency(), cpu1.getFrequency()); // 降序排列

    }

}



public class CPUSortExample {

    public static void main(String[] args) {

        // 创建一个泛型TreeMap,使用CPUPriceComparator进行单价排序

        TreeMap<CPU, String> priceSortedCPUs = new TreeMap<>(new CPUPriceComparator());



        // 创建一个泛型TreeMap,使用CPUFrequencyComparator进行主频排序

        TreeMap<CPU, String> frequencySortedCPUs = new TreeMap<>(new CPUFrequencyComparator());



        // 随机生成10个CPU对象并添加到TreeMap中

        for (int i = 0; i < 10; i++) {

            String model = "CPU" + (i + 1);

            double price = ThreadLocalRandom.current().nextDouble(100, 500); // 随机生成单价

            double frequency = ThreadLocalRandom.current().nextDouble(2.0, 4.5); // 随机生成主频



            CPU cpu = new CPU(model, price, frequency);



            priceSortedCPUs.put(cpu, model);

            frequencySortedCPUs.put(cpu, model);

        }



        // 输出按单价降序排列的CPU列表

        System.out.println("CPUs sorted by price (descending):");

        for (CPU cpu : priceSortedCPUs.keySet()) {

            System.out.println(cpu);

        }



        // 输出按主频降序排列的CPU列表

        System.out.println("\nCPUs sorted by frequency (descending):");

        for (CPU cpu : frequencySortedCPUs.keySet()) {

            System.out.println(cpu);

        }

    }

}

3. 编写学生成绩管理系统,实现以下功能。

① 文件student.txt(不少于6行)的每行存放了一个学生的学号、姓名。

② 文件course.txt(不少于4行)的每行存放了一门课程的课程号、课程名。

③ 文件score.txt(不少于15行)的每行存放了一个学生某门课程的成绩信息,包含学号、课程号、成绩。

④ 读取上述文件,分别存于3个泛型HashMap中(注意key的选取)。

⑤ 允许用户输入学号和课程号,以查询某学生某门课的成绩。

⑥ 统计每门课程的平均分。

⑦ 允许用户输入学号,以删除HashMap中对应的学生及其所有的成绩信息

package XJGL;

import java.io.File;

import java.io.FileNotFoundException;

import java.util.HashMap;

import java.util.Scanner;

import java.io.*;

import java.util.*;

public class StudentManagementSystem {

    private HashMap<String, String> studentMap;

    private HashMap<String, String> courseMap;

    private HashMap<String, Double> scoreMap;



    public StudentManagementSystem() {

        studentMap = new HashMap<>();

        courseMap = new HashMap<>();

        scoreMap = new HashMap<>();

    }



    private void readStudentInfo(String fileName, HashMap<String, String> students) {

        try {

            Scanner scanner = new Scanner(new File(fileName));

            while (scanner.hasNextLine()) {

                String line = scanner.nextLine();

                String[] parts = line.split(" ");

                if (parts.length == 2) {

                    students.put(parts[0], parts[1]);

                } else {

                    System.err.println("Invalid line in student.txt: " + line);

                }

            }

            scanner.close();

        } catch (FileNotFoundException e) {

            e.printStackTrace();

        }

    }



    private void readCourseInfo(String fileName, HashMap<String, String> courses) {

        try {

            Scanner scanner = new Scanner(new File(fileName));

            while (scanner.hasNextLine()) {

                String line = scanner.nextLine();

                String[] parts = line.split(" ");

                if (parts.length == 2) {

                    courses.put(parts[0], parts[1]);

                } else {

                    System.err.println("Invalid line in course.txt: " + line);

                }

            }

            scanner.close();

        } catch (FileNotFoundException e) {

            e.printStackTrace();

        }

    }



    private void readScoreInfo(String fileName, HashMap<String, Double> scores) {

        try {

            Scanner scanner = new Scanner(new File(fileName));

            while (scanner.hasNextLine()) {

                String line = scanner.nextLine();

                String[] parts = line.split(" ");

                if (parts.length == 3) {

                    scores.put(parts[0] + parts[1], Double.parseDouble(parts[2]));

                } else {

                    System.err.println("Invalid line in score.txt: " + line);

                }

            }

            scanner.close();

        } catch (FileNotFoundException e) {

            e.printStackTrace();

        }

    }



    private void calculateCourseAverages() {

        HashMap<String, Double> courseSum = new HashMap<>();

        HashMap<String, Integer> courseCount = new HashMap();



        for (String studentId : scoreMap.keySet()) {

            String courseId = studentId.substring(3);

            double score = scoreMap.get(studentId);



            if (courseSum.containsKey(courseId)) {

                courseSum.put(courseId, courseSum.get(courseId) + score);

                courseCount.put(courseId, courseCount.get(courseId) + 1);

            } else {

                courseSum.put(courseId, score);

                courseCount.put(courseId, 1);

            }

        }



        System.out.println("Course Averages:");

        for (String courseId : courseSum.keySet()) {

            double average = courseSum.get(courseId) / courseCount.get(courseId);

            System.out.println(courseId + ": " + average);

        }

    }



    public void deleteStudentInfo(String studentID) {

        // 删除学生信息及其成绩

        List<String> keysToRemove = new ArrayList<>();



        for (Map.Entry<String, String> entry : studentMap.entrySet()) {

            if (entry.getKey().equals(studentID)) {

                keysToRemove.add(entry.getKey());

            }

        }



        for (String key : keysToRemove) {

            studentMap.remove(key);

        }



        keysToRemove.clear();



        for (Map.Entry<String, Double> entry : scoreMap.entrySet()) {

            if (entry.getKey().startsWith(studentID)) {

                keysToRemove.add(entry.getKey());

            }

        }



        for (String key : keysToRemove) {

            scoreMap.remove(key);

        }

    }





    public static void main(String[] args) {

        StudentManagementSystem system = new StudentManagementSystem();

        system.readStudentInfo("E:/PRODUCE/xc5/src/XJGL/student.txt", system.studentMap);

        system.readCourseInfo("E:/PRODUCE/xc5/src/XJGL/course.txt", system.courseMap);

        system.readScoreInfo("E:/PRODUCE/xc5/src/XJGL/score.txt", system.scoreMap);



        Scanner scanner = new Scanner(System.in);

        System.out.print("Enter student ID: ");

        String studentId = scanner.next();

        System.out.print("Enter course ID: ");

        String courseId = scanner.next();



        String studentName = system.studentMap.get(studentId);

        String courseName = system.courseMap.get(courseId);

        Double score = system.scoreMap.get(studentId + courseId);



        if (studentName != null && courseName != null && score != null) {

            System.out.println("Student: " + studentName);

            System.out.println("Course: " + courseName);

            System.out.println("Score: " + score);

        } else {

            System.out.println("Student or course not found.");

        }



        system.calculateCourseAverages();



        System.out.print("Enter student ID to delete: ");

        String studentToDelete = scanner.next();

        system.deleteStudentInfo(studentToDelete);



        // Print updated student and score information

        System.out.println("Updated Student Information:");

        for (String id : system.studentMap.keySet()) {

            System.out.println(id + " " + system.studentMap.get(id));

        }



        System.out.println("Updated Score Information:");

        for (String key : system.scoreMap.keySet()) {

            System.out.println(key + " " + system.scoreMap.get(key));

        }

    }

}

以下是示例的 `student.txt`,`course.txt` 和 `score.txt` 文件的内容示例:

`student.txt` 文件内容示例:

```

S101 John

S102 Alice

S103 Bob

S104 Sarah

S105 Michael

S106 Emma

```

`course.txt` 文件内容示例:

```

C101 Math

C102 Science

C103 History

C104 English

```

`score.txt` 文件内容示例:

```

S101 C101 95.5

S101 C102 85.0

S101 C103 92.5

S101 C104 88.0

S102 C101 77.5

S102 C102 89.5

S102 C103 74.0

S102 C104 92.5

S103 C101 80.0

S103 C102 95.0

S103 C103 87.5

S103 C104 78.5

S104 C101 88.0

S104 C102 91.5

S104 C103 86.0

S104 C104 82.0

S105 C101 92.5

S105 C102 78.5

S105 C103 90.0

S105 C104 96.5

S106 C101 85.0

S106 C102 89.0

S106 C103 94.0

S106 C104 81.5```

这些文件包含了学生、课程和成绩信息,供程序读取和操作。请根据你的需求和数据填充实际的文件内容。

实验程序及结果(附录)

思考

1. Set中的元素不允许重复,具体如何区分?

1. Set中的元素不允许重复,这是因为Set是一种集合,它的元素是无序的且不可重复的。这是通过元素的`equals`和`hashCode`方法来实现的。当你向Set中添加一个元素时,Set会首先检查该元素是否已经存在于集合中。这里涉及两个方法的作用:

   - `equals`方法:用于比较两个对象是否相等。Set使用`equals`方法来检查两个元素是否相等。

   - `hashCode`方法:用于计算对象的哈希码。哈希码是一个整数,每个对象都有一个独一无二的哈希码。Set使用`hashCode`来确定对象在集合中的位置。

   如果两个元素的`equals`方法返回`true`,并且它们的`hashCode`相同,那么Set会认为它们是相同的元素,不会允许重复。

2. 如何理解“泛型不是协变的”这句话?

2. "泛型不是协变的"这句话指的是在Java中,泛型类型不支持协变。协变是指子类型的关系,例如子类是父类的子类型。在泛型中,如果有一个泛型类型`A`,那么`A<子类型>`并不是`A<父类型>`的子类型。

   这是因为Java的泛型是不变的(invariant)。这意味着泛型类不支持直接赋值给其他泛型类,即使它们之间存在继承关系。这是出于类型安全的考虑,以确保泛型的参数类型在编译时得到严格检查,防止类型不匹配的错误。

   但是,Java中引入了通配符类型和通配符捕获来实现协变和逆变。通过使用通配符,你可以实现类似协变的操作。例如,你可以使用`List<? extends 父类型>`来实现协变,允许在`List`中存储子类型的元素。但要注意,通配符类型有一些限制,如无法添加元素(只能读取),因为编译器无法确定通配符类型的确切类型。

   总之,泛型不是协变的意味着泛型类型不能直接赋值给不同类型的泛型,但可以通过通配符来实现协变和逆变。这有助于保持类型安全。

猜你喜欢

转载自blog.csdn.net/qq_42531954/article/details/135391280