Java容器Set接口
Set接口的实现,可以方便地将指定的类型以集合类型保存在一个变量中。Set是一个不包含重复元素的Collection,更确切地讲,Set 不包含满足 e1.equals(e2) 的元素对,并且最多包含一个 null 元素。Set接口的底层存储实现都是依赖Map的实现,也可以说Set中元素的管理就是对Map中key的管理。下面简单描述一下各种Set接口的实现类,主要包括HashSet,LinkedHashSet,TreeSet

1、HashSet
HashSet底层是有HashMap实现的,存储的是[key-Object常量]这样的键值对,同样包括initialCapacity和loadFactor两个参数,这两个参数的意义和HashMap一样,都是比较重要的。另外,HashSet集合里边的元素是无序的。
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
{
static final long serialVersionUID = -5024744406713321676L; private transient HashMap<E,Object> map; // Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object(); /**
* Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
* default initial capacity (16) and load factor (0.75).
*/
public HashSet() {
map = new HashMap<E,Object>();
} /**
* Constructs a new set containing the elements in the specified
* collection. The <tt>HashMap</tt> is created with default load factor
* (0.75) and an initial capacity sufficient to contain the elements in
* the specified collection.
*
* @param c the collection whose elements are to be placed into this set
* @throws NullPointerException if the specified collection is null
*/
public HashSet(Collection<? extends E> c) {
map = new HashMap<E,Object>(Math.max((int) (c.size()/.75f) + , ));
addAll(c);
} /**
* Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
* the specified initial capacity and the specified load factor.
*
* @param initialCapacity the initial capacity of the hash map
* @param loadFactor the load factor of the hash map
* @throws IllegalArgumentException if the initial capacity is less
* than zero, or if the load factor is nonpositive
*/
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<E,Object>(initialCapacity, loadFactor);
}
2、LinkedHashSet
LinkedHashSet继承了HashSet,但它底层存储使用的是LinkedHashMap,所以其中的元素是按照插入有序的。看LinkedHashSet类只是定义了四个构造方法,也没看到和链表相关的内容,为什么说LinkedHashSet内部使用链表维护元素的插入顺序(插入的顺序)呢?点进去看下这个三个参数的构造方法HashSet(int initialCapacity, float loadFactor, boolean dummy),就会发现使用的实现类是LinkedHashMap了:
public class LinkedHashSet<E>
extends HashSet<E>
implements Set<E>, Cloneable, java.io.Serializable { private static final long serialVersionUID = -2851667679971038690L; /**
* Constructs a new, empty linked hash set with the specified initial
* capacity and load factor.
*
* @param initialCapacity the initial capacity of the linked hash set
* @param loadFactor the load factor of the linked hash set
* @throws IllegalArgumentException if the initial capacity is less
* than zero, or if the load factor is nonpositive
*/
public LinkedHashSet(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor, true);
} /**
* Constructs a new, empty linked hash set with the specified initial
* capacity and the default load factor (0.75).
*
* @param initialCapacity the initial capacity of the LinkedHashSet
* @throws IllegalArgumentException if the initial capacity is less
* than zero
*/
public LinkedHashSet(int initialCapacity) {
super(initialCapacity, .75f, true);
} /**
* Constructs a new, empty linked hash set with the default initial
* capacity (16) and load factor (0.75).
*/
public LinkedHashSet() {
super(16, .75f, true);
}
/**
* Constructs a new, empty linked hash set. (This package private
* constructor is only used by LinkedHashSet.) The backing
* HashMap instance is a LinkedHashMap with the specified initial
* capacity and the specified load factor.
*
* @param initialCapacity the initial capacity of the hash map
* @param loadFactor the load factor of the hash map
* @param dummy ignored (distinguishes this
* constructor from other int, float constructor.)
* @throws IllegalArgumentException if the initial capacity is less
* than zero, or if the load factor is nonpositive
*/
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<E,Object>(initialCapacity, loadFactor);
}
3、TreeSet
TreeSet底层存储使用的是TreeMap,使用它可以从Set中提取有序的序列,元素必须实现Comparable接口否则按默认字典排序。
public class TreeSet<E> extends AbstractSet<E>
implements NavigableSet<E>, Cloneable, java.io.Serializable
{
/**
* The backing map.
*/
private transient NavigableMap<E,Object> m; // Dummy value to associate with an Object in the backing Map
private static final Object PRESENT = new Object(); /**
* Constructs a set backed by the specified navigable map.
*/
TreeSet(NavigableMap<E,Object> m) {
this.m = m;
} /**
* Constructs a new, empty tree set, sorted according to the
* natural ordering of its elements. All elements inserted into
* the set must implement the {@link Comparable} interface.
* Furthermore, all such elements must be <i>mutually
* comparable</i>: {@code e1.compareTo(e2)} must not throw a
* {@code ClassCastException} for any elements {@code e1} and
* {@code e2} in the set. If the user attempts to add an element
* to the set that violates this constraint (for example, the user
* attempts to add a string element to a set whose elements are
* integers), the {@code add} call will throw a
* {@code ClassCastException}.
*/
public TreeSet() {
this(new TreeMap<E,Object>());
}
总结一下:
HashSet是为快速查找而设计的Set,存入HashSet的元素必须定义hashCode();LinkedHashSet具有HashSet的查询速度,且内部使用链表维护元素的顺序(插入顺序),在使用迭代器遍历Set时,结果会按插入的次序显示,元素必须定义hashCode()方法;TreeSet保存次序的Set,底层为树结构,使用它可以从Set中提取有序的序列,元素必须实现Comparable接口。
另外,这里提一下hashcode和equals在Set中的比较重要的意义。当对以哈希为底层的集合操作的时候,会先以hashcode去找对应的链表,然后再遍历对应的链表通过equals对比key,最后找到对应的value。还是和上次说的一样,当hashcode方法设计的不好的时候,会导致元素分布不均匀,然后调用大量的equals对比key,最后影响到程序的执行效率。
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
最后提一下面试比较常问到的问题:当两个对象的hashcode相等的时候它们的equals不一定返回true;但当两个对象的equals返回true的时候它们的hashcode一定相同。
Java容器Set接口的更多相关文章
- Java容器Map接口
Map接口容器存放的是key-value对,由于Map是按key索引的,因此 key 是不可重复的,但 value 允许重复. 下面简单介绍一下Map接口的实现,包括HashMap,LinkedHas ...
- Java容器List接口
List接口是Java中经常用到的接口,如果对具体的List实现类的特性不了解的话,可能会导致程序性能的下降,下面从原理上简单的介绍List的具体实现: 可以看到,List继承了Collection接 ...
- Java容器---Collection接口中的共有方法
1.Collection 接口 (1)Collection的超级接口是Iterable (2)Collection常用的子对象有:Map.List.Set.Queue. 右图中实现黑框的ArrayLi ...
- Java容器——List接口
1. 定义 List是Collection的子接口,元素有序并且可以重复,表示线性表. 2. 常用实现类 ArrayList:它为元素提供了下标,可以看作长度可变的数组,为顺序线性表. LinkedL ...
- java容器——Collection接口
Collection是Set,List接口的父类接口,用于存储集合类型的数据. 2.方法 int size():返回集合的长度 void clear():清除集合里的所有元素,将集合长度变为0 Ite ...
- Java容器——Set接口
1.定义 set中不允许放入重复的元素(元素相同时只取一个).它使用equals()方法进行比较,如果返回true,两个对象的HashCode值也应该相等. 2.方法 TreeSet中常用的方法: b ...
- Java容器——Map接口
1.定义 Map用于保存存在映射关系<key, value>的数据.其中key值不能重复(使用equals()方法比较),value值可以重复. 2.常用实现类 HashMap:和Hash ...
- Java容器深入浅出之Collection与Iterator接口
Java中用于保存对象的容器,除了数组,就是Collection和Map接口下的容器实现类了,包括用于迭代容器中对象的Iterator接口,构成了Java数据结构主体的集合体系.其中包括: 1. Co ...
- 【Java心得总结七】Java容器下——Map
我将容器类库自己平时编程及看书的感受总结成了三篇博文,前两篇分别是:[Java心得总结五]Java容器上——容器初探和[Java心得总结六]Java容器中——Collection,第一篇从宏观整体的角 ...
随机推荐
- Python模块Scrapy导入出错:ImportError: cannot import name xmlrpc_client
Mac(OS version: OS X Yosemite 10.10.5)上安装Scrapy模块,使用时出现: from six.moves import xmlrpc_client as xmlr ...
- [转帖]UsingDiskspdforSQLServer --- 改天做下练习 官方文档.
Using DiskSpd in SQL Server environments Writer: Robert Beene Contributors: Jose Barreto, Ramu Konid ...
- 如何在DBGrid中能支持多项记录的选择
When you add [dgMultiSelect] to the Options property of a DBGrid, you give yourself the ability to s ...
- 【刷题】洛谷 P1501 [国家集训队]Tree II
题目描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: + u v c:将u到v的路径上的点的权值都加上自然数c: - u1 v1 u2 v2:将树中原有的 ...
- 一步步创建第一个Docker App —— 1. 背景介绍
原文:https://docs.docker.com/engine/getstarted-voting-app/#/docker-stacks-and-services 你将会学习什么 本文创建 ...
- bzoj2300【HAOI2011】防线修建
题目描述 近来A国和B国的矛盾激化,为了预防不测,A国准备修建一条长长的防线,当然修建防线的话,肯定要把需要保护的城市修在防线内部了.可是A国上层现在还犹豫不决,到底该把哪些城市作为保护对象呢?又由于 ...
- [学习笔记]平衡树(Splay)——旋转的灵魂舞蹈家
1.简介 首先要知道什么是二叉查找树. 这是一棵二叉树,每个节点最多有一个左儿子,一个右儿子. 它能支持查找功能. 具体来说,每个儿子有一个权值,保证一个节点的左儿子权值小于这个节点,右儿子权值大于这 ...
- 【noip模拟】D(==)
Portal --> who knows == Description 数轴上面有一些洞,有一些老鼠,每个洞有一个容量限制,一只位于\(x\)的老鼠进到位于\(y\)的洞要花费\(|x-y|\) ...
- 850. 矩形面积 II
我们给出了一个(轴对齐的)矩形列表 rectangles . 对于 rectangle[i] = [x1, y1, x2, y2],其中(x1,y1)是矩形 i 左下角的坐标,(x2,y2)是该矩形右 ...
- ORB算法介绍(转)
本文为原创文章,转载请注明出处:http://blog.csdn.net/yang843061497/article/details/38553765 绪论 假如我有2张美女图片,我想确认这2张图片中 ...