vector线程安全的集合
hashset底层为hashmap
文章目录
- 1 “==”和equals的区别是什么?
- 1.1 “==”解释
- 1.2 “equals”解释
- 1.3 注意点:equals不能比较基本数据类型
- 1.4 Integter缓存数组
- 1.4.1 引入案例发现问题
- 1.4.2 解释缓存数组
- 1.5 字符串常量池
- 1.5.1 案例一
- 1.5.2 案例二
- 1.5.3 案例三
- 1.5.4 案例4
- 1.5.5 案例5
- 1.5.6 案例6
- 1.5.7 案例7
- 1.5.8 案例8
- 1.5.9 案例9
- 2 两个对象的hashcode值相同,则equals是否也相同?
- 2.1 不对,两者间没有太大的关系
- 2.2 重写的hashCode方法调用
- 2.3 Arrays的hashCode方法
- 3 重写equals的时候需不需要重写hashcode呢?
1 “==”和equals的区别是什么?
- “= =”是运算符,如果是基本数据类型,比较是存储的值: int i = 100; int j = 100; i= =j;true
- 若是引用数据类型,比较的是所指向对象的地址值:User user1 = new User(); User user2 = new User(); user1= =user2; false
1.1 “==”解释
“==”是运算符
- ① 若相比对象是基本数据类型,则比较存储值是否相等;
- ② 若相比是引用数据类型,则比较是所指向对象的地址值是否相等。
案例:
final String str2 = "ab";//在字符串常量池中创建“ab”,并将地址值赋值给str2
System.out.println(str2);
final String str3 = "cd";//在字符串常量池中创建“cd”,并将地址值赋值给str3
System.out.println(str3);
String str6 = new String("abcd");//在堆中开辟地址空间,并把得到的地址值赋值给str6
String str4 = str2+str3;//在字符串常量池中得到abcd的地址
System.out.println(str4);
String str5 = "abcd";//在字符串常量池中创建abcd时,发现已有,不用创建,就使用创建好的地址值
System.out.println("str4 = str5 : " + (str4==str5));//true
System.out.println("str6 = str5 : " + (str6==str5));//false
1.2 “equals”解释
equals是Object的方法,用来比较两个对象地址值是否相等。
源码如下(其底层仍是“==”):
案例:
final String str2 = "ab";//在字符串常量池中创建“ab”,并将地址值赋值给str2
System.out.println(str2);
final String str3 = "cd";//在字符串常量池中创建“cd”,并将地址值赋值给str3
System.out.println(str3);
String str6 = new String("abcd");//在堆中开辟地址空间,并把得到的地址值赋值给str6
String str4 = str2+str3;//在字符串常量池中得到abcd的地址
System.out.println(str4);
String str5 = "abcd";//在字符串常量池中创建abcd时,发现已有,不用创建,就使用创建好的地址值
System.out.println("str4 = str5 : " + (str4==str5));//true
System.out.println("str6 = str5 : " + (str6==str5));//false
System.out.println(str6.equals(str4)); //true :String底层重写了equals比较的是对象的内容
1.3 注意点:equals不能比较基本数据类型
equals不能用于比较基本数据类型,如果没有对equals进行重写,则相当于“==”,比较的是引用数据类型变量所指地址值。
- 注意:我们自定义的对象需要重写equals方法,一般情况下,类会重写equals方法用来比较两对象内容是否相等。如:String类中的equals()是被重写了,比较的是对象的内容。
1.4 Integter缓存数组
1.4.1 引入案例发现问题
问题:我们发现,首先Integter是引用数据类型,但是,我们在做这两次
比较判断
的时候,却得到了两次不一样结果
,如果说第二个FALSE得出是正常的,那第一个TRUE出现究极奇怪。
1.4.2 解释缓存数组
- ① Integter有一个缓冲数组,将-128~127的所有数值,创建成Integter对象,提前放入到数组中。
- ② i=100和i2=100,都是从数组中获取Integter对象,因为获取的是同一个,所以最终结果返回TRUE。
- ③i3=300和i4=300,因为数组中不存在,则需new Integter()创建两次对象,两次对象的地址值不同,所以结果返回FALSE。
1.5 字符串常量池
注意:“==”号,在引用数据类型中,比较的都是
地址值
。
1.5.1 案例一
final String str2 = "ab";//在字符串常量池中创建“ab”,并将地址值赋值给str2
System.out.println(str2);
final String str3 = "cd";//在字符串常量池中创建“cd”,并将地址值赋值给str3
System.out.println(str3);
String str6 = new String("abcd");//在堆中开辟地址空间,并把得到的地址值赋值给str6
String str4 = str2+str3;//在字符串常量池中得到abcd的地址
System.out.println(str4);
String str5 = "abcd";//在字符串常量池中创建abcd时,发现已有,不用创建,就使用创建好的地址值
System.out.println("str4 = str5 : " + (str4==str5));//true
System.out.println("str6 = str5 : " + (str6==str5));//false
System.out.println(str6.equals(str4)); //true :String底层重写了equals比较的是对象的内容
1.5.2 案例二
String s1 = new String("abc");//堆中开辟新空间,得到新地址值
String s2 = new String("abc");//堆中开辟新空间,得到新地址值
System.out.println(s1 == s2);//false
System.out.println(s1.equals(s2)); // true:底层重写了equals方法
1.5.3 案例三
String s1 = "abc";//字符串常量池中创建abc,得到地址值
String s2 = new String("abc");//堆中开辟新空间,得到新地址值
s2.intern();//可以拿到s2的常量
System.out.println(s1 ==s2);//false
1.5.4 案例4
String str1 = "ab" + "cd";//先做计算得到abcd,字符串常量池中创建,并得到地址值
String str11 = "abcd";//字符串常量池发现已有,直接得到地址值
System.out.println("str1 = str11 : "+ (str1 == str11)); //TRUE
1.5.5 案例5
String str2 = "ab";//字符串常量池中创建,并得到地址值
String str3 = "cd";//字符串常量池中创建,并得到地址值
String str4 = str2+str3;//此处相当于str2+new String(str3)
String str5 = "abcd";//字符串常量池发现已有,直接得到地址值
System.out.println("str4 = str5 : " + (str4==str5));//false
1.5.6 案例6
final String str2 = "ab";//被final修饰的变量只能被赋值一次
final String str3 = "cd";//被final修饰的变量只能被赋值一次
String str4 = str2+str3;//“ab”+"cd"="abcd",并在字符串常量池中创建abcd,得到地址值
String str5 = "abcd";//字符串常量池发现已有,直接得到地址值
System.out.println("str4 = str5 : " + (str4==str5));//TRUE
1.5.7 案例7
String str6 = "b";//字符串常量池中创建b,得到其地址值
String str7 = "a" + str6;//此处相等于:“a”+new String(str6)
String str67 = "ab";//字符串常量池中创建ab,得到其地址
System.out.println("str7 = str67 : "+ (str7 == str67));//false
1.5.8 案例8
final String str8 = "b";//final修饰的变量,只能被赋值一次
String str9 = "a" + str8;//此处相等于:“a”+“b”先做计算得到值:ab,并在字符串常量池中创建ab,得到其地址值
String str89 = "ab";//在字符串常量池中,创建ab是发现已有,得到其地址值
System.out.println("str9 = str89 : "+ (str9 == str89)); //TRUE
1.5.9 案例9
String s1="Hello";//字符串常量池中创建并得到地址值
String s2="hello";//字符串常量池中创建并得到地址值
String s3=s1.toLowerCase();//将大写转为小写,但是地址值仍是先前的
String s4=s2.toLowerCase();//将大写转为小写,但是地址值仍是先前的
System.out.println(s3==s4);//false,==号在引用数据类型是比较的是地址值
2 两个对象的hashcode值相同,则equals是否也相同?
2.1 不对,两者间没有太大的关系
2.2 重写的hashCode方法调用
调用时以下算法
2.3 Arrays的hashCode方法
element.hashCode方法是native(用C语言写的)方法,无法再查看源码,不过能确定的是用个了啥算法。
因此,极端情况下,会发生哈希碰撞,即出现地址值相同结果
3 重写equals的时候需不需要重写hashcode呢?
需要重写
- ① 当重写了equals和hashcode时,比如给HashMap存入数据时,先计算key的hash值,然后对数组长度取余,得到key在数组照片那个存储的位置,其次使用equals比对要存入的位置是否已有相同的数据,若相同,则替换,若不同,存入数组下面的链表中。
- ②若自定义类中,没有重写hashcode方法,会调用其父类Object中的hashcode方法,默认是根据地址进行哈希运算,结果:
两个值相同的对象实例,其hashcode值不一样,存入相同值在Map中
。