我几乎没有问题/疑点来填充HashMap中的值
我希望HashMap接受“Student”作为键,“Details”作为值。 由于hashMap的键应该是不可变的,我有一些疑问,如果
,如何处理它学生班参考了“实验室”
public class Student {
private String id;
private String name;
private Department dept;
public Student(String id, String name, Department dept)
{
this.id=id;
this.name=name;
this.dept=dept;
}
public Department getDepartment()
{
return this.dept;
}
}
public class Department {
private String deptId;
private Lab lab;
public Department(String deptId, Lab lab)
{
this.deptId=deptId;
this.lab=lab;
}
public void setLab(Lab lab)
{
this.lab=lab;
}
}
public class Lab {
private String labId;
private String labName;
public Lab(String labId, String labName)
{
this.labId=labId;
this.labName=labName;
}
}
public class StudentDetails
{
private String fatherName;
private String address
public StudentDetails(String fatherName, String address)
{
this.fatherName=fatherName;
this.address=address;
}
}
public class StudentMaintainer {
public static void main(String[] args)
{
StudentDetails stDetails= new StudentDetails("John","Mumbai");
Lab lab= new Lab("100","CS");
Department dept= new Department("900", lab);
Student st = new Student("3000",dept);
Map<Student,StudentDetails> studentMaintainer= new ArrayList<>();
studentMaintainer.put(st,stDetails);
}
}
现在即使Student是可复制的,我也可以获得Department的引用并调用setLab()来更改StudentObject。 (我错了吗?)
现在如果部门和实验室来自第三方罐子,如果学生hashCode是(primeNumber + Student.id + Department.id + Lab.id),我怎么能在我的地图中使用学生对象.hashcode()[只是有些奇怪情况下];
答案 0 :(得分:5)
就我所理解的而言,不变性与Cloneable无关,事实恰恰相反。不可变性更多地与声明类final和使用不可变字段,不可覆盖的方法,没有setter方法,返回字段或不可变字段的深层副本的getter方法等有关...请阅读A Strategy for Defining Immutable Objects了解更多信息此
此外,您的代码还有一个伪 --constructor:
public void Student(String id, String name, Department dept)
{
this.id=id;
this.name=name;
this.dept=dept;
}
不应声明真正的构造函数返回任何,甚至不是void。更好的是:
// note the difference?
public Student(String id, String name, Department dept)
{
this.id=id;
this.name=name;
this.dept=dept;
}
此外,如果要将其作为HashMap的键,那么您的Student类应正确覆盖equals和hashCode。
答案 1 :(得分:4)
现在即使学生可以克隆,我也可以参考部门 并调用setLab()来更改StudentObject。 (我错了吗?)
你是对的。这可能发生,并且可能导致您的Student类看起来变异。对于Student
不可变的实例,您必须无法修改其任何字段[0]。这包括在其中一个字段上调用类似setter方法的东西。
现在如果部门和实验室来自第三方罐子,我该如何使用 如果学生hashCode是,我的地图中的学生对象 (primeNumber + Student.id + Department.id + Lab.id).hashcode()[只是一些 奇怪的情况];
这是一个非常好的问题。你显然不能只是将类更改为不可变的,因为你无法控制它们,所以你可能需要有点创意。可能的解决方案:
java.util.Collections.unmodfiableList
)。这样做的好处是你仍然可以引用代码库中的第三方类,但调用mutator方法的缺点是在运行时而不是在编译时失败。在您自己的代码库中编写适配器,如下所示:
public final class MyImmutableDepartment {
private final MyImmutableLab lab;
private final String departmentId;
public MyImmutableDepartment(Department thirdPartyMutableDepartment) {
this.departmentId = thirdPartyMutableDepartment.getId();
this.lab = new MyImmutableLab(thirdPartyMutableDepartment.getLab());
}
// getters and the MyImmutableLab class left as an exercise
}
这样做的好处是你在编译时知道,这些类不能被改变。
这两种方法的缺点是你基本上必须镜像第三方库中的每个类,以确保它们是不可变的。
我认为还有其他选择。
[0]在某些情况下这是可能的,并且可以用于内部缓存,但它是一个在学习时坚持的合适指南。
答案 2 :(得分:0)
学生不需要一成不变!具体来说,要求是当密钥在HashMap中时,equals / hashCode的行为不会改变。
这可以通过三种方式实现:
但是,在你的具体例子中,每个学生都有一个id。为什么在实现equals / hashCode时会使用任何其他属性?