万网主机 建网站,深圳个人网站制作,什么网站可以免费做试卷,做互助盘网站找哪家好和谐 平等将对象存储在集合中时#xff0c;同一对象永远不能添加两次很重要。 这是集合的核心定义。 在Java中#xff0c;使用两种方法来确定两个引用的对象是否相同#xff0c;或者它们都可以存在于同一Set中。 equals#xff08;#xff09;和hashCode#xff08;… 和谐 平等 将对象存储在集合中时同一对象永远不能添加两次很重要。 这是集合的核心定义。 在Java中使用两种方法来确定两个引用的对象是否相同或者它们都可以存在于同一Set中。 equals和hashCode。 在本文中我将解释平等与同一性之间的区别并探讨它们在彼此之间所具有的一些优势。 Java提供了这两种方法的标准实现。 标准的equals方法被定义为“身份”比较方法。 这意味着它将比较两个内存引用以确定它们是否相同。 因此存储在内存中不同位置的两个相同的对象将被视为不相等。 如果使用Object类的源代码可以使用-operator进行比较。 public boolean equals(Object obj) {return (this obj);
} hashCode方法由虚拟机作为本机操作实现因此在代码中不可见但通常将其实现为简单地返回内存引用在32位架构上或以32位模表示内存引用在64位体系结构上。 许多程序员在设计类时选择要做的一件事就是用不同的相等性定义覆盖此方法在该方法中您不查看比较内存引用而是查看两个实例的值以查看它们是否可以相等。 这是一个例子 import java.util.Objects;
import static java.util.Objects.requireNonNull;public final class Person {private final String firstname;private final String lastname;public Person(String firstname, String lastname) {this.firstname requireNonNull(firstname);this.lastname requireNonNull(lastname);}Overridepublic int hashCode() {int hash 7;hash 83 * hash Objects.hashCode(this.firstname);hash 83 * hash Objects.hashCode(this.lastname);return hash;}Overridepublic boolean equals(Object obj) {if (this obj) return true;if (obj null) return false;if (getClass() ! obj.getClass()) return false;final Person other (Person) obj;if (!Objects.equals(this.firstname, other.firstname)) {return false;} else return Objects.equals(this.lastname, other.lastname);}
} 这种比较称为“平等”与之前的“身份”相比。 只要两个人的名字和姓氏相同就将被视为相等。 例如这可以用于从输入流中筛选出重复项。 请记住如果您覆盖equals方法则还应该始终覆盖hashCode方法 平等 现在如果您选择平等而非身份则需要考虑一些事项。 您必须问自己的第一件事是具有相同属性的此类的两个实例是否一定相同 对于上述人员我会拒绝。 有一天您的系统中很有可能会有两个姓氏和名字相同的人。 即使您继续添加更多的个人信息例如生日或喜欢的颜色您迟早也会发生冲突。 另一方面如果您的系统正在处理汽车并且每辆汽车都包含对“模型”的引用则可以安全地假定如果两辆汽车都是黑色Tesla S模型则即使对象是汽车它们也可能是同一模型。存储在内存中的不同位置。 这是平等可能很好的一个例子。 import java.util.Objects;
import static java.util.Objects.requireNonNull;public final class Car {public static final class Model {private final String name;private final String version;public Model(String name, String version) {this.name requireNonNull(name);this.version requireNonNull(version);}Overridepublic int hashCode() {int hash 5;hash 23 * hash Objects.hashCode(this.name);hash 23 * hash Objects.hashCode(this.version);return hash;}Overridepublic boolean equals(Object obj) {if (this obj) return true;if (obj null) return false;if (getClass() ! obj.getClass()) return false;final Model other (Model) obj;if (!Objects.equals(this.name, other.name)) {return false;} else return Objects.equals(this.version, other.version);}}private final String color;private final Model model;public Car(String color, Model model) {this.color requireNonNull(color);this.model requireNonNull(model);}public Model getModel() {return model;}
} 如果两辆汽车的内存地址相同则它们被认为是相同的。 另一方面只要它们具有相同的名称和版本则认为它们的模型相同。 这是一个例子 final Car a new Car(black, new Car.Model(Tesla, Model S));
final Car b new Car(black, new Car.Model(Tesla, Model S));System.out.println(Is a and b the same car? a.equals(b));
System.out.println(Is a and b the same model? a.getModel().equals(b.getModel()));// Prints the following:
// Is a and b the same car? false
// Is a and b the same model? true身分识别 选择平等而不是身份的一种风险是它可能会导致分配比堆上更多的对象。 只需看上面的汽车示例。 对于我们创建的每辆汽车我们还为模型分配内存中的空间。 即使java通常优化了字符串分配以防止重复对于始终相同的对象仍然是一定的浪费。 将内部对象转换为可以使用身份比较方法进行比较并同时避免不必要的对象分配的一个简单技巧是将其替换为枚举 public final class Car {public enum Model {TESLA_MODEL_S (Tesla, Model S),VOLVO_V70 (Volvo, V70);private final String name;private final String version;Model(String name, String version) {this.name name;this.version version;}}private final String color;private final Model model;public Car(String color, Model model) {this.color requireNonNull(color);this.model requireNonNull(model);}public Model getModel() {return model;}
} 现在我们可以确定每种模型只会在内存中的某个位置存在因此可以使用身份比较安全地进行比较。 然而与此有关的一个问题是这实际上限制了我们的可扩展性。 在此之前可以在不修改Car.java文件中的源代码的情况下即时定义新模型的方法但是现在我们已经将自己锁定在一个枚举中该枚举通常应该保持不变。 如果需要这些属性那么对等比较可能更适合您。 最后一点如果您重写了类的equals和hashCode方法后来又想根据身份将其存储在Map中则始终可以使用IdentityHashMap结构。 即使equals和hashCode方法已被覆盖它也会使用内存地址来引用其键。 翻译自: https://www.javacodegeeks.com/2016/03/equality-vs-identity.html和谐 平等