hashmap的存储结构
‘壹’ hashtable hashmap treeset treemap的存储结构是什么
hashset内部结构是使用hashmap实现的,当然是散列表。
treemap和treeset是树形结构
‘贰’ java中的hashmap是一种什么数据结构
您好,提问者: HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。 当然,HashMap是一个不同步的类。 我们都知道迭代时候会转换为Set,说明底层具备了Set的特性。 Set的底层结构:无序、根据HashCode判断,如果HashCode一样再去判断
‘叁’ hashmap是以什么方式存储数据 arraylist又是以什么方式存储数据
hashmap 实质上一个数组和链表的结合体,记得严尉敏版的C数据结构上将这个称为“散列表”。对于hashmap存储可以这样理解,数组用于存储key,链表用于存储value,每个链表都链接在数组中的一个元素上。
arraylist 实质上就是一个顺序的动态数组,开始时以一默认值开一数组,满了后再扩容,且实现了动态添加和删除。
二者性能区别:hashmpa 用于快速查找,但是arraylist基本上不浪费空间。各有利弊吧
‘肆’ android中hashmap是什么意思有什么作用
在认识hashmap中要先认识Map。在数组中我们是通过数组下标来对其内容索引的,而在Map中我们通过对象来对对象进行索引,用来索引的对象叫做key,其对应的对象叫做value。
HashMap的初始过程 :在并发环境下使用HashMap
而没有做同步,可能会引起死循环,关于这一点,sun的官方网站上已有阐述,这并非是bug。
HashMap的数据结构 :HashMap主要是用数组来存储数据的,我们都知道它会对key进行哈希运算,哈系运算会有重复的哈希值,对于哈希值的冲突,HashMap采用链表来解决的。在HashMap里有这样的一句属性声明:
transient Entry[]
table;
因此hashmap可以在andriod中用来存储数据。
‘伍’ hashmap底层实现原理
hashmap底层实现原理是SortedMap接口能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator遍历TreeMap时,得到的记录是排过序的。
如果使用排序的映射,建议使用TreeMap。在使用TreeMap时,key必须实现Comparable接口或者在构造TreeMap传入自定义的Comparator,否则会在运行时抛出java.lang.ClassCastException类型的异常。
Hashtable是遗留类,很多映射的常用功能与HashMap类似,不同的是它承自Dictionary类,并且是线程安全的,任一时间只有一个线程能写Hashtable
从结构实现来讲,HashMap是:数组+链表+红黑树(JDK1.8增加了红黑树部分)实现的。
(5)hashmap的存储结构扩展阅读
从源码可知,HashMap类中有一个非常重要的字段,就是 Node[] table,即哈希桶数组。Node是HashMap的一个内部类,实现了Map.Entry接口,本质是就是一个映射(键值对),除了K,V,还包含hash和next。
HashMap就是使用哈希表来存储的。哈希表为解决冲突,采用链地址法来解决问题,链地址法,简单来说,就是数组加链表的结合。在每个数组元素上都一个链表结构,当数据被Hash后,得到数组下标,把数据放在对应下标元素的链表上。
如果哈希桶数组很大,即使较差的Hash算法也会比较分散,如果哈希桶数组数组很小,即使好的Hash算法也会出现较多碰撞,所以就需要在空间成本和时间成本之间权衡,其实就是在根据实际情况确定哈希桶数组的大小,并在此基础上设计好的hash算法减少Hash碰撞。
‘陆’ HashMap如何存储数据的
对key进行hash,未发生碰撞,直接存储,发生碰撞,碰撞数小于8,链表存储,大于8,红黑树存储。
参考:
飞升之路 Java学习笔记-HashMap原理
‘柒’ HashMap是什么东西
HashMap,中文名哈希映射,HashMap是一个用于存储Key-Value键值对的集合,每一个键值对也叫做Entry。这些个键值对(Entry)分散存储在一个数组当中,这个数组就是HashMap的主干。HashMap数组每一个元素的初始值都是Null。
HashMap是基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。(除了异步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
(7)hashmap的存储结构扩展阅读:
因为HashMap的长度是有限的,当插入的Entry越来越多时,再完美的Hash函数也难免会出现index冲突的情况。
HashMap数组的每一个元素不止是一个Entry对象,也是一个链表的头节点。每一个Entry对象通过Next指针指向它的下一个Entry节点。当新来的Entry映射到冲突的数组位置时,只需要插入到对应的链表即可。
‘捌’ Java中HashMap和TreeMap的区别深入理解
HashMap底层是用数组做的,TreeMap是基于树做的
这么做的结果就是HashMap的数据在不停的添加的时候效率会比较低,而对于查找的效率是比较快的,TreeMap对于添加的效率是比较高的但是对于查找的效率要相对比较低一些
这里简单从底层说一下,我就不从具体的实现上说,只从数据结构和大致的原理上来补充一下我的答案。
HashMap这个类在存储的时候,首先根据key来计算机将要存储的key-value映射对存储在数组的什么位置上,当计算出位置后就把这个映射对存储到这个位置上。当读取的时候,首先根据key来计算出一个位置来,到数组的相应的位置上去读取数据,如果没有数据,则表示此Map中不存在该映射对,若存在则直接返回。说到这里就可以解释一下为什么对于不停地存储的效率相对比较低了,首先在初始化的时候对于数组的长度给了一个初始的长度,当往这里面添加数据达到一定的程度的时候就没法继续添加数据了,继续添加数据的冲突就会增大,或者没法添加数据(这里有一个衡量的量就是装填因子,是指这个数组中的添加的数据的个数和数组长度的比值,在java中比较合理的装填因子数是0.75),当数据添加到这个程度的时候不能不让用户继续添加数据吧,总得解决继续添加数据的问题啊,于是提出了解决方案,即开一个更大的数组,把当前上的每一个数据重新在更大的数组上计算位置,并把数据复制过去,这样完成的数组的扩大,看完这个我们知道,这个过程是很耗时的,所以说对于不停的存储数据时效率是比较低的。这里有没有一个稍微好一点的解决方案或者说不需要进行数组的扩大吗,我们能不能一开始在初始化的时候就把数组的空间开辟的足够大,这样就不用在存储的过程进行复制了,可以吗,答案是肯定的,java给我们提供了这个在初始化的时候的方式。但是,也是有问题的那就是我们的数据不够多,就会造成空间的浪费。有没有一个速度即快又不浪费空间的方式呢,解决方案也有一个,那就是在开始的时候我们就能很好的预测数据的规模,这样我们在开始的时候按照相应的规模进行初始化,这样就很好了,实际中我们是不能很好的预测这个规模的。于是对于这种情况提出了下一个解决方案TreeMap。
TreeMap是一个基于树的存储结构,学过数据结构的应该知道,树的实现方式是基于指针实现的,在Java中是用引用模拟实现的,这里大家都知道,其实树的读取效率并不低,这里是相对于数组的顺序查找来说的,但是与HashMap的查找方式相比就有了差距,HashMap是上来先问你在哪,直接就去取数据了,TreeMap需要遍历,也就是需要挨个询问你是我要的东西吗,对比一下,是就返回,不是就继续查找,于是查找的效率就低了,但是它解决了HashMap数组扩大的时候的效率问题,就是新添加的数据可以往里面添加,不会出现复制的情况,这里就是由于模拟的指针的缘故实现的。
其实从总体来说这两个各有利弊,我们在使用的时候需要根据实际的需要来选择相应的类。
‘玖’ 关于C++中的哈希表
构
{int elem[MAXSIZE]; //数据元素体
HAVEORNOT elemflag[MAXSIZE]; //元素状态标志,没有记录、有记录、有过记录但已被删除
int count; //哈希表中当前元素的个数
}HashTable;
BOOL DeleteHash(HashTable &H,Record e)
{//在查找成功时删除待删元素e,并返回True,否则返回False
int p;
if(!SearchHash(H,e.keynum,p)) //表中不存在待删元素
return False;
else
{H.elemflag[p]=DELKEY; //设置标志为DELKEY,表明该元素已被删除
H.count--; //哈希表当前长度减一
return True;
}
}
BOOL SearchHash(HashTable H,int k,int &p)
{//在开放寻址哈希表H中查找关键字为k的数据元素,若查找成功,以p指示
//待查数据元素在表中的位置,并返回True;否则,以p指示插入位置,并
//返回False
int p1;
p1=p=Hash(k); //求得哈希地址
while(H.elemflag[p]==HAVEKEY&&k!=H.elem[p])
//该位置中填有记录并且关键字不相等
{p++; //冲突处理方法:线性探测再散列
if(p>=MAXSIZE) p=p%MAXSIZE; //循环搜索
if(p==p1) return False; //整个表已搜索完,没有找到待查元素
}
if(k==H.elem[p]&&H.elemflag[p]==HAVEKEY) //查找成功,p指示待查元素位置
return True;
else return False; //查找不成功
}
‘拾’ 画出hashmap数据结构图,怎么将hashmap变成线程安全
结构体:
typedefstruct_node{
void*key;
void*val;
struct_node*next;
}hashnode;
hashnode代表一个存储节点,包含了指向其key域的指针、一个指向其val域的指针、一个作为hash冲突处理的链表指针。
实际使用时, 需要定义一个头节点,由于hasmap一般是设定一个桶的大小,比如4096,那么你需要定义一个4096个元素的数组,数组的每一个元素可以指向一个hashnode节点,因此,这个数组的定义应该是 hashnode* head[4096]
插入时,根据传入的key算一个hash值,这个hash值由你指定的一个hash_function计算出来,然后插入到head桶中的一个位置
线程安全只需要在Insert操作和get操作时加一个读写锁即可