Collection接口存储一组不唯一,无序的对象
Set接口继承Collection接口,存储一组唯一,无序的对象
List接口继承Collection接口,存储一组不唯一,有序的对象.
Map接口存储一组成对的键-值对象,提供key到value的映射。Map中的key不要求有序,不允许重复。value同样不要求有序。但可以重复
ArrayList继承自List接口 下面这个实例体现了ArryList的存储方式:
package itcast;
import java.util.ArrayList;
import java.util.Collection;
public class ReflectTest2 {
public static void main(String[] args){
Collection collections = new ArrayList(); //定义了一个ArrayList()对象
//使用构造方法public ReflectPoint(int a,int b) new出3个ReflectPoint对象
ReflectPoint rp1 = new ReflectPoint(3,3);
ReflectPoint rp2 = new ReflectPoint(5,5);
ReflectPoint rp3 = new ReflectPoint(3,3);
//使用ArrayList对象Add()方法添加元素
collections.add(rp1);
collections.add(rp2);
collections.add(rp3);
collections.add(rp1);
System.out.println(collections.size()); //这里的输出结果为4 因为ArrayList继承自List
//List集合存储的是一组不唯一(可以重复),有序的对象
}
}
HashSet继承自Set接口 同样使用上面的例子看看HashSet的存储方式是什么?
package itcast;
import java.util.Collection;
import java.util.HashSet;
public class ReflectTest2 {
public static void main(String[] args){
Collection collections = new HashSet(); //定义了一个HashSet()对象
//使用构造方法public ReflectPoint(int a,int b) new出3个ReflectPoint对象
ReflectPoint rp1 = new ReflectPoint(3,3);
ReflectPoint rp2 = new ReflectPoint(5,5);
ReflectPoint rp3 = new ReflectPoint(3,3);
//使用HashSet对象Add()方法添加元素
collections.add(rp1);
collections.add(rp2);
collections.add(rp3);
collections.add(rp1);
System.out.println(collections.size()); //这里的输出结果变为3 为什么呢? 因为HashSet继承自Set
//Set集合存储的是一组唯一,无序的对象
}
}
对于rp1和rp3是不是同一个对象呢? 如果用双等号来做判断肯定是不等的。但是你作为程序员,因为x和y都相等所以我们希望它们相等。 这时候我们就需要覆盖它们的equals的方法
放覆盖equals方法时我们发现System.out.println(rp1.equals(rp3));的输出结果为true
可是当我们再允许第一个例子时运行结果还是为3 这又是为什么呢?
这时候我们就需要了解HashSet的存储方式和hashCode()这个方法的作用
HashSet:
如果想查找一个集合众是否包含有某个对象,大概的程序代码怎样写呢?你通常是逐一
取出每个元素与药查找的对象进行比较,当发现某个元素与药查找的对象进行equals方法比较的结果相等时,
则停止继续查找并返回肯定的信息,否则返回否定的信息。如果一个集合中有很多个元素,例如有一万个元素,并且没有包含要查找的
的对象时,则意味着你的程序需要从该集合众取出一万个元素逐一比较才能得到结论。有人发明了一种哈希算法来提高从集合众查找元素的效率
这种方式将集合分成若干个存储区域,每个对象可以计算出一个哈希吗,可以将哈希吗分组,每组分别对应
某个存储区域,根据一个对象的哈希吗就可以确定该对象应该存储在哪个区域
HashSet就是采用哈希算法存取对象的集合,它内部采用对某个数字n进行取余的方式对哈希吗进行分组
和划分对象的存储区域。可见hashSet集合具有很好的对象检索性能
但是HashSet集合存储对象的效率相对低些
hashCode():Object类定义了一个hashCone()方法来返回每个Java对象的哈希吗
当从HashSet集合众查找某个对象时,Java系统首先调用对象的hashCode()方法来获得该对象的哈希吗。然后根据哈希吗找到相应的存储区域,最后取出该存储区域
内的每个元素与该对象进行equals方法比较,这样不用遍历集合中的所有元素就可以得到结论。
当我们覆盖hashCode()方法时,我们发现System.out.println(collections.size());的输出结果变为2了。
什么时候才要覆盖hashCode()方法呢?
只有类的实例对象要被采用哈希算法进行存储和检索时,这个类才需要按要求覆盖hashCode方法。即使程序可能暂时不会用到当前类的hashcode()方法,
但是为它提供一个hashcode方法也不会有什么不好,没准以后什么时候又用到了这个方法了,所以,通常要求hashcode方法和equals方法一并被同时覆盖
提示:
(1)通常来说,一个类的两个实例对象用equals()方法比较结果相等时,它们的哈希吗也必须相等,但反之则不成立,即equals方法比较结果不相等的对象可以有
相同的哈希吗,或者说哈希吗相同的两个对象的equals方法比较的结果可以不等,例如字符串"BB"和"Aa"的equals方法比较结果肯定不相等,但它们的hashcode方法返回值却相等。
(2)当一个对象被存储进hashSet集合中以后,就不能修改这个对象中的那些参与计算的哈希值得字段了,否则,对象修改后的哈希值与最初存储进hashSet集合众时
的哈希值就不同了,在这种情况下,即使在contains方法使用该对象的当前引用作为参数去HashSet集合众检索对象,也将返回找不到对象的结果,这也会导致无法从HashSet集合中单独删除当前对象,从而造成内存泄露
|
|