HashSet不重复存储元素的执行过程

6 篇文章 0 订阅

      十一嘛,该干点啥呢?既然没啥事儿可干,那就继续看看代码吧。好的,那就开始技术。

       在前几篇博客中写了关于ArrayList的一些知识,现在就学一个Set集合的东西,Set集合:元素不可重复,是无序的

其中在Set接口中的方法和Collection一致,HashSet和TreeSet是常用子类。这次我们主要用到HashSet!
HashSet:内部数据结构是Hash表,底层存储通过算法实现,根据元素自身的特点,确实其存放的位置。是不同步的。

其中最大特点就是不重复,和无法按输入顺序输出。看一个代码的例子:

public class HashSetDemo {

	public static void main(String[] args) {
		
		HashSet hs = new HashSet();
		
		hs.add("linweieran");
		hs.add("linweieran");
		hs.add("haha48");
		hs.add("heihei");
		
		
		Iterator it=hs.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
	}
}
结果证明没有按输入顺序输出字符串,同时也是不可重复。

这就用到了hash算法中的hasCode()  and equals()方法。但是当存储自定义对象的时候就出现了一定的“重复”。

public static void main(String[] args) {
		
		HashSet hs=new HashSet();
			
		hs.add(new Person("linweieran",24));
		hs.add(new Person("linweieran1",23));
		hs.add(new Person("linweieran2",22));
		hs.add(new Person("linweieran3",25));
		hs.add(new Person("linweieran",24));
		
		Iterator it =hs.iterator();
		while(it.hasNext()){
			Person p=(Person)it.next();
			System.out.println(p.getName()+":"+p.getAge());
		}		
	}
其中Person类,就是前一个博文里用到的Person类。

可以看出元素出现了重复。分析原因,这是因为在HashSet集合中对每一个新对象都hash一个新值。那么HashSet是如何hash、如何进行不重复存储的呢?

      hash运算估计学过计算机的都知道这个,hash当在影射位置已有对象是有链表也有后移的存储方式,这个在这里就说了,整个 存储机制怎么运行呢?

      (1)首先向集合中存储元素或者对象的时候,通过hashCode()函数计算出hash值;

      (2)再通过equals()函数判断相同的是否存在,如果存在就不存,否则存入,在Java中的底层代码HashCode()代码如下:

 public int hashCode() {
	int h = 0;
	Iterator<E> i = iterator();
	while (i.hasNext()) {
	    E obj = i.next();
            if (obj != null)
                h += obj.hashCode();
        }
	return h;
    }

equals代码如下:

public boolean equals(Object o) {
	if (o == this)
	    return true;

	if (!(o instanceof Set))
	    return false;
	Collection c = (Collection) o;
	if (c.size() != size())
	    return false;
        try {
            return containsAll(c);
        } catch (ClassCastException unused)   {
            return false;
        } catch (NullPointerException unused) {
            return false;
        }
    }
但这这是遇到String类型时候会这样做,但遇到先前提到的Person类的时候,有这样的功能,必须复写hashCode 和equals方法,具体代码如下:

public class Person {
	
	private String name;
	private int age;
	
	//alt+shift+s
	
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	
	
	
	@Override
	public int hashCode() {

		System.out.println(this+"....hashCode");
		int nameNu=name.hashCode();		
		return nameNu+age;
	}

	@Override
	public boolean equals(Object obj) {
		
		if(this==obj)
			return true;
		if(!(obj instanceof Person))
			throw new ClassCastException();//类型错误
		
		Person p = (Person)obj;
		System.out.println(this+"...equal..."+p.name);
		return this.name.equals(p.name)&&this.age==p.age;
	}
	
	public String toString(){
		return name+":"+age;
	}


	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	

}
对于hashCode简单的写为返回name+age;对于equals 当名字和年龄相同时,就认为是同一个人。

通过看一下执行步骤

可以看出所写的执行过程是正确的。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值