关于各种map的总结理解

HashMap

1.map的特点:key只有一个,而一个key可以有多个value,并且key值不可以出现重复项。就好比,一个孩子只有一个亲生父亲,而一个父亲可以派生出多个亲生孩子。他继承了AbstractMap类。

2.hashMap可以序列化(即实现了Serializable接口,推荐打开源码看一下,141行),所以线程不安全。如果再线程中一般情况下使用ConcurrentHashMap来操作。在每一个分段上都用锁进行保护,从而让锁的粒度更精细一些,并发性能更好,而 HashMap 没有锁机制,不是线程安全的。

3.hashMap的底层在jdk1.8之前主要是数组和链表组成,jdk1.8之后新增了红黑树的特性。数组是hashMap的主体,而链表是为了解决哈希冲突(下方有对hash冲突的解释)。.HashMap中主要是通过key的hashCode来计算hash值(查看每一个map的哈希值下方标注),然后通过hash值选择不同的数组来存储。

只要hashCode相同,计算出来的hash值就一样,如果存储对象多了,就有可能不同的对象计算出来的hash值是相同的,这就出现了所谓的hash冲突,HashMap的底层是通过链表来解决hash冲突的。

具体就是把相同hash值的HashMap,通过链表的形式进行存储,相当于存储的数组就是哈希表,数组的每个元素都是一个单链表的头结点,链表是用来解决hash冲突的,如果不同的key映射到了数组的同一位置,那么就将其放入单链表中。

4.插入元素的方式有jdk1.8之前的头插法,转换成了尾插法

5.HashMap的默认大小为16,并且一 定是2的指数,每次扩容都为old*2。

很多人不知道hashCode这个属性的使用场景。

在最早的数据存储中 ,很多人用txt文件来充当数据库,但是txt文件存储不了特别大量的数据,于是就会建多个txt文件来存储,但是这时候问题来了 如何能通过随机性存储,这时候就用到了hashCode来进行对txt文件连接计算的选择。通过计算HashCode值来将数据写进不同的txt存储,当然现在已经不再这样使用了,总不能回归原始社会。

但是这种写法依旧可以运用到现在分库分表的案例中。

哈希冲突

对应不同的关键字可能获得相同的hash地址,即 key1≠key2,但是f(key1)=f(key2)。这种现象就是冲突,而且这种冲突只能尽可能的减少,不能完全避免。因为哈希函数是从关键字集合和地址集合的映像,通常关键字集合比较大,而地址集合的元素仅为哈希表中的地址值。

HashCode 值查看

     Map<String, Object> map = new HashMap<>();
        map.put("name", "Bob");
        map.put("age", "18");
        map.put("sex", "Boy");
        Iterator<String> iterator = map.keySet().iterator();
        System.out.println("迭代器遍历");
        while (iterator.hasNext()) {
            String key = iterator.next();
            System.out.println("hashCode : >>>>>"+key.hashCode());
        }

​ 显示数据

迭代器遍历
hashCode : >>>>>113766
hashCode : >>>>>3373707
hashCode : >>>>>96511

    public static void main(String[] args) {
        Map<String, Object> map = new HashMap<>();
        map.put("name", "Bob");
        map.put("age", "18");
        map.put("sex", "Boy");
        Iterator<String> iterator = map.keySet().iterator();
        System.out.println("迭代器遍历");
        while (iterator.hasNext()) {
            String key = iterator.next();
            System.out.println(key);
            Object values = map.get(key);
            System.out.println(values);
        }
        System.out.println();
        System.out.println("foreach遍历");
        for (String key : map.keySet()) {
            Object o = map.get(key);
            System.out.println(key + "=" + o);
        }
        System.out.println();
        System.out.println("获取Map中的所有key与value的对应关系");
        Set<Map.Entry<String, Object>> entries = map.entrySet();
        Iterator<Map.Entry<String, Object>> iterator1 = entries.iterator();
        while (iterator1.hasNext()) {
            Map.Entry<String, Object> keys = iterator1.next();
//            System.out.println(keys);
            String key = keys.getKey();
            Object value = keys.getValue();
            System.out.println(key);
            System.out.println(value);
            System.out.println(keys);
        }
    }

LinkedHash

HashMap和双向链表合二为一即是LinkedHashMap

LinkedHash将key和value put进集合时是有序的,根据你添加元素的顺序来决定,LinkedHash是有序的集合,

他继承了HashMap(源码164行),所以LinkedHashMap是具有HashMap的所有特性。只是在细节实现上稍有不同。

HashMap是没有顺序的,当我们希望有序的进行存储数据的时候,就可以使用LinkedMapHash进行存储。然LinkedHashMap增加了时间和空间上的开销,但是它通过维护一个额外的双向链表保证了迭代顺序。即该迭代顺序可以是插入顺序,也可以是访问顺序。

LinkedHash和HashMap区别

  • LinkedHashMap是继承于HashMap,是基于HashMap和双向链表来实现的。
  • HashMap无序;LinkedHashMap有序,可分为插入顺序和访问顺序两种。如果是访问顺序,那put和get操作已存在的Entry时,都会把Entry移动到双向链表的表尾(其实是先删除再插入)。
  • LinkedHashMap存取数据,还是跟HashMap一样使用的Entry[]的方式,双向链表只是为了保证顺序。
  • LinkedHashMap是线程不安全的。

HashTable

一般情况下不怎么使用,即使在线程中人们普遍使用的是ConcurrentHashMap。

hashTable继承了Dictionary类,hashTable的方法是同步的,即线程安全,HashMap的方法不是同步的非线程安全,在多并发的情况下我们可以使用hashTable.

HashTable中不允许有null键和null值,HashMap中允许出现一个null键,可以存在一个或者多个键的值都为null。程序中,对于HashMap,如果使用get(参数为 键)方法时,返回结果为null,可能是该键不存在,也可能是该键对应的值为null,这就出现了结果的二义性。因此,在HashMap中,我们不能使用get()方法来查询键 对应的值,应该使用containskey()方法。

HashTable是直接使用对象的hashCode。HashMap是重新计算hash值。

HashTable的底层实现的数组和初始大小和扩容方式。HashTable初始大小为11,并且每次扩容都为:2*old+1。

HashSet

  1. 底层是以哈希表(数组+链表/红黑树)的方式进行存储数据
  2. 是一个无序的容器(你怎么存进去的 不一定怎么取出来)
  3. 不能存储相同元素,(相同元素回覆盖)
  4. 因为没有下标,所以不能使用普通for循环进行遍历
  5. 允许有null值得出现

ConcurrentHashMap

继承了AbstractMap类

利用synchronized来锁住整张Hash表来实现线程安全,即每次锁住整张表让线程独占。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
在 Vue 中,map 是指将数据对象映射为另一个新的数组,常用于处理需要对数据进行转换的情况。 具体来说,Vue 中的 map 方法可以用于对数组或对象进行遍历,返回一个新的数组。对于数组,map 方法会遍历数组的每一项,并将每一项传入回调函数中进行处理,最终返回一个新的数组。对于对象,map 方法会遍历对象的每一个属性,并将属性值传入回调函数中进行处理,最终返回一个新的数组。 例如,我们可以使用 map 方法将一个数组中的每一项都加上 1: ``` const arr = [1, 2, 3, 4, 5]; const newArr = arr.map(item => item + 1); console.log(newArr); // [2, 3, 4, 5, 6] ``` 在 Vue 中,我们通常使用 map 方法对需要渲染的数据进行处理,以便更好地适配模板。例如,我们可以使用 map 方法将一个数组中的每一项都转换为一个 Vue 组件实例: ``` <template> <div> <my-component v-for="item in items" :key="item.id" :data="item"></my-component> </div> </template> <script> import MyComponent from './MyComponent.vue'; export default { data() { return { items: [ { id: 1, name: 'Item 1' }, { id: 2, name: 'Item 2' }, { id: 3, name: 'Item 3' }, ], }; }, components: { MyComponent, }, computed: { itemComponents() { return this.items.map(item => { return { id: item.id, component: MyComponent, props: { data: item, }, }; }); }, }, }; </script> ``` 在上面的例子中,我们使用 map 方法将 items 数组中的每一个对象都转换为一个包含组件、属性等信息的对象,最终渲染出多个组件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值