1. Concept
##==: The operation The symbol generates a boolean result, which calculates the relationship between the values of the operands
equals: ##Object's instance method, compares the content# of two objects ##Is it the same
Object’s native method, get the object The hash value is used to determine the index position of the object in the hash table. It is actually an int typeinteger
2. Relational operators==Basic
Data typeThere are eight basic data types in Java:
Floating point type:
float(4 byte), double(8 byte) Integer type: byte(1 byte), short(2 byte), int(4 byte), long(8 byte) Character type: char(2 byte)
Boolean type: boolean (JVM specification does not clearly stipulate the space size it occupies, but only stipulates that it can only take the literal values "true" and "false")
For variables of these eight basic data types, the variables directly store "values". Therefore, when comparing using the relational operator ==, what is being compared is the "value" itself.
It should be noted that Floating point types and integer types are both signed types (the highest bit is only used to represent positive and negative, and does not participate in calculations [Take byte as an example, its range is -2^7 ~ 2^7 - 1, -0 is -128]), and char is an unsigned type (all bits are involved in the calculation, so the value range of the char type is 0~2^16-1).
variables of reference type are stored together Not the "value" itself, but the address
in memory of the object associated with it. For example, the following line of code, String str1;
This sentence declares a reference type variable, which is not associated with any object at this time.
str1= new String("hello");
. The references here are very similar to pointers in C/C++. 2. Summary
Therefore, for the relational operator ==:If the type of the operand is
, then the relational operator determines whether the values of the left and right operands are equalIf the type of the operand is
, then the relational operator determines the memory address of the left and right operands Are they the same. In other words, if true is returned at this time, the operator must be acting on the same object.
3. equals method
Statement in Object: public boolean equals(Object obj) {}
2. The role of equals method
Judge the difference between two objects
content Is it the same In order to understand the role of the equals method more intuitively, let’s first look at the implementation of the equals method in the Object class.
public boolean equals(Object obj) { return (this == obj); }
但我们都知道,下面代码输出为 true:
public class Main { public static void main(String[] args) { String str1 = new String("hello"); String str2 = new String("hello"); System.out.println(str1.equals(str2)); } }
原来是 String 类重写了 equals 方法:
public boolean equals(Object anObject) { // 方法签名与 Object类 中的一致 if (this == anObject) { // 先判断引用是否相同(是否为同一对象), return true; } if (anObject instanceof String) { // 再判断类型是否一致, // 最后判断内容是否一致. String anotherString = (String)anObject; int n = count; if (n == anotherString.count) { char v1[] = value; char v2[] = anotherString.value; int i = offset; int j = anotherString.offset; while (n-- != 0) { if (v1[i++] != v2[j++]) return false; } return true; } } return false; }
即对于诸如“字符串比较时用的什么方法,内部实现如何?”之类问题的回答即为:
使用equals方法,内部实现分为三个步骤:
先 比较引用是否相同(是否为同一对象),
再 判断类型是否一致(是否为同一类型),
最后 比较内容是否一致
Java 中所有内置的类的 equals 方法的实现步骤均是如此,特别是诸如 Integer,Double 等包装器类。
3、equals 重写原则
对象内容的比较才是设计equals()的真正目的,Java语言对equals()的要求如下,这些要求是重写该方法时必须遵循的:
对称性: 如果x.equals(y)返回是“true”,那么y.equals(x)也应该返回是“true” ;
自反性: x.equals(x)必须返回是“true” ;
类推性: 如果x.equals(y)返回是“true”,而且y.equals(z)返回是“true”,那么z.equals(x)也应该返回是“true” ;
一致性: 如果x.equals(y)返回是“true”,只要x和y内容一直不变,不管你重复x.equals(y)多少次,返回都是“true” ;
对称性: 如果x.equals(y)返回是“true”,那么y.equals(x)也应该返回是“true”。
任何情况下,x.equals(null)【应使用关系比较符 ==】,永远返回是“false”;x.equals(和x不同类型的对象)永远返回是“false”
4、小结
因此,对于 equals 方法:
其本意 是 比较两个对象的 content 是否相同
必要的时候,我们需要重写该方法,避免违背本意,且要遵循上述原则
1、hashCode 的来源
hashCode 方法是基类Object中的 实例native方法,因此对所有继承于Object的类都会有该方法。
在 Object类 中的声明(native方法暗示这些方法是有实现体的,但并不提供实现体,因为其实现体是由非java语言在外面实现的):
public native int hashCode();
2、哈希相关概念
我们首先来了解一下哈希表:
概念 : Hash 就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出(int),该输出就是散列值。这种转换是一种 压缩映射,也就是说,散列值的空间通常远小于输入的空间。不同的输入可能会散列成相同的输出,从而不可能从散列值来唯一的确定输入值。简单的说,就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。
应用–数据结构 : 数组的特点是:寻址容易,插入和删除困难; 而链表的特点是:寻址困难,插入和删除容易。那么我们能不能综合两者的特性,做出一种寻址容易,插入和删除也容易的数据结构?答案是肯定的,这就是我们要提起的哈希表,哈希表有多种不同的实现方法,我接下来解释的是最常用的一种方法——拉链法,我们可以理解为 “链表的数组”,如图:
图1 哈希表示例
The left side is obviously an array, and each member of the array is a linked list. All elements held by this data structure contain a pointer for linking between elements. We assign elements to different linked lists based on their own characteristics. We also find the correct linked list based on these characteristics, and then find the element from the linked list. Among them, the method of calculating the element array subscript based on the element characteristics is the hashing method.
The scope of application of the zipper method: The basic data structure for quick search and deletion usually requires the total amount of data to be put into memory.
Key points:
Hash function selection, for strings, integers, permutations, specific corresponding hash methods;
Collision processing, one is Open hashing is also called the zipper method, and the other is closed hashing, also called the open addressing method.
3. Brief description of hashCode
In Java, The hashCode method defined by the Object class will return different integers for different objects. (This is accomplished by converting the object's internal address to an integer, but the JavaTM Programming Language does not require this implementation trick).
The general contract of hashCode is:
During the execution of a Java application, multiple calls to the same object hashCode method must consistently return the same integer, provided that the information used to compare objects with equals has not been modified. This integer does not need to be consistent from one execution of an application to another execution of the same application.
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
If the two objects are not equal according to the equals(java.lang.Object) method, then call hashCode on either of the two objects. Method does not require to necessarily generate different integer results. However, programmers should be aware that generating different integer results for unequal objects can improve hash table performance.
To further understand the role of hashCode, we must first understand the container in Java, Because HashCode is only useful in data structures that require the use of hash algorithms, such as HashSet, HashMap and Hashtable.
There are three types of collections in Java, one is List, the other is Queue, and the third is Set. The elements in the first two sets are ordered, and the elements can be repeated; the elements in the last set are unordered, but the elements cannot be repeated.
So, here is a more serious problem: if you want to ensure that elements are not repeated, what should be the basis for judging whether two elements are repeated? This is the Object.equals method. However, if you check once every time an element is added, then when there are many elements, the number of comparisons of elements added to the collection will be very large. In other words, if there are now 1000 elements in the collection, then when the 1001 element is added to the collection, it will call the equals method 1000 times. This will obviously greatly reduce efficiency. Therefore, Java adopts the principle of hash table. In this way, we use the hash algorithm to calculate a value for each element to be stored in the collection, and then calculate the position of the element in the array based on this value. Therefore, when a new element is added to the collection, it can be divided into two steps:
##First call the hashCode method of this element, and then based on the The resulting value calculates where the element should be in the array. If there is no element at this position, then store it directly at this position;
If there is already an element at this position, Then call its equals method to compare with the new element: if it is the same, it will not be stored. Otherwise, it will be stored in the linked list corresponding to this position (the implementation of HashSet, HashMap and Hashtable in Java always puts the element at the head of the linked list) .
When it comes to hashCode, we have to talk about the equals method. Both are methods in the Object class. Since the Object class is the base class of all classes, these two methods can be overridden in all classes.
If x.equals(y) returns "true", then the hashCode() of x and y must be equal;
If x.equals(y) returns "false", then the hashCode() of x and y may be equal or different;
原则 3 : 如果 x 和 y 的 hashCode() 不相等,那么 x.equals(y) 一定返回 “false” ;
原则 4 : 一般来讲,equals 这个方法是给用户调用的,而 hashcode 方法一般用户不会去调用 ;
原则 5 : 当一个对象类型作为集合对象的元素时,那么这个对象应该拥有自己的equals()和hashCode()设计,而且要遵守前面所说的几个原则。
5、实现例证
hashCode()在object类中定义如下:
public native int hashCode();
说明是一个本地方法,它的实现是根据本地机器相关的。
String 类是这样重写它的:
public final class String implements java.io.Serializable, Comparable<String>, CharSequence{ /** The value is used for character storage. */ private final char value[]; //成员变量1 /** The offset is the first index of the storage that is used. */ private final int offset; //成员变量2 /** The count is the number of characters in the String. */ private final int count; //成员变量3 /** Cache the hash code for the string */ private int hash; // Default to 0 //非成员变量 public int hashCode() { int h = hash; int len = count; //用到成员变量3 if (h == 0 && len > 0) { int off = offset; //用到成员变量2 char val[] = value; //用到成员变量1 for (int i = 0; i < len; i++) { h = 31*h + val[off++]; //递推公式 } hash = h; } return h; } }
对程序的解释:h = s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
,由此可以看出,对象的hash地址不一定是实际的内存地址。
hashcode是系统用来快速检索对象而使用
equals方法本意是用来判断引用的对象是否一致
重写equals方法和hashcode方法时,equals方法中用到的成员变量也必定会在hashcode方法中用到,只不过前者作为比较项,后者作为生成摘要的信息项,本质上所用到的数据是一样的,从而保证二者的一致性
The above is the detailed content of Sample code that explains in detail the differences and connections between ==, equals and hashCode in Java. For more information, please follow other related articles on the PHP Chinese website!