一列键值对数据,存储在一个table中,如何通过数据的关键字快速查找相应值呢?不要告诉我一个个拿出来比较key啊。
大家都知道,在所有的线性数据结构中,数组的定位速度最快,因为它可通过数组下标直接定位到相应的数组空间,就不需要一个个查找。而哈希表就是利用数组这个能够快速定位数据的结构解决以上的问题的。
具体如何做呢?大家是否有注意到前面说的话:“数组可以通过下标直接定位到相应的空间”,对就是这句,哈希表的做法其实很简单,就是把Key通过一个固定的算法函数既所谓的哈希函数转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当作数组的下标,将value存储在以该数字为下标的数组空间里,而当使用哈希表进行查询的时候,就是再次使用哈希函数将key转换为对应的数组下标,并定位到该空间获取value,如此一来,就可以充分利用到数组的定位性能进行数据定位。
不知道说到这里,一些不了解的朋友是否大概了解了哈希表的原理,其实就是通过空间换取时间的做法。到这里,可能有的朋友就会问,哈希函数对key进行转换,取余的值一定是唯一的吗?这个当然不能保证,主要是由于hashcode会对数组长度进行取余,因此其结果由于数组长度的限制必然会出现重复,所以就会有“冲突”这一问题,至于解决冲突的办法其实有很多种,比如重复散列的方式,大概就是定位的空间已经存在value且key不同的话就重新进行哈希加一并求模数组元素个数,既 (h(k)+i) mod S , i=1,2,3…… ,直到找到空间为止。还有其他的方式大家如果有兴趣的话可以自己找找资料看看
有很多人讨论访问数组和Map哪个快
直接访问数组下标当然最快咯,O(1)的时间。 可以直接定位到下标所对应的数组的值!!但问题是你通常都不知道要访问的元素的下标是多少,1这个时候就要遍历数组来找到这个元素,这个时候map的优势就体现出来了,通常比数组要快!!
map是用来查找的。
请问hashtable类里面的hash函数是怎么样的?
他是调用每个类自己本身的hashCode的方法来确定的
public synchronized V put(K key, V value)
{
// Make sure the value is not null
if (value == null)
{
throw new NullPointerException();
}
// Makes sure the key is not already in the hashtable.
Entry tab[] = table;
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {
if ((e.hash == hash) && e.key.equals(key))
{
V old = e.value;//e.hash应该是这个哈希表中元素得到hashcode的静态变量!!
e.value = value;
return old;
}
}
modCount++;
if (count >= threshold) {
// Rehash the table if the threshold is exceeded
rehash();
tab = table;
index = (hash & 0x7FFFFFFF) % tab.length;
}
// Creates the new entry.
Entry<K,V> e = tab[index];
tab[index] = new Entry<K,V>(hash, key, value, e);//存入哈希表中
count++;
return null;
这是存入时的代码!!根据获取hashcode 对数组的大小取余!~获取下标!
if ((e.hash == hash) && e.key.equals(key))
{
V old = e.value;//e.hash
e.value = value;
return old;
}
看这段代码!但出现key相同时会把第二个存储第一个忽略掉
关于hash函数的如何取看链接
http://baike.baidu.com/view/549615.htm
下面看两个面试题
a)请问哈希表 (hashtable) 是如何存储数据的 ?
答案: Hashtable 是用来存储 key 和 value 对的数据结构 , 根据设定的 hash 函数 H(key) 和处理冲突的方法将一组关键字( key )映象到一个有限的连续的地址集(区间)上,并以关键字在地址集中的“象”作为记录在表中存储位置,这种表便成为 hashtable.
b)是否两个键值通过 hash 函数产生的映射地址会一样?怎么办?
答案 : 是,一般情况下,完全避免冲突是很难的。因为通常关键字集合会比目标地址空间大。哈希函数要尽量避免冲突(避免不同的关键字产生相同的 hash 值),使一组关键字的哈西地址尽可能的均匀分布在整个地址区间。所以有一些冲突处理方法:开放定址法,再哈希法,链地址法(用链表保存冲突的值),公共溢出区。
分享到:
相关推荐
在"LeetCode--HashTable-master"这个项目中,可能包含了多种哈希表相关的LeetCode题解,涵盖了各种哈希表的应用场景,如查找、计数、去重、最短路径等问题。通过深入理解和实践这些题解,可以更好地掌握哈希表的使用...
哈希表节点结构 struct Node:表示哈希表中的一个节点,包含键、值以及指向下一个节点的指针。 哈希表结构 struct HashTable:...销毁哈希表函数 destroyHashTable:释放哈希表的内存,包括每个链表的节点和数组本身。
接下来,创建一个`HashTable`结构体,包含数组和数组长度: ```c typedef struct HashTable { HashNode **buckets; int size; } HashTable; ``` 然后,编写初始化、插入、查找和删除等基本操作的函数。初始化...
HashMap和HashTable是Java中两个常用的数据结构,都是基于哈希表实现的,但它们之间存在着一些关键的区别。本文将深入探讨HashMap和HashTable的底层原理,并总结常见的面试题。 HashMap的底层原理 HashMap是Java中...
1. 哈希函数:哈希函数是散列表的核心,它接受一个输入(通常是字符串或任何其他数据类型),并返回一个介于0和数组大小减1之间的整数。一个好的哈希函数应该使得不同输入映射到数组的不同位置,降低冲突的可能性。 ...
哈希表(HashTable)是一种非常重要的数据结构,它在计算机科学和编程中有着广泛的应用。哈希表基于“键值对”(Key-Value Pair)的概念,通过将键(Key)映射到值(Value)来存储数据,使得数据的查找、插入和删除...
在Java中,哈希表的典型实现包括`java.util.HashMap`和`java.util.Hashtable`类。 ### 哈希表基本原理 哈希表的核心在于哈希函数,它能将任意大小的键转化为固定大小的索引。理想的哈希函数能将不同的键均匀分布到...
2. **计算索引:**使用哈希值和数组长度计算出数组中的索引位置。 3. **查找元素:**在该索引位置上的链表或红黑树中遍历,通过`equals()`方法找到目标元素。 4. **返回结果:**如果找到元素,则返回其值;否则返回...
- **Hashtable**:古老的哈希表实现,线程安全但效率低。 - **ConcurrentHashMap**:线程安全的哈希表实现,适用于多线程环境。 #### 4. Set接口的实现类 - **HashSet**:基于HashMap实现的Set,不保证元素的顺序...
- HashMap和Hashtable都是基于哈希表的Map接口实现。HashMap是线程不安全的,允许多个null键和值;而Hashtable则是线程安全的,不允许键或值为null。 - HashSet和HashMap类似,不同的是HashSet实现Set接口,不允许...
哈希表(Hashtable) Hashtable 类提供了一种在用户定义键结构的基础上来组织数据的手段。例如,在地址列表的哈希表中,你可以根据邮政编码作为键来存储和排序数据,而不是通过人名。哈希表键的具体含义完全取决于...
2. **集合和数组的区别**: - 数组是固定大小的,存储同类型的元素,而集合的大小可变,可以存储不同类型的数据。 - 集合提供了更多的操作,如添加、删除、查找等,而数组的操作相对较少。 - 集合支持泛型,可以...
- **HashMap底层原理**:基于哈希表实现,使用负载因子和数组大小动态调整以保证性能,解决冲突使用开放寻址法或链地址法。 - **排序算法**:冒泡排序、选择排序、插入排序、快速排序、归并排序等,各有优缺点,...
- **堆内存**:用于存储对象实例和数组,又细分为新生代和老年代。 - **非堆内存**:包括方法区和程序计数器等,用于存储类信息、常量、静态变量等。 - **垃圾回收**:通过垃圾回收机制自动管理堆内存中的对象生命...
- 常见数据结构(栈、队列、链表、树、图、哈希表)及其应用。 以上只是Java面试宝典中的部分核心知识点,实际面试中还会涉及到更深入的技术讨论,如性能调优、代码质量、设计原则以及项目经验等。对于每个主题,...
- HashMap和Hashtable:基于哈希表的键值对存储,HashMap非同步,Hashtable同步。 - Set接口:不允许重复元素的集合,如HashSet和TreeSet。 6. **输入/输出流(I/O)** - 文件操作:读写文件,包括字符流...
9. 集合和数组的区别:集合提供了动态大小、多样化操作等优点,而数组是固定大小、静态类型的数据结构。 理解并熟练掌握Java集合框架是每个Java开发者的基础,这不仅包括接口的使用,还涉及到它们的实现原理和性能...
- **堆区**:用于存放对象实例和数组。 - **栈区**:用于线程私有的局部变量、操作数栈等。 - **程序计数器**:记录当前线程所执行的字节码的行号指示器。 - **本地方法栈**:支持Native方法的执行。 - **方法...