1

HashMap に値を入力する際の問題や疑問はほとんどありません

HashMap で「Student」をキーとして、「Details」を値として受け入れるようにしたいと考えています。hashMap へのキーは不変でなければならないので、次の場合にこれをどのように処理できるか疑問があります。

  1. 学生クラスは複製できませんでした
  2. 学生クラスには「ラボ」への参照があります

    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 を変更できます。(私が間違っている?)

Department と Lab がサードパーティの jar からのものである場合、Student hashCode が (primeNumber+Student.id+Department.id+Lab.id).hashcode() [ちょうどいくつかの奇妙なケース]; の場合、マップで Student オブジェクトを使用するにはどうすればよいですか?

4

3 に答える 3

5

私が理解している限り、不変性は Cloneable とは何の関係もありません。実際、その逆です。不変性は、クラス final を宣言し、不変フィールド、オーバーライド不可能なメソッド、setter メソッドなし、フィールドまたは不変フィールドのディープ コピーを返す getter メソッドなどを使用することと関係があります。詳細については、不変オブジェクトを定義するための戦略をお読みください。これについて。

また、コードには疑似コンストラクターがあります。

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 を適切にオーバーライドする必要があります。

于 2013-11-28T18:35:25.653 に答える
4

Student が複製可能であっても、Department の参照を取得し、setLab() を呼び出して StudentObject を変更できます。(私が間違っている?)

あなたは正しいです。これが発生する可能性があり、Student クラスが変異しているように見える可能性があります。のインスタンスStudentが不変であるためには、そのフィールドのいずれも変更できてはなりません[0]。これには、フィールドの 1 つでセッター メソッドのようなものを呼び出すことも含まれます。

Department と Lab がサードパーティの jar からのものである場合、Student hashCode が (primeNumber+Student.id+Department.id+Lab.id).hashcode() [ちょうどいくつかの奇妙なケース]; の場合、マップで Student オブジェクトを使用するにはどうすればよいですか?

それはとても良い質問です。クラスを制御できないため、明らかにクラスを不変に変更することはできません。そのため、少し創造的になる必要があるかもしれません。可能な解決策:

  • 使用したいサード パーティ オブジェクトがインターフェイスである場合は、すべてのミューテーター メソッドの本体が例外をスローする独自の型でインターフェイスを実装できます (例: を考えてくださいjava.util.Collections.unmodfiableList)。これには、コードベースでサードパーティ クラスを引き続き参照できるという利点がありますが、ミューテーター メソッドの呼び出しがコンパイル時ではなく実行時に失敗するという欠点があります。
  • 次のように、独自のコードベースにアダプターを記述します。

    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] これが可能で、内部キャッシングに使用できる場合もありますが、学習する際に固執する適切なガイドラインです。

于 2013-11-28T20:30:11.737 に答える