一、set接口和List接口中的区别
注意:set接口中的方法和Collection接口中的方法一模一样。
二、Set接口的实现类
1、HashSet集合 ,本质是HashMap<>
2、set接口使用
无序例子:
注意:输出时没有按输入时的顺序输出。
3、增强for的形式
不允许存储元素,如果有重复元素不会报错,但是只会输出一个。
三、哈希表的特性
1、其实应该说是哈希链表,首先有一个数组,每个数组元素下是一个链表。这个数组初始时有个容量,当存储元素达到一定量时就会产生哈希表的再哈希(rehash)其中这个一定量就是加载因子。rehash就是重新开辟一个数组,并将之前数组中的内容全部复制进去。相当的耗费时间。
2、哈希表
这张图解释了哈希表的存储过程:首先,哈希表先调用对象的哈希值,通过哈希值来判断哈希表中是否有该对象存在。但是即使哈希值一样也不会放弃存储。因为也许元素不一样但是哈希值确相同,于是接着比较看元素的值是否相同,即:调用对象的equals()方法,如果equals()方法一样,那么就表明该元素真的重复了。
总结一下:先判断对象的哈希值是否相同,若返回true,再调用equals()方法判断对象的值是否相同。如果返回true表示重复,不会存储到哈希表上。
注意:String类重写了父类的HashCode方法,重写的结果就是:new String("abc") 不管new几次只要字符相同,HashCode都相同。
此外Object的HashCode方法是不可见的。没有开源。如图所示:
四、哈希表面临的问题
上图是new String(),由于String类重写了HashCode方法,导致实例化HashCode值相同。如果对象是自定义类。当存储相同的值时会出现HashCode的值就会不同。就会打印出相同的值。那么如何避免打印相同的值呢?如图:
如上图:由于是自定义对象,导致能存储看着相同的值,其实是匿名对象,他们的hashcode固然不同,所以被存进去了。对于用户来说如何将这些相同的值当做一个对象呢?
那就需要重写hashCode方法。
首先:设置无重复值的过程有两步,一是通过比较hashCode,如果hashCode相同就比较equals()方法。如果也相同就表明存储的内容重复。
其中第一步是:让相同的对象得到相同的哈希值。equals()方法是比较不同对象却又有相同哈希值的情况。通过这两个方法实现了相同数据看成一个对象。为了减少让不同对象却具有相同哈希值的概率。可以通过如下重写hashCode()方法。
对于equals()方法也需要重写。
注意:eclipse可以自动创建hashCode和equals()方法。
五、LinkedHashSet 基于链表的哈希表实现
同样不会存储相同的数据。
注意:八种基本类型都重写了hashCode和equals()方法。
六、两道面试题
但是:如果这样
将静态变量a+1,hashCode每次都会不同。其实sun公司对这个定了一个协议:
1、hashCode相同对象返回值每次必须相等。故返回值不能搞成a+1。
2、equals()方法为true时,hashCode必须相同。
3、equals()方法不为true时,hashCode不一定相同。