Lombokの@EqualsAndHashCode(lombok.EqualsAndHashCode)アノテーションの利用サンプルです。
クラスに@EqualsAndHashCode
アノテーションを付与することで、対象クラスのequals
メソッドとhashCode
メソッドがクラス内のメンバに応じて適切にオーバーライドされます。
ちなみに、@Data
や@Value
のアノテーションを付与すると、内部的に@EqualsAndHashCode
アノテーションが付与されたのと同じことが起こります。
デフォルトの@EqualsAndHashCodeを付与
パラメータの指定なしで@EqualsAndHashCode
を付与すると、クラス内の全メンバを利用してequals
, hashCode
の処理が生成されます
■@EqualsAndHashCodeを付与したクラス
import java.util.List; import lombok.EqualsAndHashCode; @EqualsAndHashCode public class Person1 { private long id; private String name; private List<String> notes; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<String> getNotes() { return notes; } public void setNotes(List<String> notes) { this.notes = notes; } }
■利用側のコード
import java.util.Arrays; public class Person1Client { public static void main(String[] args) { Person1 p1 = new Person1(); p1.setId(1L); p1.setName("Taro"); p1.setNotes(Arrays.asList("note1", "note2", "note3")); Person1 p2 = p1; Person1 p3 = new Person1(); p3.setId(1L); p3.setName("Taro"); p3.setNotes(Arrays.asList("note1", "note2", "note3")); Person1 p4 = new Person1(); p4.setId(1L); p4.setName("Taro"); p4.setNotes(Arrays.asList("note1", "note2", "note3", "note4")); System.out.println("p1#hashCode: " + p1.hashCode()); System.out.println("p2#hashCode: " + p2.hashCode()); System.out.println("p3#hashCode: " + p3.hashCode()); System.out.println("p4#hashCode: " + p4.hashCode()); System.out.println("p1#equals(p2): " + p1.equals(p2)); System.out.println("p1#equals(p3): " + p1.equals(p3)); System.out.println("p1#equals(p4): " + p1.equals(p4)); } }
■実行結果
メンバの値が同じならhashCode
の値は一致し、equals
の結果もtrueを返しています。
p1#hashCode: 1348088265 p2#hashCode: 1348088265 p3#hashCode: 1348088265 p4#hashCode: -1365998099 p1#equals(p2): true p1#equals(p3): true p1#equals(p4): false
■実際に生成されるソースコード
各メンバの値を使用して、equals
, hashCode
の処理が生成されていることが分かります。
import java.util.List; public class Person1 { private long id; private String name; private List<String> notes; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<String> getNotes() { return notes; } public void setNotes(List<String> notes) { this.notes = notes; } @Override public boolean equals(final Object o) { if (o == this) return true; if (!(o instanceof Person1)) return false; final Person1 other = (Person1) o; if (!other.canEqual((Object) this)) return false; if (this.getId() != other.getId()) return false; final Object this$name = this.getName(); final Object other$name = other.getName(); if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false; final Object this$notes = this.getNotes(); final Object other$notes = other.getNotes(); if (this$notes == null ? other$notes != null : !this$notes.equals(other$notes)) return false; return true; } protected boolean canEqual(final Object other) { return other instanceof Person1; } @Override public int hashCode() { final int PRIME = 59; int result = 1; final long $id = this.getId(); result = result * PRIME + (int) ($id >>> 32 ^ $id); final Object $name = this.getName(); result = result * PRIME + ($name == null ? 43 : $name.hashCode()); final Object $notes = this.getNotes(); result = result * PRIME + ($notes == null ? 43 : $notes.hashCode()); return result; } }
equals, hashCodeから除外するフィールドを指定する
@EqualsAndHashCode
を付与するとデフォルトでは全メンバをもとにequals
, hashCode
がオーバライドされますが、
exclude
パラメータにフィールド名を指定すると、equals
, hashCode
の処理から除外することができます。
■@EqualsAndHashCodeを付与したクラス
excludeの対象にnotesを指定しています。
import java.util.List; import lombok.EqualsAndHashCode; @EqualsAndHashCode(exclude={"notes"}) public class Person2 { private long id; private String name; private List<String> notes; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<String> getNotes() { return notes; } public void setNotes(List<String> notes) { this.notes = notes; } }
■実際に生成されるソースコード
equals
とhashCode
の処理内にnotesフィールドが含まれていないことが分かります。
import java.util.List; public class Person2 { private long id; private String name; private List<String> notes; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<String> getNotes() { return notes; } public void setNotes(List<String> notes) { this.notes = notes; } @Override public boolean equals(final Object o) { if (o == this) return true; if (!(o instanceof Person2)) return false; final Person2 other = (Person2) o; if (!other.canEqual((Object) this)) return false; if (this.getId() != other.getId()) return false; final Object this$name = this.getName(); final Object other$name = other.getName(); if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false; return true; } protected boolean canEqual(final Object other) { return other instanceof Person2; } @Override public int hashCode() { final int PRIME = 59; int result = 1; final long $id = this.getId(); result = result * PRIME + (int) ($id >>> 32 ^ $id); final Object $name = this.getName(); result = result * PRIME + ($name == null ? 43 : $name.hashCode()); return result; } }
equals, hashCodeの対象に含めるフィールドを指定する
of
パラメータを使用することで、equals
, hashCode
の処理に含めるフィールドを明示的に指定することができます
■@EqualsAndHashCodeを付与したクラス
import java.util.List; import lombok.EqualsAndHashCode; @EqualsAndHashCode(of={"id"}) public class Person3 { private long id; private String name; private List<String> notes; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<String> getNotes() { return notes; } public void setNotes(List<String> notes) { this.notes = notes; } }
■実際に生成されるソースコード
idフィールドをもとに、equals
, hashCode
の処理が生成されていることが分かります
import java.util.List; public class Person3 { private long id; private String name; private List<String> notes; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<String> getNotes() { return notes; } public void setNotes(List<String> notes) { this.notes = notes; } @Override public boolean equals(final Object o) { if (o == this) return true; if (!(o instanceof Person3)) return false; final Person3 other = (Person3) o; if (!other.canEqual((Object) this)) return false; if (this.getId() != other.getId()) return false; return true; } protected boolean canEqual(final Object other) { return other instanceof Person3; } @Override public int hashCode() { final int PRIME = 59; int result = 1; final long $id = this.getId(); result = result * PRIME + (int) ($id >>> 32 ^ $id); return result; } }