java Set源码解析

一、Set概述

1、Set继承了Collection的接口,集合中不包含重复的元素,并且最多存在一个空的元素;

2、HashSet和TreeSet是Set的两个实现类。HashSet依赖于HashMap,他的元素是无序的,TreeSet依赖于TreeMap,元素是有序的;

二、HashSet解析

1、HashSet简介

(1)HashSet底层是用HashMap来存储的,能够存储一个null值,元素时无序的。

(2)HashSet是非线程安全的,在多线程环境下使用add、delete等操作,会发生快速失败,所以可以在使用的时候加上同步锁。

2、HashSet的底层存储

由这两句可以看出HashSet的存储使用的是HashMap,他的value值使用的是一个虚拟的默认值

//底层是用HashMap来存储元素
private transient HashMap<E,Object> map;

//定义一个虚拟的Object作为HashMap的value
private static final Object PRESENT = new Object();

3、HashSet初始化方法

    初始化HashSet有下面四种方法,但是从方法的实现中都可以看到实际上是初始化对应的HashMap

//初始化一个HashSet:是用的是初始化HashMap的方法,默认的容量为17,负载因子0.75
public HashSet() {
	map = new HashMap<>();
}

//初始化包含固定集合的HashSet:先初始化一个HashMap,然后经集合中的元素添加到map中
public HashSet(Collection<? extends E> c) {
	map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
	addAll(c);
}

//初始化指定容量和负载因子的HashSet:实际上也是指定HashMap的容量和负载因子
public HashSet(int initialCapacity, float loadFactor) {
	map = new HashMap<>(initialCapacity, loadFactor);
}

//初始化指定容量的HashSet:默认负载因子
public HashSet(int initialCapacity) {
	map = new HashMap<>(initialCapacity);
}

4、HashSet对应的方法

    下面是HashSet中对应的方法,如果已经了解到HashMap对应的方法的实现过程,那么理解这几个方法就很简单,他们的实现都是基于HashMap来进行的,从这几个方法中也可以看出,HashSet中的值实际上是对应了HashMap中的key值,而HashMap中的value就是前面说到的默认的对象,而在HashMap中key值是不能重复的,这也限制了HashSet中的元素不能重复。

//返回HashSet中元素的个数
public int size() {
	return map.size();
}

//判断HashSet是否为空
public boolean isEmpty() {
	return map.isEmpty();
}

//判断HashSet中是否包含某元素:也就是判断HashMap中是否已经包含对应的key值
public boolean contains(Object o) {
	return map.containsKey(o);
}

/**
* 向HashSet中插入一个元素:将该元素做为key值,value为默认的object插入到HashMap中,
* 如果set中不包含该元素返回true值,已包含返回false值
* @param e
* @return
*/
public boolean add(E e) {
	return map.put(e, PRESENT)==null;
}

/**
* 删除Set中的一个元素,实际上是删除的是Map中对用的key值
* 如果HashMap中对应的key值的value值为默认的Object,返回true,否则返回false
* @param o
* @return
*/
public boolean remove(Object o) {
	return map.remove(o)==PRESENT;
}

//清空HashSet
public void clear() {
	 map.clear();
}

5、HashSet的遍历方式

HashSet有两种遍历方式:一种是使用迭代器的形式,一种是使用增强型for循环的方式

Iterator<Object> it = set.iterator();
while(it.hasNext()) {
	System.out.println(it.next());
}
		
for(Object o: set) {
	System.out.println(o);
}

6、HashSet总结

    相比较而言,HashSet的源码的实现比较简单,如果对HashMap已经熟悉,那么很容易理解HashSet:

(1)HashSet中的元素是无序的,基于HashMap实现,HashMap中的元素也是无序的;

(2)HashSet中的元素时不能重复的,HashSet中的值对应的是HashMap中的key值,而key值不能重复;

(3)HashSet是非线程安全的。

三、TreeSet解析

1、TreeSet简介

(1)TreeSet是通过TreeMap实现的,也是基于红黑树的存储结构;

(2)TreeSet中不允许存在null对象;

(3)TreeSet中的元素时有序的;

2、TreeSet的构造方法

    TreeSet有四种构造方法,分别对应的是TreeMap的构造方法,在这里也可以看出TreeSet都是通过闯进一个TreeMap来存储元素,

TreeSet(NavigableMap<E,Object> m) {
	this.m = m;
}

//初始化一个TreeSet:使用自认顺序排序,调用的是TreeMap的初始化方法
public TreeSet() {
	this(new TreeMap<E,Object>());
}

//初始化一个指定排序方式的TreeSet:调用对应的TreeMap初始化方法
public TreeSet(Comparator<? super E> comparator) {
	this(new TreeMap<>(comparator));
}

//初始化一个包含指定集合元素的TreeSet:先初始化一个TreeMap,使用自然排序,然后将集合中的元素添加到map中
public TreeSet(Collection<? extends E> c) {
	 this();
	 addAll(c);
}

//创建一个包含指定Set的TreeSet:先创建一个指定的排序的TreeMap,然后将元素加入到map中
public TreeSet(SortedSet<E> s) {
	 this(s.comparator());
	 addAll(s);
}

3、TreeSet中对应的方法

    下面是TreeSet中最常用的几个方法,他的实现都是基于TreeMap对应的方法实现的,与HashSet一样,TreeSet中的值对应的是TreeMap中的key值,所以不允许存在重复的元素和值。

 //TreeSet中的元素个数,使用的是TreeMap的size方法
public int size() {
	return m.size();
}

//判断TreeSet是否为空,使用的是TreeMap的isEmpty方法
public boolean isEmpty() {
	return m.isEmpty();
}

//判断TreeSet中是否包含某值,实际上是判断TreeMap中是否包含对应的key值
public boolean contains(Object o) {
	return m.containsKey(o);
}

/**
* 向TreeSet中添加一个元素:实际上是向TreeMap中添加一个key对对应元素,value为默认值的过程,
* 如果TreeMap中返回的结果为空,表示该元素之前在TreeMap中不存在,不为空表示已存在
* @param e
* @return
*/
public boolean add(E e) {
	return m.put(e, PRESENT)==null;
}

/**
* 删除TreeSet中的元素,实际上是删除TreeMap中key为o的元素
* 如果TreeMap中返回的结果是默认的PRESENT,表示该元素在Set中存在,那么结果为true,反之为false
* @param o
* @return
*/
public boolean remove(Object o) {
	return m.remove(o)==PRESENT;
}

//清空TreeSet中的元素,实际上是清空TreeMap中的元素
public void clear() {
	m.clear();
}

4、TreeSet的遍历方式

    TreeSet的可以使用迭代器进行遍历,也可以使用for循环进行遍历

Iterator it = set.iterator();
while(it.hasNext()) {
	System.out.println(it1.next());
}
		
for(Object o: set) {
	System.out.println(o);
}

5、TreeSet总结

(1)TreeSet的底层实现是基于TreeMap实现的,为了更好的理解TreeSet,建议先理解TreeMap的结构;

(2)TreeSet中的元素时有序的,不存在重复的元素和null值;

四、Set总结

1、set中不允许存在重复的元素;

2、HashSet是基于HashMap实现的,有HashMap有相同的特性;

3、TreeSet是基于TreeMap实现的,他包含的方法都是根据TreeMap中对应的方法实现;

4、理解set的时候建议首先了解map的实现过程。





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值