Java中HashSet的解读
一. HashSet源代码
HashSet 的实现
对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层采用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,查看 HashSet 的源代码,可以看到如下代码: Java代码
public class HashSet<E> extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable {
// 使用 HashMap 的 key 保存 HashSet 中所有元素 private transient HashMap<E,Object> map;
// 定义一个虚拟的 Object 对象作为 HashMap 的 value private static final Object PRESENT = new Object(); ...
// 初始化 HashSet,底层会初始化一个 HashMap public HashSet() {
map = new HashMap<E,Object>(); }
// 以指定的 initialCapacity、loadFactor 创建 HashSet // 其实就是以相应的参数创建 HashMap
public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<E,Object>(initialCapacity, loadFactor); }
public HashSet(int initialCapacity) {
map = new HashMap<E,Object>(initialCapacity); }
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<E,Object>(initialCapacity , loadFactor); }
// 调用 map 的 keySet 来返回所有的 key public Iterator<E> iterator()
{
return map.keySet().iterator(); }
// 调用 HashMap 的 size() 方法返回 Entry 的数量,就得到该 Set 里元素的个数
public int size() {
return map.size(); }
// 调用 HashMap 的 isEmpty() 判断该 HashSet 是否为空, // 当 HashMap 为空时,对应的 HashSet 也为空 public boolean isEmpty() {
return map.isEmpty(); }
// 调用 HashMap 的 containsKey 判断是否包含指定 key // HashSet 的所有元素就是通过 HashMap 的 key 来保存的 public boolean contains(Object o) {
return map.containsKey(o); }
// 将指定元素放入 HashSet 中,也就是将该元素作为 key 放入 HashMap public boolean add(E e) {
return map.put(e, PRESENT) == null; }
// 调用 HashMap 的 remove 方法删除指定 Entry,也就删除了 HashSet 中对应的元素
public boolean remove(Object o) {
return map.remove(o)==PRESENT; }
// 调用 Map 的 clear 方法清空所有 Entry,也就清空了 HashSet 中所有元素
public void clear() {
map.clear(); } ... }
由上面源程序可以看出,HashSet 的实现其实只是封装了一个 HashMap 对象来存储所有的集合元素,所有放入 HashSet 中的集合元素实际上由 HashMap 的 key 来保存,而 HashMap 的 value 则存储了一个 PRESENT,它是一个静态的 Object 对象。
HashSet 的绝大部分方法都是通过调用 HashMap 的方法来实现的,因此 HashSet 和 HashMap 两个集合在实现本质上是相同的。
二.HashSet<E>对象
HashSet<E>创建的对象称为集合:
HashSet<string> s= HashSet<string>;
那么s就是一个可以存储 string 类型数据的集合,s 可以调用add(String s)方法将string类型的数据添加到集合中。添加到集合中的数据称为集合的元素。集合不允许有相同的元素,也就是说,如果b已经是集合中的元素,那么在执行set.add(b)操作是无效的。 三.HashSet<E>中的方法详解
① public boolean add(E o) —— 向集合添加参数指定的元素。(如果此集合中还
不包含指定元素,则添加指定元素。)
参数:
o - 将添加到此集合中的元素。 返回:
如果该集合还不包含指定元素,则返回 true。
② public void clear() ——清空集合,使集合不含有任何元素。
③ public boolean contains(Object o) —— 判断参数指定的数据是否属于集合。()
参数:
o - 其在此集合中的存在已得到测试的元素。
返回:
如果此集合不包含指定元素,则返回 true。
④ public boolean isEmpty()—— 判断集合是否为空。
返回:
如果此集合不包含任何元素,则返回 true。
⑤ public boolean remove(Object o) ——集合删除参数指定的元素。
参数:
o - 如果存在于此集合中则需要将其移除的对象。
返回:
如果集合包含指定元素,则返回 true。
⑥ public int size () —— 返回集合中元素的个数。
返回:
此集合中的元素的数量(集合的容量)。
⑦ Object [ ] toArray() —— 将集合元素存放到数组中,并返回这个数组。
⑧ boolean containsAll (HashSet set) —— 判断当前集合是否包含参数指定的集合。
⑨ public Object clone () —— 得到当前集合的一个克隆对象,该对象中元素的改
变不会影响到当前集合中的元素,反之亦然。 返回:
此集合的浅表复制。
四.代码:
import java.util.HashSet;
class Student{ String name; int score;
Student(String name, int score){ this.name = name; this.score = score; } }
public class TestHashSet{
public static void main(String[] args) {
Student zh = new Student("张三",77); Student li = new Student("李四",68); Student wa = new Student("王五",67);
HashSet<Student> set = new HashSet<Student>(); HashSet<Student> subset = new HashSet<Student>();
System.out.println("Before add(zh):"+set.add(zh)); set.add(zh);
System.out.println("After add(zh):"+set.add(zh)); //add方法的实现 set.add(wa); set.add(li);
subset.add(wa); subset.add(li);
System.out.println("Is subset empty? "+subset.isEmpty()); //isempty方法的实现
if (set.contains(wa)){
System.out.println("集合set中含有:"+wa.name); //contains方法的实现 }
if(set.containsAll(subset)){
System.out.println("集合set包含集合subset"); }
int number = subset.size(); //size方法的实现 System.out.println("集合subset中有"+number+"个元素:");
Object s[] = subset.toArray(); //toArray 方法的实现
for(int i=0; i<s.length; i++){
System.out.printf("姓名:%s,分数:%d\n", ((Student)s[i]).name,((Student)s[i]).score); }
subset.remove(wa); //remove方法的实现 System.out.println("After implement remove on subset");
System.out.println("集合subset中有"+subset.size()+"个元素:");
Object a[] = subset.toArray();
for(int i=0; i<a.length; i++){
System.out.printf("姓名:%s,分数:%d\n", ((Student)a[i]).name,((Student)a[i]).score); } } }
五.运行结果
Before add(zh):true After add(zh):false Is subset empty? false 集合set中含有:王五 集合set包含集合subset 集合subset中有2个元素: 姓名:李四,分数:68 姓名:王五,分数:67
After implement remove on subset 集合subset中有1个元素: 姓名:李四,分数:68
Java中HashSet的解读的更多相关文章
- Java中HashSet和HashMap
Set中存储元素为什么不重复(即使hashCode相同)? HashSet中存放自定义类型元素时候,需要重写对象中的hashCode方法和equals方法, HashSet中存放自定义类型元素时候,需 ...
- Java中HashSet的重复性与判等运算重载
目录 还有一个故事--(平行世界篇) 还有一个美丽的梦幻家园:java.util 并且还有一个善战的达拉崩巴:HashSet 还有另外一个故事(不是虚假传说) 还有一对涂满毒药的夺命双匕:equals ...
- Java中HashSet,HashMap和HashTable的区别
HashMap.HashSet.HashTable之间的区别是Java程序员的一个常见面试题目,在此仅以此博客记录,并深入源代码进行分析: 在分析之前,先将其区别列于下面 1:HashSet底层采用的 ...
- java中HashSet详解(转)
HashSet 的实现 对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层采用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,查看 HashSe ...
- java中HashSet详解
HashSet 的实现 对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层采用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,查看 HashSe ...
- java集合(4)- java中HashSet详解
HashSet 的实现 对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层采用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,查看 HashSe ...
- java中hashSet原理
转自: http://blog.csdn.net/guoweimelon/article/details/50804799 HashSet是JavaMap类型的集合类中最常使用的,本文基于Java1. ...
- java中HashSet实现(转)
hashset底层的数据结构是hash表,hash表实现方式采用数组+链表,数组类型为HashNode,每个数组元素为链表的头指针,链表中存储经过hash函数散列后冲突的元素,数组的长度为26 has ...
- java中HashSet对象内的元素的hashCode值不能变化
因为不管是HashMap(或HashTable,还是HashSet),key值是以hashCode值存进去的,加入key值变了,将无法从集合内删除对象,导致内存溢出.
随机推荐
- 码农的福利来了, 编程在线Androd 客户端上线了
编程在线下载: 编程在线网站:http://codestudy.sinaapp.com (最新版2.1) 编程在线移动版:http://codestudy.sinaapp.com/mobile/ 编程 ...
- iOS 应用隐藏状态栏
有时候在 Storyboard 和 target 里的设定并不足以使得应用能够完全隐藏状态栏. 这时候需要到 Info.plist,添加一项:View controller-based status ...
- PTA——删除重复字符
PTA 7-60 删除重复字符 #include<stdio.h> #include<string.h> #define N 85 int main() { ,flag; ch ...
- 在线编辑器Ckeditor (2) - php (31)
接上一篇 3 in-page(页内)配置,在使用Ckeditor的界面里进行直接配置 页内配置 效果 特点:配置项完全属于某个特定的Ckeditor实例,不可重用 三种配置方式比较 定制方式 特点 说 ...
- UnSafe类中的一些重要方法
UnSafe类中的一些重要方法 JDK中的rt.jar保重Unsafe类中提供了硬件级别的原子性操作,Unsafe类中的方法都是navtice方法,他们使用JNI的方式访问C++实现库,下面我们来了解 ...
- 深入了解java虚拟机(JVM) 第十三章 虚拟机字节码执行引擎
一.概述 执行引擎是java虚拟机最核心的组成部件之一.虚拟机的执行引擎由自己实现,所以可以自行定制指令集与执行引擎的结构体系,并且能够执行那些不被硬件直接支持的指令集格式.所有的Java虚拟机的执行 ...
- memcache内存存储
memcache的内存分配默认是采用了Slab Allocator的机制分配.管理内存.在该机制出现以前,内存的分配是通过对所有记录简单地进行malloc和free来进行的. 但是,这种方式会导致内存 ...
- FTP枢轴攻击
简单来说,这是攻击者可以利用属于不同网络的那些系统的攻击. 本文作者:jishuzhain 对于这种攻击,攻击者需要利用主服务器来帮助攻击者将自己添加到本地网络中,然后攻击者就可以将客户端系统进行定位 ...
- Flutter 1.0 正式版: Google 的便携 UI 工具包
简评:所以 React-Native 和 Flutter 该怎么选? 在 10 个月前的 MWC 上,谷歌发布了 Flutter 的 Beta 版本,给跨平台应用开发带来了一种全新的选择,昨天谷歌正式 ...
- leetcode-139-单词拆分(递归超时,动归解决)
题目描述: 给定一个非空字符串 s 和一个包含非空单词列表的字典 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词. 说明: 拆分时可以重复使用字典中的单词. 你可以假设字 ...