当前位置:首页 » 存储配置 » hashmap怎么存储

hashmap怎么存储

发布时间: 2022-06-27 21:12:07

java中的HashMap的工作原理是什么

一,存储方式: Java中的HashMap是以键值对(key-value)的形式存储元素的。


二,调用原理: HashMap需要一个hash函数,它使用hashCode()和equals()方法来向集合/从集合添加和检索元素。当调用put()方法的时候,HashMap会计算key的hash值,然后把键值对存储在集合中合适的索引上。如果key已经存在了,value会被更新成新值。


三,其他热性: HashMap的一些重要的特性是它的容量(capacity),负载因子(load factor)和扩容极限(threshold resizing)。

② HashMap如何存储数据的

对key进行hash,未发生碰撞,直接存储,发生碰撞,碰撞数小于8,链表存储,大于8,红黑树存储。

参考:

飞升之路 Java学习笔记-HashMap原理

③ C++ Map中的数据存储方式是什么Map和HashMap有什么区别

你要先去了解一下HASH算法
相对MAP来说,HASHMAP具有更高的查询速度。
举个简单的例子来说
MAP中储存为顺序储存,也就是一个接着一个的储存
如一个MAP中存储
1
3
4
三个元素
则,MAP中第一个元素为1,第二个为3,第三个为4
如果想从MAP中查找元素4,则必须从开始进行便利,则必须比较三次。
而HASHMAP中,开始储存的时候,就将即将储存的元素用一个自定义函数将他转变后,存到相应位置

④ hashmap底层实现原理

hashmap底层实现原理是SortedMap接口能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator遍历TreeMap时,得到的记录是排过序的。

如果使用排序的映射,建议使用TreeMap。在使用TreeMap时,key必须实现Comparable接口或者在构造TreeMap传入自定义的Comparator,否则会在运行时抛出java.lang.ClassCastException类型的异常。

Hashtable是遗留类,很多映射的常用功能与HashMap类似,不同的是它承自Dictionary类,并且是线程安全的,任一时间只有一个线程能写Hashtable

从结构实现来讲,HashMap是:数组+链表+红黑树(JDK1.8增加了红黑树部分)实现的。

(4)hashmap怎么存储扩展阅读

源码可知,HashMap类中有一个非常重要的字段,就是 Node[] table,即哈希桶数组。Node是HashMap的一个内部类,实现了Map.Entry接口,本质是就是一个映射(键值对),除了K,V,还包含hash和next。

HashMap就是使用哈希表来存储的。哈希表为解决冲突,采用链地址法来解决问题,链地址法,简单来说,就是数组加链表的结合。在每个数组元素上都一个链表结构,当数据被Hash后,得到数组下标,把数据放在对应下标元素的链表上。

如果哈希桶数组很大,即使较差的Hash算法也会比较分散,如果哈希桶数组数组很小,即使好的Hash算法也会出现较多碰撞,所以就需要在空间成本和时间成本之间权衡,其实就是在根据实际情况确定哈希桶数组的大小,并在此基础上设计好的hash算法减少Hash碰撞。

⑤ 我用一个hashmap存了一个用户的信息,怎么把它保存在一个文件里求指点

我采用对象流,对象流就是以对象为单位写进文件,hashmap集合正好就是一个对象。代码如下:
/**
* 保存进文件
*/
public static void saveFile() {
try(ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(url)))){
oos.writeObject(list);
System.out.println("保存成功");
} catch (IOException e) {
e.printStackTrace();
}
}
1. try(){}catch只是对异常进行捕获和关闭对象流,暂时可不必理会,可用eclipse自动生成。
2. new ObjectOutputStream是创建对象流oos;
3. new BufferedOutputStream是创建缓冲流,什么是缓冲流简单说下就是跟播放视频的缓存差不多的道理,可以批量读写数据;
4. new FileOutputStream(url)这句代码才是对文件进行操作,url是你要操作文件的路径,记住文件路径这里要用反斜杠/,这句代码你可以理解成告诉计算机我要对哪个文件进行操作,并分配相应的内存;记住是文件不是文件夹
5. oos.writeObject(list);最后这一句代码就是把我们的数据从内存写进文件,看writeObject就知道英文这是对象写入 操作,list是集合,你可以改成你的map

⑥ 求高手给解答一下 HashMap 的存储结构,说的越清楚越好,谢谢

HashMap存储结构浅析
1.hashmap是按照存储结构来讲是数组(散列桶)与链表的组合体.

2. 如何计算hashmap中的散列桶的位置。

首先hashcode的值是用来辅助计算散列桶的位置的。如何散列有不同的算法,比如%或 & (散列桶的length-1)

hashmap内部实现会把hashcode的值通过移位等运算再加工一下,保证加工之后的值二进制串中的01分布更加均匀. 数组的index或散列桶的位置等于h & (length-1); 由于length初始值是16, 将来也是基于2的倍数进行自动扩展. 所以length - 1的binary形式一定是一堆1,然后做与运算的结果就是取优化后哈希值的低位
index一定会<=length-1. 正好做为数组的下标. 注意,通常根据hashcode计算散列桶的算法是%。
由于数组的长度默认是16,并且会以2的倍数resize,当数组变大之后,会将以前数组中的每个entry的key重新hash到新的数组里:index=h & (newlength-1)

3.与运算会将计算出的哈希值转换成正的吧?上面有提到过溢出的问题,这样可能会导致二进制符号位为1,得出的值是负数
->HashMap的代码实现,里面的MAX_CAPACITY是Integer Max Value的一半,也就是低位的部分不可能出现在符号位上
注:int是32位,通常最左边的位是符号位. 如果数组的容量length最大的值才是Integer Max Value的一半,那么与之后不会肯定影响到符号位的值.

4.字符串如何计算hashcode

for (int i = 0; i < len; i++) {
h = 31*h + val[off++];


}

如果h的值随着字符串的增长而超过32整型的值.
 不管它如何增大,它只取32位(即使超过32位),所以说会出现负数(超过32位时,32位应该是1. 这样截取之后,首位是1就会表示负数)。

hashcode的范围就是一个int的范围-2^32到2^31

5.

5. 散列的目的是索引化访问

如果一个map使用array来实现,第一个array里面存放key,第二个存放value,k-v的index一致。这样的存储结构,如果要去匹配某个key,需要遍历key array的元素,才能找到。这样查找的效率与array的长度成反比。散列表的出现就是在速度与存储空间找到一个平衡并且每次查找的时间是恒定的, 散列表的目的就象通过index访问array那样,将一切索引化。比如通过hashcode去定位散列桶。散列桶中的元素有可能冲突。hashmap的解决是继续通过equal去比较冲突的元素是否相等。

又例如hashmap的数组位置是0~7。又假如要把某个类的实例存放在以上8个位置中,如果不用hashcode而任意存放,那么当查找时就需要到每个位置去找。
假如类中字段ID,如果hash算法是hashcode=ID%8,以后在查找该类时就可以通过ID除8 求余数直接找到存放的位置。 

但是如果两个类的实例的hashcode被散列到同一个桶,例如9除以8和17除以8的余数都是1,这时9和17就存在冲突,这时就需要equals去进一步比较冲突的元素是否相等。

hashcode来定位实例的散列桶位置然后再通过 equals判断该桶里面的元素是否逻辑相等。

所以二者的用途一定要区分:equals是用来判断是否逻辑相等。hashCode是与hashset,hashtable,hashmap之类的数据结构使用时,用来快速定位散列桶。

6.数据结构get/add与hashcode和equal

6.1 HashSet

对于Set接口的实现类HashSet,它是按照哈希算法来存取集合中的对象,并且因为其继承了Set接口,所以不允许加入相同的元素,这就要使用到equals()和hashCode()方法了。在往HashSet里面添加对象的时候,在Add()的方法内部,它首先调用该对象的hashCode()方法,如果返回的哈希码与集合已存在对象的哈希码不一致(HashMap会缓存放入元素的hashcode值,方便比较,HashSet有可能一样,如果存在一样的hashcode,add失败,直接返回),则add()方法认定该对象没有与集合中的其它对象重复,那么该对象将被添加进集合中。如果hashCode()方法返回的哈希码与集合已存在对象的哈希码一致,那么将调用该对象的equals方法,进一步判断其是否为同一对象(根据java规范,并不强制不相等的二个对象拥有不相等的hashcode,这样就导致不相等的二个对象可能存在一样的hashcode,所以,倒过来,先判断hashcode相等并不能决定二个对象也一定相等,所以,还需要进一步判断equal来决定,以便add即使hashcode相同,但是equal不同的元素到hashset里).

6.2 HashMap 具体可以参考effective java 39~40

hashmap的contains方法与get类似,在使用contains之前,先检查元素的类里面是否实现了hashcode,equal方法。下面的示例中equal中使用id去判断是否相等,hashcode里面一样,也只能使用id去生成。尽量使hashcode里面的元素与equal里面的元素一致。 具体原因可以参考effective java 39~41. 下面示例中直接使用id是因为从第三方调用返回的数据都有id值,并不是需要保存后才会生成id的场景。后一种就不能使用id去判断了。

@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((m_sId == null) ? 0 : m_sId.hashCode());
return result;
}

@Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
SNSProfile other = (SNSProfile) obj;
if (m_sId == null)
{
if (other.m_sId != null)
return false;
}
else if (!m_sId.equals(other.m_sId))
return false;
return true;
}

7.String 类的hashcode的生成函数中
for (int i = 0; i < len; i++) { h = 31*h + val[off++]; } 
为什么要用31×h,这个数字是怎么算出来的或者说用31有什么好处
->
这 种方法HashCode的计算方法可能最早出现在Brian W. Kernighan和Dennis M. Ritchie的《The C Programming Language》中,被认为是性价比最高的算法(又被称为times33算法,因为C中乘数常量为33,JAVA中改为31),实际上,包括List在 内的大多数的对象都是用这种方法计算Hash值。 


9.hashmap的容量是按照2的次方增长,所以length-1的二进制值都是1.

8.resize中的transfer方法

void transfer(Entry[] newTable) {
Entry[] src = table;
int newCapacity = newTable.length;
for (int j =0; j < src.length; j++) {
Entry<K,V> e = src[j];
if (e !=null) {
src[j] =null;
do {
Entry<K,V> next = e.next;
int i = indexFor(e.hash, newCapacity);
//将newTable[i]的引用(C里面的指针)赋给了e.next。也就是使用了单链表的头插入方式(还有种是在尾插入方式)
e.next = newTable[i];
newTable[i] = e;//将e插入后做为第一个节点。上一步e.next的指向是旧的第一个节点。
e = next;
} while (e !=null);
}
}
}

HashMap与LinkedHashMap的区别:LinkedHashMap中的key是按照插入的顺序排序。不象HashMap的key是无序的。主要用在有序访问map的场景

⑦ 怎样利用HashMap类对象存储一本小型词典的信息

HashMap是利用 Key - Value(键-值对)的方式来存对象的,

这样,你就可以把 单词 当作 Key,把注释当 Value,

因为key是唯一的,这样就可以根据单词来取值咯,

取得时候得先判断一下,看此单词有没有存在,否则可能会有空指针异常。

HashMap使用方法,建议你去查看 帮助文档,我就不再罗嗦了。

⑧ hashmap是以什么方式存储数据 arraylist又是以什么方式存储数据

hashmap 实质上一个数组和链表的结合体,记得严尉敏版的C数据结构上将这个称为“散列表”。对于hashmap存储可以这样理解,数组用于存储key,链表用于存储value,每个链表都链接在数组中的一个元素上。

arraylist 实质上就是一个顺序的动态数组,开始时以一默认值开一数组,满了后再扩容,且实现了动态添加和删除。

二者性能区别:hashmpa 用于快速查找,但是arraylist基本上不浪费空间。各有利弊吧

⑨ 怎样用hashmap保存对象

如果要从hashMap里取数据 当你只取Key时,可以这么做 Iterator ite = keySet.iterator(); while(ite.hasNext()){ System.out.println(ite.next());}只取Value时,这么做 Collection values = hm.values(); ite = values.iterator(); while(ite.hasNext()){ System.out.println(ite.next());}都取出来可以这么做 Set content = hm.entrySet(); ite = content. HashMap map = new HashMap(); map.put('key',obj); 这样就保存到HashMap里了。

⑩ HashMap是什么东西

HashMap,中文名哈希映射,HashMap是一个用于存储Key-Value键值对的集合,每一个键值对也叫做Entry。这些个键值对(Entry)分散存储在一个数组当中,这个数组就是HashMap的主干。HashMap数组每一个元素的初始值都是Null。

HashMap是基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。(除了异步和允许使用 null 之外,HashMap 类与 Hashtable 大致相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。

(10)hashmap怎么存储扩展阅读:

因为HashMap的长度是有限的,当插入的Entry越来越多时,再完美的Hash函数也难免会出现index冲突的情况。

HashMap数组的每一个元素不止是一个Entry对象,也是一个链表的头节点。每一个Entry对象通过Next指针指向它的下一个Entry节点。当新来的Entry映射到冲突的数组位置时,只需要插入到对应的链表即可。

热点内容
海康威视存储卡质量如何 发布:2024-09-19 08:55:35 浏览:939
python3默认安装路径 发布:2024-09-19 08:50:22 浏览:516
环卫视频拍摄脚本 发布:2024-09-19 08:35:44 浏览:418
sqlserveronlinux 发布:2024-09-19 08:16:54 浏览:256
编程常数 发布:2024-09-19 08:06:36 浏览:952
甘肃高性能边缘计算服务器云空间 发布:2024-09-19 08:06:26 浏览:162
win7家庭版ftp 发布:2024-09-19 07:59:06 浏览:717
数据库的优化都有哪些方法 发布:2024-09-19 07:44:43 浏览:269
知乎华为编译器有用吗 发布:2024-09-19 07:32:20 浏览:618
访问虚拟机磁盘 发布:2024-09-19 07:28:13 浏览:670