【问题标题】:Looking through class Arraylist objects without nested loops查看没有嵌套循环的类 Arraylist 对象
【发布时间】:2020-12-30 22:45:09
【问题描述】:

上学期我有一个面向对象的编程项目,就是模拟一个简单的宿舍。

1. 应该有一个管理器类,其中主要方法和其他 80% 的方法必须存在。 2.一个宿舍类,包含一个数组列表。 3.包含房间数组列表的块类。 4.一个包含学生数组列表的房间类。 5.所有这些类都包含用于其私有变量的 getter 和 setter。

有一些我们应该添加到程序中的方法与我的问题无关,所以我不会在这里写它们,但问题是,其中一些方法需要查看这些arraylists 来查找特定对象。例如,具有特定学号的学生。我使用嵌套循环创建了这些方法。但我知道有一些方法可以避免大量嵌套。

这是我的简化代码。我将只让管理器类包含一个嵌套循环方法作为示例:

import java.util.Scanner;

public class Manager {

    private String name;
    private String familyName;
    private String userName;
    private String passWord;

    private static Scanner scan = new Scanner(System.in);
    private Dormitory dorm = new Dormitory();
    private static Menu menu = new Menu();
    private Student tempStudent;
    private Block tempBlock;
    private Room room;
    private boolean bool;

    {
        dorm.setDormManager(this);
    }

    public Manager(String managerName, String managerID) {
        name = managerName;
        userName = managerID;
    }

    //find student with its number
    public void findStudent() {
        //Taking the student number from the user.
        System.out.println("Please enter the student number:");
        String studentNum = scan.nextLine();
        for (int i = 0; i < dorm.getBlockList().size(); i++)
            for (int j = 0; j < dorm.getBlockList().get(i).getRooms().size(); j++)
                for (int k = 0; k < dorm.getBlockList().get(i).getRooms().get(j).getRoomStudents().size(); k++)
                    if (dorm.getBlockList().get(i).getRooms().get(j).getRoomStudents().get(k).getStudentNumber().equals(studentNum)) {
                        tempStudent = dorm.getBlockList().get(i).getRooms().get(j).getRoomStudents().get(k);
                        break;
                    }
    }

    public void create() {
        //Used loops for the original program.
        Block block1 = new Block("1");
        Block block2 = new Block("2");
        dorm.getBlockList().add(block1);
        dorm.getBlockList().add(block2);
        Room room1 = new Room("1");
        Room room2 = new Room("2");
        dorm.getBlockList().get(0).getRooms().add(room1);
        dorm.getBlockList().get(1).getRooms().add(room2);
        Student student1 = new Student("12345678");
        Student student2 = new Student("98765432");
        dorm.getBlockList().get(0).getRooms().get(0).getRoomStudents().add(student1);
        dorm.getBlockList().get(1).getRooms().get(0).getRoomStudents().add(student2);
    }

    public static void main(String[] args) {
        Manager manager = new Manager("Dumbledore", "@1112");
        manager.create();
    }
}

public class Dormitory {

    private int blocks;
    private Manager dormManager;
    private long allMembers;
    private ArrayList<Block> blockList = new ArrayList<Block>();
}

public class Block {

    private String blockNumber;
    private ArrayList<Room> rooms = new ArrayList<Room>();
    private Dormitory dorm = new Dormitory();

    public Block(String blockNum) {
        blockNumber = blockNum;
    }
}

public class Room {

    private String roomNumber;
    private ArrayList<Student> roomStudents = new ArrayList<Student>();
    private Block roomBlock;
    private Student roomManager;

    public Room(String roomNum) {
        roomNumber = roomNum;
    }
}

public class Student {

    private String studentName;
    private String studentFamilyName;
    private String studentNumber;
    private Room room;

    public Student(String studentNum) { //Creates a student object using the student number.
        studentNumber = studentNum;
    }
}

我尽力减少代码。 我搜索了很多,问了很多人,但我没有得到我想要的答案。我不知道为什么我找不到任何关于这个的东西,但如果你能借给我,我会非常感激帮忙或者给我相关文章的链接。

【问题讨论】:

  • 提醒一下:你不能在snipplets中运行Java代码
  • 请不要做多余的 cmets,例如构造函数上方的“constructor”或变量上方的“variables”。注释应为在某些方面无法记录自身的代码添加详细信息或说明。
  • 自我描述的声明、定义或陈述,不需要注释,除非它真的有必要。例如,在int x = 5; //assigning 5 to variable x 的定义中,如果你继续为其他几个代码sn-ps 编写这些cmets,注释真的没用,它会制造更多噪音,而且代码看起来很难看,难以阅读。请记住,让您的代码尽可能简单和干净。
  • 嵌套循环没有错。
  • 哇,我的评论真的那么糟糕吗?抱歉,我只是想让它更具可读性。我想我应该看到更多好的评论示例。感谢您的建议。

标签: java loops oop arraylist nested-loops


【解决方案1】:

以下引用来自tutorialspoint。这是来自Stream 接口的forEach 方法的完美用例。我提供的链接和有关 Streams 的进一步阅读有助于避免重复代码。

使用 Java 中的集合框架,开发人员必须使用循环并进行重复检查。另一个问题是效率。由于多核处理器可以轻松使用,Java 开发人员必须编写可能非常容易出错的并行代码处理。

dorm.getBlockList().stream().forEach((b) -> {
    b.getRooms().stream().forEach((r) -> {
        ...
    })
});

您还可以从here 阅读有关parallelStreams 的信息。

【讨论】:

  • 我认为您错过了问题的重点。 OP 询问是否需要循环
  • 我不这么认为,是吗?为什么他首先要做级联循环?我认为 OP 想要的是让学生以有效的方式获得宿舍和学生编号。
  • OP 是一名学习编程的学生,因此最好假设他们没有太多经验并且愿意接受更好的解决方案。假设 studentNumber 是每个学生的唯一标识符也是安全的,与他们所在的街区/房间无关(你认为如果你改变宿舍,你的 studentNumber 会改变吗?)
  • 我认为学生成功完成了这个项目。 OP 唯一需要的是一个有效的解决方案。如果学生成功地完成了他为作业编写的代码,如果期望他编写这样的代码只是为了找到具有特定 studentNumber 的学生,那么正确的假设是不同宿舍中可能存在相似的 studentNumber。我认为没有教授会在给出及格分数之前不纠正这一点,除非这是必需的行为,即使效率不高。
  • 我放弃了,你显然从未听说过学号的概念。这是您的唯一 ID,用于登录,用于在图书馆借书,用于一切
【解决方案2】:

简短回答:不,您永远不应该遍历所有检查 getStudentNumber().equals(studentNum) 的内容。这有linear time complexity O(N)

长答案:您应该根据您的查询索引您的数据

例如:使用具有constant time complexity O(1) 的 HashMap 进行索引。 (注意:这段代码不是线程安全的)

public class SchoolService {
    private Map<String, Student> studentsById = new HashMap<>();
    private Map<Long, Dorm> dormsById = new HashMap<>();

    /// dormsByAreaCode is showing an example of an index which groups objects into lists
    private Map<String, List<Dorm>> dormsByAreaCode = new HashMap<>();

    public void addStudent(Student student) {
       if (studentsById.containsKey(student.getName()) {
           throw new IllegalStateException("Duplicate student " + student.getName());
       }
       studentsById.put(student.getId(), student);
    }

    public Student getStudentById(String studentId) {
       Student student = studentsById.get(studentId);
       if (student == null) {
           throw new IllegalStateException("No such student " + studentId);
       }
       return student;
    }

    public void addDorm(Dorm dorm) {
        // TODO: validation
        dormsById.put(dorm.getId(), dorm);
        List<Dorm> areaDorms = dormsByAreaCode.get(dorm.getAreaCode());
        if (areaDorms == null) {
            areaDorms = new ArrayList<>();
            dormsByAreaCode.put(dorm.getAreaCode(), areaDorms);
        }
        areaDorms.add(dorm);
    }

    public Dorm getDormById(long dormId) {
        Dorm dorm = dormsById.get(id);
        // TODO: validation
        return dorm;
    }

    public List<Dorm> getDormsByAreaCode(String areaCode) {
        List<Dorm> areaDorms = dormsByAreaCode.get(areaCode);
        // TODO: validation
        return areaDorms;
    }

    // etc
}

【讨论】:

  • 如果这个号码的学生在另一个宿舍怎么办?
  • 我很确定 studentNumber 是一个唯一标识符。
  • 我不知道你很确定。
猜你喜欢
  • 2018-03-23
  • 2020-11-30
  • 1970-01-01
  • 2018-05-11
  • 2018-06-05
  • 2021-05-19
  • 2021-12-09
  • 2021-03-27
相关资源
最近更新 更多