Java学习疑点(6)--Set集合添加元素时底层如何实现无重复元素?

9 篇文章 0 订阅

最近在学习Collection时发现Set集合的一个显著特点: 不包含重复元素. 经过测试之后发现Set集合在向其添加元素时add()和addAll()方法就对元素进行了"审查", 对比查看是否为尚未存在的元素然后选择是否添加进去. 关于这两种方法底层是如何实现的, 就是我在这里想要说明的.

我们知道Set集合是建立在Map的基础之上, 其绝大多数方法构造时都是直接引用了Map中的方法.

这里我们先以HashSet列举一个事例:

  HashSet<String> hs = new HashSet<String>();
  System.out.println(hs.add(null));
  System.out.println(hs.add(null));
  System.out.println(hs.add("Shawyeok"));
  System.out.println(hs.add("Java"));
  System.out.println(hs.add("Shawyeok"));


这里hs在调用add()向内添加元素的时候, 首先会判断元素是否为null(Set的这种不重复元素特性注定会出现一个现象----一个Set集合中最多只能包含一个null元素)若为null则会查找集合中是否有null元素, 若没有则添加成功, 返回true; 反之则添加失败, 返回false.

若元素非null, 则首先调用元素的hashCode()方法得到其哈希值与集合中的各个元素的哈希值一一比较, 如果不相同说明这是两个不同的元素, 可以添加;  如果相同则再调用equals方法对两个元素进行比较, 若equals方法返回true则说明两个元素是同一元素, 不能添加; 反之, 说明两元素非同一元素, 可以添加.

下面是运行结果:

true
false
true
true
false

如何向Set集合中添加我们自己定义的类的对象呢?

上面已经说明了Set集合是如何保证不添加重复元素的, 我们可以想到重写继承自Object类中hashCode()以及equals()方法来保证不添加重复元素. 同样的, 写一个事例:

import java.util.*;

class Test {
	public static void main(String[] args) {
		HashSet<Person> hs = new HashSet<Person>();
		Person Tim = new Person("Tim", Person.MAN, 176);
		Person Jine = new Person("Jine", Person.WOMAN, 173);
		System.out.println(hs.add(Tim));
		System.out.println(hs.add(Jine));
		System.out.println(hs.add(new Person("Tim", Person.MAN, 176)));
	}
}
class Person {
	private String name;
	private boolean gender;		//true:man ; false:woman
	private int height;
	
	public static final boolean MAN = true;
	public static final boolean WOMAN = false;
	
	public Person(String name, boolean gender, int height) {
		this.name = name;
		this.gender = gender;
		this.height = height;
	}
	
	public int hashCode() {
		int sum = name.hashCode() + height*2;		//这里height乘以2是为了尽量保证不同元素哈希值的唯一性
		if(gender) {
			sum++;
		} else {
			sum--;
		}
		return sum;
	}
	
	public boolean equals(Object obj) {
		if(!(obj instanceof Person)) {
			return false;
		}
		
		Person p = (Person)obj;
		if(this.name != p.name) {
			return false;
		}
		if(this.gender != p.gender) {
			return false;
		}
		if(this.height != p.height) {
			return false;
		}
		return true;
	}
}
 

下面是程序打印结果:

true
true
false

从结果可以看出以上的分析是正确的.

注: 以上分析可能会有讲述不妥以及语义欠缺的情况, 敬请谅解.关于Set集合更多特性的详细信息请参考阅读Java源代码.


 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值