主要内容

  1. java中的==、equals()和hashCode()
  2. 算法题leetcode[15]:3Sum

java中的==、equals()和hashCode()

“==”运算符

首先来看最基础的==符号,它比较的是变量(栈)内存中存放的对象(堆)的内存地址,用来判断两个对象的地址是否相同,即是否指向同一个对象。
简单来说==比较的是,是否指向同一个对象(堆)

1
2
3
4
5
6
7
8
9
10
11
12
public static void main(String[] args) {
String str1=new String("abc");
String str2=new String("abc");

String str3="efg";
String str4="efg";
System.out.println(str1==str2);
System.out.println(str3==str4);
//输出:
//false
//true
}

现象解释:str1==str2输出false,是因为str1和str2虽然存储的字符串相同,但是它们各自new了自己单独的对象,而==比较的是指向的对象是否相同,所以输出false。
str3==str4是因为java中变量池的存在,定义str3和str4的时候,java回到变量池中寻找是否存在已经定义过的,如果有已经定义了的,那么直接将引用指向它就可以了,不必再重新新建对象了。因为str3和str4指向同一个对象,所以str3==str4为true。

equals()

首先看一段代码我们写了一个Myobj,并new了两个对象,分别使用==和equals()来进行比较

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Test {
public static void main(String[] args) {

Myobj obj1=new Myobj("aaa");
Myobj obj2=new Myobj("aaa");
System.out.println(obj1==obj2);
System.out.println(obj1.equals(obj2));
//输出
//false
//false
}

}
class Myobj{
String name;
public Myobj(String name){
this.name=name;
}
}

现象解释:
obj1==obj2输出false,很好理解,因为==比较的是指向的对象是否是同一个,因为obj1和obj2指向了它们各自new的对象,所以为false。
obj1.equals(obj2)输出false,是因为我们在Myobj没有重写equals()方法,使用的是Object中的equals()方法.
Object类中的equals()方法的实现

1
2
3
public boolean equals(Object obj) {
return (this == obj);
}

看到了Object类中的equals()方法的实现,对obj1.equals(obj2)输出false也很好理解了,因为它本质上和obj1==obj2是一样的。
重写equals()方法:
如果我们认为name相同的MyObject对象就是equals的的话,我们就需要重写equals()方法了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class Test {
public static void main(String[] args) {

Myobj obj1=new Myobj("aaa");
Myobj obj2=new Myobj("aaa");
System.out.println(obj1==obj2);
System.out.println(obj1.equals(obj2));
//输出;
//false
//true
}
}
class Myobj{
public String name;
public Myobj(String name){
this.name=name;
}
public boolean equals(Myobj obj){
return this.name.equals(obj.name);
}
}

hashCode()

  1. hashCode()方法的作用是什么
    HashCode()方法主要是在哈希表中起作用,如HashSet、HashMap等。单我们向哈希表中添加对象的时候,首先会调用hashCode()方法计算Object的哈希码,根据哈希码的值,确定该对象在哈希表中的位置,如果该位置已经有对象了,那么就调用equals()比较这些对象与Object是否相等,如果相等,则不需要保存object对象,如果不相等,则把对象加入链表中。
    这也就解释了equals()相等,则hashCode()必须相等,如果两个对象equals相等,那么它们在哈希表中应该只出现一次,如果hashCode不相等,那么它们会被散列到哈希表中的不同位置,就不止出现一次了。

重写hashCode()
几个原则:

  1. equals相等,则hashCode必须相等(重点)
  2. hashCode不能太简单,否则哈希冲突会很多
  3. hashCode不能太复杂,否则计算耗时,影响性能

Object类中的hashCode方法:

1
public native int hashCode();

重写hashcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class Test {
public static void main(String[] args) {

Myobj obj1=new Myobj("aaa",1);
Myobj obj2=new Myobj("aaa",1);

System.out.println(obj1.equals(obj2));
System.out.println(obj1.hashCode()==obj2.hashCode());
}

}

class Myobj{
public String name;
public int id;
public Myobj(String name,int id){
this.name=name;
this.id=id;
}

public boolean equals(Myobj obj){
return this.name.equals(obj.name)&&this.id==obj.id;
}

@Override
public int hashCode(){
int hash=17;
//选取了equals方法中的两个用于比较的域name和id
hash=hash*31+name.hashCode();
hash=hash*31+id;
return hash;
}
}

《Effective Java》中提出的一种重写hashCode的方法:

  1. 初始化一个整形变量,并赋予一个非零的常数
  2. 选取equals方法中用于比较的所有域,然后针对每个域的属性进行计算(确保原则一)
  3. 将每个域的散列码合并到对象的哈希码中

算法题leetcode[15]:3Sum

题目:
Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Note:
The solution set must not contain duplicate triplets.

Example:
Given array nums = [-1, 0, 1, 2, -1, -4],
A solution set is:
[
[-1, 0, 1],
[-1, -1, 2]
]

分析:
首先对数据进行排序,然后固定也给位置,从两边进行夹逼。

解法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class Solution {
List<List<Integer>> result=new ArrayList<List<Integer>>();
public List<List<Integer>> threeSum(int[] nums) {
//用于存储结果

if(nums==null||nums.length<3){
return result;
}
// 首先进行排序
Arrays.sort(nums);
//首先国定一个位置,再去寻找另外两个数
for(int i=0;i<nums.length-2;i++){
if(i>0&&nums[i]==nums[i-1]){
continue;
}
find(nums,i+1,nums.length-1,nums[i]);
}

return result;

}
private void find(int[] nums,int begin,int end,int target){
int l=begin;
int r=end;
while(l<r){
if((nums[l]+nums[r]+target)==0){
List<Integer> list=new ArrayList<Integer>();
list.add(target);
list.add(nums[l]);
list.add(nums[r]);
result.add(list); //加入结果集
while(l<r&&nums[l]==nums[l+1]){
l++;
}
while(l<r&&nums[r]==nums[r-1]){
r--;
}
l++;
r--;
}else if((nums[l]+nums[r]+target)<0){
l++;
}else{
r--;
}
}
}
}