`
wusuoya
  • 浏览: 641700 次
  • 性别: Icon_minigender_2
  • 来自: 成都
社区版块
存档分类
最新评论

HashSet、HashMap,散列表数据结构(哈希表)

    博客分类:
  • Java
 
阅读更多

很多开发者,初学者都知道HashSet无序,不可重复,线程非同步。底层是哈希表结构。
但它是怎么做到的?什么是散列表数据结构(哈希表)?有什么特性?都清楚吗?不清楚继续往下看。

它是这样做到的:

先来看HashSet的源码,首先看默认构造器:
[java] 
public HashSet() { 
    map = new HashMap<E,Object>(); 

// ok,我们看到构造器中new了一个HashMap。key使用了泛型,value使用Object。 

public HashSet() {
 map = new HashMap<E,Object>();
}
// ok,我们看到构造器中new了一个HashMap。key使用了泛型,value使用Object。
再来看add方法源码:
[java]
private static final Object PRESENT = new Object(); 
public boolean add(E e) { 
    return map.put(e, PRESENT)==null; 

// PRESENT是一个Object类型的常量,用来当做map的value. 也就是说,你以后在HashSet中存储的元素都是HashMap中key,value全部使用Object。 

private static final Object PRESENT = new Object();
public boolean add(E e) {
 return map.put(e, PRESENT)==null;
}
// PRESENT是一个Object类型的常量,用来当做map的value. 也就是说,你以后在HashSet中存储的元素都是HashMap中key,value全部使用Object。
HashMap的key是不可以重复的,保证元素唯一的依据是对象的hashCode跟equals方法。
而HashSet不就是用HashMap的key来存储元素嘛,也就保证了元素的唯一性。包括迭代器也是HashMap中keySet方法取得的iterator。
[java] 
public Iterator<E> iterator() { 
    return map.keySet().iterator(); 

public Iterator<E> iterator() {
 return map.keySet().iterator();
}
通过上面的介绍,已经对HashSet比较了解了,我们知道HashSet底层是用了HashMap。
要想知道怎么做到存取速度快的,我们直接看HashMap就好了。

散列表数据结构(哈希表)

散列表(Hash table,也叫哈希表),是根据关键字(Key value)而直接进行访问的数据结构。
也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

HashMap底层就是散列表数据结构,即数组和链表的结合体,
底层是一个数组结构,数组中的每一项又是一个链表。这样做有什么好处呢?
数组能够提供对元素的快速访问但不易于扩展(如果不知道元素脚标,还得进行遍历查找),链表易于扩展但不能对其元素进行快速访问。
怎样做到两全其美,就是散列表数据结构。

我们来看看HashMap中元素存跟取的实现方式:

首先明白,HashMap根据key的hashCode计算出元素在Entry数组中的位置,然后再Entry内部链表中存放key,value。

 

我们来对HashMap存取元素的过程来做一个小的总结:

元素(key,value)在HashMap中被封装进Entry数组。
put元素的时候,根据key的hash值定位元素在Entry数组中的索引,如果当前索引有元素,就通过equals方法进行比较,将元素存进当前Entry的链表中适当的位置。
get元素的时候,根据key的hash值定位元素在Entry数组中的索引,然后通过equals方法定位元素在链表中的位置,取出该元素。

性能分析:

因为元素的存取是通过hash算法进行的,所以速度都没的说。
在查找操作中,唯一影响性能的是在链表中,但实际只要优化好了key对象hashCode跟equals方法,就会避免链表中的数据过多而导致查找性能变慢。

再一个非常影响性能的是数组扩容操作,当使用默认的DEFAULT_INITIAL_CAPACITY对HashMap进行初始化的时候,
如果元素个数非常多,会导致扩容次数增加,每次扩容都会进行元素位置的重新分配,这是相当耗费性能的。
如果能预算好元素个数,就应该避免使用默认的DEFAULT_INITIAL_CAPACITY,可在HashMap的构造函数中为其指定一个初始值。

问题解决:

hashCode必须和equals保持兼容(equals方法的判断依据和计算hashCode的依据相同),这样做是为了避免链表中的数据过多。

 

参考链接:http://www.2cto.com/kf/201306/218390.html

分享到:
评论

相关推荐

    哈希表操作

    哈希表,也被称为散列表,是一种数据结构,它提供了快速的数据存储和检索能力。在哈希表中,数据是以键值对的形式存储的,通过一个哈希函数将键(Key)转换为数组的索引位置,从而实现快速访问。在Java中,哈希表的...

    java-leetcode面试题解哈希表第1题两数之和-题解.zip

    哈希表,又称散列表,是一种数据结构,它通过键(key)与值(value)的对应关系,提供快速的数据存取。在Java中,我们通常使用HashMap或HashSet来实现哈希表。哈希表的查找、插入和删除操作的时间复杂度可以达到O(1)...

    java-leetcode面试题解哈希表第36题有效的数独-题解.zip

    哈希表,又称散列表,是一种高效的数据结构,能够快速地进行查找、插入和删除操作。它的核心思想是通过散列函数将键(key)映射到数组的特定位置,从而实现O(1)的平均时间复杂度。在这个面试题中,哈希表被用来验证...

    java-leetcode面试题解哈希表第387题字符串中的第一个唯一字符-题解.zip

    哈希表,又称散列表,是一种高效的数据结构,它能够提供快速的插入、查找和删除操作,平均时间复杂度为O(1)。 题目描述: 给定一个只包含小写字母的非空字符串s,找出字符串中的第一个不重复的字符。如果存在这样的...

    Java版本数据结构实验报告

    此外,哈希表(散列表)是另一种高效的数据结构,它通过键值对进行存储,提供快速查找、插入和删除操作。Java的HashMap和HashSet类是哈希表的典型应用。哈希函数的质量直接影响了哈希表的性能,避免哈希冲突是设计...

    HashSet的实现原理

    关于HashSet与HashMap的区别,在底层数据结构上,二者都基于哈希表,但存储的方式不同。HashMap存储的是键值对(key-value pairs),键不唯一,值可以重复。而HashSet存储的是唯一元素,可以看作是键的集合,只是不...

    《实用数据结构教程Java语言描述》源代码

    8. 散列表:散列表是哈希表的一种,用于快速查找,基于哈希函数将键映射到槽位。 9. 堆:堆是一种特殊的树形数据结构,满足堆属性(最大堆或最小堆)。Java中的PriorityQueue是堆的实现,常用于优先级队列。 10. ...

    数据结构(Java版)

    哈希表,也称为散列表,通过哈希函数将键映射到数组的索引上,实现快速查找。Java的HashMap类是哈希表的一种实现,提供O(1)的平均时间复杂度进行插入、查找和删除操作。哈希表在数据库索引、缓存等方面有广泛应用。 ...

    数据结构—Java语言描述

    7. **散列表(哈希表)**:散列表提供快速的查找、插入和删除操作,它的实现基于哈希函数。Java中的HashMap类和HashSet类是散列表的常见应用。 在"数据结构—Java语言描述"课程中,你将学习到如何在Java中实现这些...

    数据结构(Java版)

    7. 散列表(哈希表):散列表提供快速的插入、查找和删除操作,Java中的HashMap和HashSet都是散列表的实现。 8. 排序算法:包括冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序等,这些算法在Java中都有...

    《恋上数据结构》第1季度 + 第2季 完整学习笔记,从0实现的 Java 数据结构大全。.zip

    5. 哈希表:哈希表,也称为散列表,通过哈希函数将键映射到数组的索引,提供快速的查找、插入和删除操作。Java的HashMap类是哈希表的典型实现,而HashSet类则是基于哈希表的无序集合。 6. 树:二叉树是一种特殊的树...

    数据结构代码JAVA版本

    9. **散列表**:散列表是一种通过散列函数实现快速查找的数据结构,如Java中的`HashMap`和`HashTable`。 10. **排序与查找算法**:如快速排序、归并排序、冒泡排序、二分查找等,它们与数据结构密切相关,影响着...

    数据结构(java)

    "数据结构(java)"这个主题涵盖了Java实现的各种常见数据结构,包括数组、链表、栈、队列、树、图、哈希表等,这些都是编程中不可或缺的基础工具。 1. **数组**:数组是最基础的数据结构,它允许我们存储相同类型...

    java数据结构源码

    11. 散列表:散列表是一种根据关键字直接访问数据的位置的数据结构,常用于实现缓存、查找表等。Java的`java.util.HashMap`和`java.util.LinkedHashMap`是两种常见的散列表实现。 12. 双向链表:双向链表中的每个...

    Java数据结构课件

    6. **散列表(哈希表)**:散列表通过哈希函数将键映射到存储位置,提供快速查找、插入和删除操作。Java的`HashMap`和`HashSet`类是散列表的典型应用,它们实现了键值对的存储和唯一性。 7. **树**:树结构包括...

    JavaHashSet和HashMap源码剖析编程开发技术

    HashMap则是一个键值对的无序存储容器,它通过哈希表(散列表)的数据结构实现,允许null键和null值。HashMap通过键的哈希值快速找到对应的值,提供O(1)的平均时间复杂度。在HashMap中,如果两个键的哈希值相同,...

    武汉大学 数据结构课件

    此外,Set接口提供了不包含重复元素的数据结构,如HashSet和TreeSet,分别基于哈希表和红黑树实现。Map接口则用于存储键值对,如HashMap和TreeMap,它们也各有其性能特点。 接下来,我们来谈谈树结构。二叉树是最...

    Java数据结构和算法中文第二版

    - **散列表(Hash Table)**:`java.util.HashMap`和`java.util.HashSet`分别提供了散列表的实现。 此外,还可以使用Java语言特性,如递归、循环等来实现各种算法。 ### 结论 掌握数据结构与算法不仅能够帮助开发者...

Global site tag (gtag.js) - Google Analytics