集合List、Set、Map详解

List、Set、Map是否继承自Collection接口?

List、Set是map不是,List是线性结构的容器,底层使用数组实现,使用于按数值索引访问元素的情形;Set存储零散的元素且不允许有重复的元素(类似数学中的集合);Map存储的是key-value键值对

阐述ArrayList、Vector、LinkedList的存储性能和特性?

共同点:ArrayList、LinkedList、Vector都是List接口的实现类,存储的数据都是有序的、可重复的。

区别:

ArrayList:作为List的主要实现类;底层使用数组;效率高;线程不安全的;

为什么ArrayList线程不安全?

ArrayList在增加元素时进行两步操作,1、判断size是否能放下add的元素;2、向底层数组中添加元素;因此多个线程同时向List中添加元素会出现  数组越界的异常;或者A线程add的值覆盖了B线程add的值;

线程不安全的解决方法?

工具类Collections中定义 了 synchronizedList(List list)方法,将此ArrayList转化为线程安全的;以读为主的场景中使  CopyOnWriteArrayList解决线程安全问题;CopyOnWrite容器即写时复制的容器。通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。这样做的好处是我们可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器。

CopyOnWrite并发容器用于读多写少的并发场景。比如白名单,黑名单,商品类目的访问和更新场景,假如我们有一个搜索网站,用户在这个网站的搜索框中,输入关键字搜索内容,但是某些关键字不允许被搜索。这些不能被搜索的关键字会被放在一个黑名单当中,黑名单每天晚上更新一次。当用户搜索时,会检查当前关键字在不在黑名单当中,如果在,则提示不能搜索。CopyOnWrite(CopyOnWriteList、CopyOnWriteMap)容器有很多优点,但是同时也存在两个问题,即内存占用问题(add数据需要重新复制一份) 和 数据一致性问题(在add过程中读取的数据是旧数据)。所以在开发的时候需要注意一下。

LinkedList:

底层使用双向链表;对于频繁的插入、删除操作,我们建议使用此类,因为效率高;

Vector:

List的古老实现类;底层使用数组实现;线程安全的,效率低;

ArrayList的底层创建方式:

ArrayList 使用空参构造器创建对象时: jdk7.0版本,底层默认创建10个元素的数组;jdk8.0底层默认创建空数组(当向集合添加元素时将空数组改为10个元素的数组;添加的元素一旦超出了底层数组的长度,就需要扩容,默认扩容为原来的1.5倍,同时,需要将原有数组中的元素复制到新的数组中(赋值方法:Arrays.copyof)。所以为了避免底层频繁的扩容,在已知元素数量的情况下,使用有参构造器创建ArrayList对象,指定其初始化长度;

HashMap、LinkedHashMap、TreeMap、Hashtable异同?

HashMap:Map的主要实现类;线程不安全的,效率高;可以存储null的key和value(存储结构:jdk7.0 数组+链表; jdk8.0 数组+链表+红黑树;解决HashMap线程不安全:CopyOnWriteMap、ConcurrentHashmap

ConcurrentHashmap:底层使用HashMap + Segment (段、部分、分割)实现,默认16个Segment,HashMap的总容量平均分配到每个Segment,插入数据时,首先获取对每个Segment的操作权限;如果没有共享资源,会造成性能浪费;

LinkedHashMap:HashMap的子类,可以按照添加的顺序遍历。对于频繁的遍历效率较高。(在HashMap存储结构的基础上,使用了一对双向链表来记录添加元素的顺序)

TreeMap:可以按照key指定的属性进行排序。底层实现:红黑树

Hashtable:Map的古老实现类;线程安全的,效率低;不可以存储null的key和value

Properties:Hashtable的子类,常常用来处理属性文件。其key和value都是String型

HashMap的实现原理?

HashMap map = new HashMap();/底层创建了长度为16的Entry数组,加载因子是0.75,向HashMap中添加元素,需要首先计算 添加元素 的key的哈希值 (根据key所在类的hashCode()计算得到) ,此哈希值经过处理以后,得到在底层Entry[]数组中要存储的位置i. 如果位置i上没元素,则直接添加成功。如果位置i上已经存在元素(或还有以链表存在的entry3,entry4),则需要通过循环的方法,依次比较 添加元素 的key和其他entry的key是否equals.如果返回值为true.则使用 添加元素 的value去替换equals为true的entry的value.如果遍历一遍以后,发现所有的equals返回都为false,则 添加元素 仍可添加成功。添加元素 指向原来的entry元素。如果添加元素的长度 >= DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR (默认值为12)且新要添加的数组位置不为null的情况下,就进行扩容。默认扩容为原长度的2倍,将原来的数据复制到新的数组中。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值