A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 吴通 中级黑马   /  2012-8-28 22:04  /  2025 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文



我们的集合List  Set Map等
当定义了一个集合时,它应该就具备了自己特有的属性,
像ArrayList就是数组结构的,LinkedList是链表数组结构的

既然数组都有自己特有的属性,那么为什么我们在存取数组的时候还要刻意的
去复写某些方法  以HashSet为例:
import java.util.*;
class HashSetDemo
{
public static void main(String[] args)
{
  HashSet al=new HashSet();
  al.add(new Person("a1",11));
  al.add(new Person("a2",12));
  al.add(new Person("a3",13));
  al.add(new Person("a4",12));
}
}
class Person
{
private String name;
private int age;

//复写hashCode方法
public int hashCode()
{
  return name.hashCode()+age;
}
//定义特有的equals方法
public boolean equals(Object obj)
{
  if(!(obj instanceof Person))
   return false;
  Person p=(Person)obj;
  return this.name.epuals(p.name)&&tis.age==p.age;
}

Person(String name,String age)
{
  this.name=name;
  this.age=age;
}
//省略了set步骤
public String getName()
{
  return name;
}
public int getAge()
{
  return age;
}
}

HashSet集合要复写HashCode和equals方法,我感觉好像并不是这个数组具有
这样的特性,而是我们刻意强加给它的,既然这样我们是不是刻意按照自己的需求再自定义
自己想要的集合类型呢?一直搞不明白!求指教

评分

参与人数 1技术分 +1 收起 理由
包晗 + 1

查看全部评分

4 个回复

倒序浏览
本帖最后由 唐志兵 于 2012-8-28 22:56 编辑

Set集合是继承的 Collection接口,它的特性是不允许存放两个相同的元素。
  1. HashSet al=new HashSet();
  2.    al.add(new Person("heima",2));
  3.   al.add(new Person("heima",2));
复制代码
如果在没有复写hashcode和equal的情况下上面的代码运行后会发生什么事呢,你觉得这两个元素能否被添加到集合当中去呢?

答案是 能够被添加到集合当中,因为它们虽然是两个相同的对象。但是它们在堆内存当中有不同的地址,所以它们的hashcode也会不相同。这样程序就会认为它们是两个不同的对象,而set集合的特性是 不允许存放两个相同的元素。

为了避免上面的情况我们就可以再类中复写 equal跟 hashcode,这样在给集合添加元素的时候 会先判断两个元素的 hashcode是否相同,如果相同,则说明是两个重复的元素,如果不相同,则继续调用equal方法判断两个对象是否相同。这样我们就可以通过
  1. public boolean equals(Object obj)
  2. {
  3.   if(!(obj instanceof Person))
  4.    return false;
  5.   Person p=(Person)obj;
  6.   System.out.println("equal");
  7.   return this.name.equals(p.name)&& this.age==p.age;
  8. }
复制代码
这样的代码来 防止在set集合当中添加了两个相同的元素。。。



版主给点分吧。。。打字很累的。







评分

参与人数 1技术分 +1 收起 理由
包晗 + 1

查看全部评分

回复 使用道具 举报
HashSet
        底层数据结构是哈希表。线程不安全。
        如果保证元素的唯一性呢?
        A:首先根据hashCode值判断。
        B:如果hashCode值不同,那么,这就是不同的元素。直接存储。
                如果hashCode值相同,那么,会继续根据equals方法进行判断,
                根据自己的需求来决定元素是否相同。如果相同,就不存储。否则,存储。
//复写hashCode方法
public int hashCode()
{
  return name.hashCode()+age*17;//这里要随便乘以一个数  用来保证hashCode的值不为一
}

评分

参与人数 1技术分 +1 收起 理由
包晗 + 1

查看全部评分

回复 使用道具 举报
Set:元素是无序(存入和取出的顺序不一定一致),元素不可以重复。
         那么在调用集合的添加方法时,必然会对元素进行比较,如果重复就不存入,如果不重复就存入。
而这个比较的过程为:1、先比较hashCode值,如果不同,则将对象存入集合中;
                                  2、如果hashCode值相同,则调用equals方法判断两个对象是否相同,如果相同不存入,如果不同则存入集合中。
如果没有重写hashCode方法,就会可能出现两个元素的hashCode值不同,但元素内容是一样的,此时就会重复添加元素。
如果没有重写equals方法,那么当两个元素不一样,hashCode值不同,但AbstractSet类的的equals方法判断两个元素相同,就会少添加元素。

以楼主的代码为例:
al.add(new Person("a1",11));
  al.add(new Person("a2",12));
al.add(new Person("a2",12)); //如果没有重写hashCode方法,因为每次new Person对象都会给一个不同的hashCode值,故会将此对象存入集合,出现重复元素的情况
al.add(new Person("a3",13));
al.add(new Person("a3",12)); //如果没有重写equals方法,有可能底层的equals方法判断new Person("a3",12)和new Person("a3",13)这两个对象一样,则不存入集合
                                                    //则少添加元素
al.add(new Person("a4",12));   

对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法。因此,需要重写hashcode和equals方法。        

评分

参与人数 1技术分 +1 收起 理由
包晗 + 1

查看全部评分

回复 使用道具 举报
谢谢 已解决
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马