数组:内存存储连续 占用内存多 寻址容易,时间复杂度: 索引查找 (O(1)),按值查找(O(log(2)n)

链表: 内存存储不连续 占用内存少 插入与删除方便,时间复杂度(O(n)) ,

为了结合数组寻址容易与链表的插入删除容易,HashTable应运而生;

java为数据结构中的映射定义了一个接口java.util.Map;它有四个实现类,分别是HashMap

Hashtable LinkedHashMap 和TreeMap.

HashMap: 数据结构:数组+链表+红黑树(或称之为链表的数组),HashMap里面有一个Entry类(key,value,next),可以理解为其存储结构是一个线性数组(Entry[]),

put():

根据key的hashCode得到hash值,然后hash对Entry[].length取模得到下标index,在数组的index 下标位置处添加value,当然这时就要注意当hash值重复时就会发生hash冲突。

解决Hash冲突: 假设Entry[0] = A;进来了一个键值对B,其index值与A相同,这时让B.next = A;

Entry[0] = B;...,这时就解决了hash冲突。也就是说数组中存储的是最后插入的元素。

get():

根据key.hashCode得到hash值对Entry[]取模得到index,这时根据index得到所对应的链表或红黑树,然后根据equea()判断key值是否相等,相等时返回该值,不相等时判断下一个元素,直到该链表中再无元素。

区别:null值,安全性,同步,速度

总结:

Map: map用于存储键值对,根据键得到值,键不允许重复(重复就覆盖了),但允许值重复。

HashMap:hashMap是一个最常用的Map。它根据键的Hashcode值存储数据,根据键可以直接得到它的值,具有很快的访问速度,遍历时,取得数据的顺序都是完全随机的。HashMap只允许一条记录的键为null,允许多个记录的值为null。HashMap不支持线程的同步,即任一时刻可以有多个线程操作HashMap;可能会导致数据不一致。(解决方法:使用SynchronizedMap或者ConcurrentHashMap)所以线程不安全,多个线程无法共享一个HashMap.。

WeakHashMap:WeakHashMap是一种改进的HashMap,它对key实行“弱引用”,当一个key不被外界所引用,则该Key会被GC回收。

HashTable: 与HashMap类似,不同点:不允许键或者值为null,synchronized,支持线程同步,线程安全,多个线程可以共享一个HasTable,即任一时刻,只允许一个线程能写HashTable,这也就导致了HashTable在写入时比较慢。

LinkedHashMap:LinkedHashMap是HashMap的一个子类,保存了记录的插入顺序,在Iterator遍历LinkedHashMap时,先得到的记录一定是先插入的,也可以在构造时用带参数,按照应用次序排序。在遍历时比HashMap慢,不过有种情况例外,当HashMap的容量很大,实际数据较少时,遍历起来可能会比LinkedHashMap慢,因为LinkedHashMap的遍历速度只与实际数据有关,与容量无关,而HashMap的遍历速度与容量有关。

TreeMap:TreeMap实现了SortMap的接口,能够将它保存的记录按照键排序,默认是升序排序。也可以指定排序的比较器,当用Iterator遍历TreeMap时,得到的记录是排过序的。

SynchronizedMap:hashMap存在线程安全问题,因此,在Collections类提供了一个方法返回一个同步版本的HashMap用于多线程环境,该方法返回一个SynchronizedMap实例。SynchronizedMap类是定义在Collection中的一个静态内部类。他实现了Map接口,并对其中的每一个方法实现,通过Synchronized关键字进行了同步控制。但还是存在潜在的安全问题。

ConcurrentHashMap:ConcurrentHashMap提供了HashTable和HashMap以及SynchronizedMap中所不同的锁机制。比起SynchronizedMap,它提供了好得多的并发性。多个读操作几乎总可以并发执行,同时进行的读和写操作也能并发执行,而同时进行的写操作仍然可以不时的并发执行。HashTable采用的锁机制是一次锁定整个hash表,从而同一时刻只能由一个线程对其进行操作;

ConrrentHashMap采用的锁机制是每一次锁定一个桶。

ConcurrentHahMap默认将hash表分为16个桶,诸如get、put、remove等寻常操作只锁当前需要用到的桶。这样一来,原本只能一个线程进入,现在却能同时有16个写线程进行执行,并发性的提升显而易见。前面所说的16个线程指的是写线程,而读操作基本不需要用到锁。只有在size等操作时才会锁定整个表。

在迭代方面,ConcurrentHashMap使用了一种不同的迭代方式。在这种迭代方式中,当Iterator被创建后集合在再发生改变就不会再是抛出ConcurrentModificationException,取而代之的是在改变时new新的数据从而不影响原有的数据,iterator完成后再将头指针替换为新的数据,这样Iterator线程就可以使用原来老的数据,从而写线程也可以并发的完成改变。

Hashmap与LinkedHashMap与TreeMap使用场景:

一般情况下,我们用的最多的是HashMap,在Map 中插入、删除和定位元素,HashMap 是最好的选择。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。如果需要输出的顺序和输入的相同,那么用LinkedHashMap 可以实现,它还可以按读取顺序来排列.

Hashmap与SynchronizedMap与ConcurrentHashMap使用场景:

一般情况下使用HashMap,但是HashMap线程不安全,所以在多线程的场景下使用SynchronizedMap,但是SynchronizedMap也存在一些潜在的安全问题(如迭代时数据更改),这时我们拥有更好的选择concurrenthashMap。

扩展:

CopyOnWriteArrayList可以用于什么应用场景?

答:CopyOnWriteArrayList用于读多写少的并发场景,比如白名单、黑名单。

CopyOnWrite容器即写时复制的容器。通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。这样做的好处是我们可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器。

CopyOnWriteArrayList(免锁容器)的好处之一是多个迭代器同时遍历和修改这个列表时,不会抛出ConcurrentModificationException。在CopyOnWriteArayList中,写入将会导致创建整个底层数组的副本,而源数组将保留在原地,使得复制的数组在被修改时,读取操作可以安全地执行。

android基础之Map系列相关推荐

  1. Android基础知识巩固系列 Android之四大组件——ContentProvider(内容提供者)

    因为最近要面试,于是打算整理整理一下Android的基础知识,由于之前本人已经学习过大概的Android基础知识,这里主要讲这四大组件.五大存储.六大布局.网络请求等这些内容,其他一些等有时间再整理, ...

  2. Android音视频学习系列(五) — 掌握音频基础知识并使用AudioTrack、OpenSL ES渲染PCM数据

    系列文章 Android音视频学习系列(一) - JNI从入门到精通 Android音视频学习系列(二) - 交叉编译动态库.静态库的入门 Android音视频学习系列(三) - Shell脚本入门 ...

  3. 重学Android基础系列篇(五):Android虚拟机指令

    前言 本系列文章主要是汇总了一下大佬们的技术文章,属于Android基础部分,作为一名合格的安卓开发工程师,咱们肯定要熟练掌握java和android,本期就来说说这些~ [非商业用途,如有侵权,请告 ...

  4. 重学Android基础系列篇(二):泛型

    前言 本系列文章主要是汇总了一下大佬们的技术文章,属于Android基础部分,作为一名合格的安卓开发工程师,咱们肯定要熟练掌握java和android,本期就来说说这些~ [非商业用途,如有侵权,请告 ...

  5. Android音视频学习系列(六) — 掌握视频基础知识并使用OpenGL ES 2.0渲染YUV数据

    系列文章 Android音视频学习系列(一) - JNI从入门到精通 Android音视频学习系列(二) - 交叉编译动态库.静态库的入门 Android音视频学习系列(三) - Shell脚本入门 ...

  6. go where 不等于_go基础之map迭代(四)

    写在之前 在文章<go基础之map-写在前面(一)>的示例代码 for k, v := range m3 { fmt.Println(k, v)} 就是go的map的迭代方法,查看该代码的 ...

  7. Android基础_数据存储

    2019独角兽企业重金招聘Python工程师标准>>> Android基础_数据存储 Android数据存储的几种形式 继承SQLiteOpenHelper public class ...

  8. 开发者福利:史上最全Android 开发和安全系列工具

    取证工具 bandicoot - 一个Python工具箱,用于分析手机元数据.它提供了一个完整,易于使用的环境,数据科学家分析手机元数据.只需几行代码,加载数据集,可视化数据,执行分析和导出结果. A ...

  9. Android基础——四大组件之Activity

    这几天继续回顾了一些Android基础方面的知识,今天跟大家一起回顾下Android四大组件中的Activity.虽然很基础,但工欲善其事,必先利其器.我们只有打好夯实的基础,才能在技术开发这条道路上 ...

  10. 《Android构建MVVM》系列(一) 之 MVVM架构快速入门

    前言 本文属于<Android构建MVVM>系列开篇,共六个篇章,详见目录树. 该系列文章旨在为Android的开发者入门MVVM架构,掌握其基本开发模式. 辅以讲解Android Arc ...

最新文章

  1. python列表切片口诀-切片 - 廖雪峰的官方网站
  2. php怎么输出以前的时间,php输出指定时间以前时间格式的方法_PHP
  3. 东八区转为0时区_格林尼治时间转换为北京时间
  4. java 蓝桥杯算法训练 数组查找及替换
  5. 生意倒闭的老板基本死于这两个思维
  6. EXCEL与数据透视表整理
  7. 突破某书新版登录流程逆向分析
  8. 过去式-ed的发音规则
  9. 马化腾:这一类中层干部,我最多忍你半年
  10. ibm服务器维修论坛,IBM通病
  11. RobotStudio动态夹具的创建
  12. linux系统怎么数据恢复,linux系统数据恢复
  13. [02]Hello World!
  14. Spring Boot HTTP over JSON 的错误码异常处理
  15. Word目录中自动添加自定义样式的多级标题的方法
  16. 如何降低自动化维护成本?
  17. TopK推荐的评价指标
  18. C Programming学习笔记【谭浩强老师编】(第四章选择结构程序设计)02 逻辑运算符和逻辑表达式
  19. Android开发者选项——GPU呈现模式分析
  20. 用python通过139邮箱发送Email

热门文章

  1. 将数字转为ASCII码
  2. 软件测试报告有哪些内容?
  3. 广告系统数据采集方法介绍
  4. 基于Arduino控制伺服电机(舵机)
  5. vue+element-ui的列表查询条件/筛选条件组件二次封装(Vue项目)——内置去除前后空格功能
  6. 思维破局:认知水平低,是一个人最致命的短板
  7. java中tab键_Java 9中的JShell中Tab键的用途是什么?
  8. linux,centos7环境下,安装RabbitMQ
  9. 我的管理成长与思考 - 那些领导的真相,理解和思考
  10. 服务器装系统鼠标键盘用不了怎么办,教你重装系统鼠标键盘不能用怎么解决?...