JAVA学习-序号2 HashSet初入门,hashCode和equals方法

来源:互联网 发布:会员视频源码 编辑:程序博客网 时间:2024/06/02 02:36

今天学习的是Collection中的foreach遍历,Set集合的基本特点,以及HashSet初入门。

示例代码如下:

   
import java.util.HashSet;import java.util.Set;public class TestSet {    public static void main(String[] args)    {        Set books=new HashSet();        //添加一个字符串对象        books.add(new String("Struts"));        //再次添加相同字符串,因俩者用equals方法比较,所以添加失败,返回false        boolean results=books.add(new String ("Struts"));        books.add("Struts");        System.out.println(books);    }}

        从中可以看出,Set集合中不允许出现相同元素,我的理解是相同的值不行,变量相同也不行。

        两个add方法中的变量都是new string出来的,可以说只是值相同而已,Set集合判断元素相等的方法是equals。书上说通过==运算符来算肯定是false(这是完全等于嘛),但是equals算出来就是true,所以Set里不允许任何值相同的元素。

        另外我注意到一点,为什么创建集合的时候都是Setbooks=newHashSet();这种语法,包括前面的Collection也是,后面指向的是子类的对象,就为了单纯体现出多态?后来我用Setbooks=newSet();试了一下,结果发现idea自动给你把好多方法写在{}里等你完善。作为初学者我终于有点明白,你为了调用Set集合类你就要通过子类把方法的实现给讲出来啊,不然要完全实现这个Set有多麻烦,还不如现成的HashSet,这个也体现了之前书上讲的“接口体现出规范与实现的分离”好像。可能有些错误=。=

        后来把Set books=new Set();后面接的方法全删了就报错了,指示一些方法没有被定义,这是最基本的了。接下来就讲到HashSet了,Set的一个典型实现类。

HashSet集合元素值可为null。当使用add方法加入元素时,HashSet有俩个方法需要判断,分别是equals()和hashCode()方法的返回值。这个书上说的我云里雾里的,先把代码敲了一遍然后去百度了下,终于弄懂。

        示例代码如下,自己加了个空类d:

import java.util.HashSet;//A的equals()方法总是返回true,但没有重写其hashCode()方法class A {    public boolean equals(Object obj)    {        return true;    }}//B的hashCode()方法总是返回1,但没有重写其equals()方法class B{    public int hashCode()    {        return 1;    }}//C的hashCode()方法总是返回2,但没有重写其equals()方法class C{    public boolean equals(Object obj)    {        return true;    }    public int hashCode()    {        return 2;    }}//dclass d{}public class TestHashSet{    public static void main(String[] args){        HashSet books=new HashSet();        //分别向books集合中添加俩个A对象,俩个B,俩个C        books.add(new A());        books.add(new A());        books.add(new B());        books.add(new B());        books.add(new C());        books.add(new C());        books.add(new d());        books.add(new d());        System.out.println(books);    }}

        结果如下:

[B@1, B@1, C@2, A@74a14482, d@677327b6, A@4554617c, d@1540e19d]

        这里刚开始我就有疑问了,明明我创建的是HashSet,怎么说的是我创建HashSet元素对象时可以重写HashSet的equals和hashCode方法呢,元素不是还可以是非引用类型吗?没方法怎么办。看半天没看懂,一百度清楚了些。

        原来HashSet集合的元素对象所实现的类必须要有equals与hashCode方法而已,并不是集合本身的这俩个方法。而且HashSet在存储元素的时候,可以先判断两个对象的hashCode()返回值是否一样的,如果一样再比较equals方法的返回值。只要相同类的对象是new出来的,然后调用HashSet的add()方法,就注定了hashCode()返回的值不一样,这样不管equals()方法有没有被重写都不会起作用了,因为元素都会被添加进HashSet对象。所以一般来说都要重写hashCode方法,我看网上最常见的就是将元素类的属性进行运算得到hashCode()返回值,这也是最实用的。

        还有一点需要注意,重写equals的时候,一定是这样的传参:public booleanequals(Object obj){},而不能随便定义。也就是形参必须是Object。

        书中还解释了为什么开发者会发明这个HashSet集合。以前学C语言时老师说过,数组元素相当于存放在一连串的内存块中,每个元素都有索引,可能前后的内存块都已经被用了,所以没办法增加长度;而HashSet中的元素hashCode()返回值hashCode决定该元素的存放位置,相当于每个HashSet元素中的索引,且这些集合中的元素不是在内存块中紧密相连的,就像“见缝插针”一样,没有集合长度这个概念的限制,所以HashSet可以自由增加长度。且当HashSet访问元素时,可以直接通过hashCode()返回的位置找到集合元素,所以HashSet的应用速度很快(原理大概理解了)。这也解释了如果equals()总是返回false,但是hashCode相同的话,一个位置可能就放了很多元素,找到元素费时间,程序运行就慢了(书上p249页hashCode方法名写错了,偷笑)。

        借鉴了一下http://blog.csdn.net/dingjingchao/article/details/53150901的代码。弄懂了equals()常见的一种重写方法,黏贴一下:

import java.util.*;class Person{    private String name;    private int age;    Person(String name,int age)    {        this.name=name;        this.age=age;    }    public int hashCode()//重写    {        return name.hashCode()+age ;    }    public boolean equals(Object obj)//重写   Object不能换    {        if(!(obj instanceof Person))            return false;        Person p=(Person)obj;        System.out.println(this.name+"...."+p.name);        return this.name.equals(p.name)&&this.age==p.age;    }    public String getName()    {        return name;    }    public int getAge()    {        return age;    }}public class HashSetDemo{    public static void main(String[] args)    {        HashSet hs=new HashSet();        hs.add(new Person("lisi01",30));        hs.add(new Person("lisi02",33));        hs.add(new Person("lisi03",35));        hs.add(new Person("lisi02",33));        hs.add(new Person("lisi01",30));        hs.add(new Person("lisi04",32));        hs.add(new Person("lisi03",35));        Iterator it=hs.iterator();        while(it.hasNext())        {            Person p=(Person)it.next();;            sop(p.getName()+" "+p.getAge());        }    }    public static void sop(Object obj)    {        System.out.println(obj);    }}

        这上面的代码有些网址上是一样的,想找个时间自己复盘一下。值得一提的是name属性也有hashCode方法。意义是不是直接返回索引地址呢?写了几句代码测试了一下确实是的,int型。本来说好的一天一篇,结果昨天加班就没写了,回来还玩手机到深夜。。。蛋疼,尽量坚持住!








原创粉丝点击