小结-JAVA中的集合类

JAVA中的集合

在这里插入图片描述

Collection

一、List(有序,可重复)
1.ArrayList
底层数据结构是数组,

  • 查询快,增删慢(数组的大小是固定的,可以通过索引迅速查询,但是在增删时,需要额外创建一个数组,将原数组的值拷贝过去进行增删)
  • 线程不安全,效率高

2.LinkedList
底层数据结构是链表,

  • 查询慢,增删快(链表的增删只需要让其指针指向下下个节点来完成,因此增删快)
  • 线程不安全,效率高

3.Vector
底层数据结构是数组,

  • 查询快,增删慢
  • 线程安全,效率低

二、Set(无序,不可重复)
HashSet
底层数据结构是哈希表
哈希表依赖两个方法:hashCode()和equals()

Map(双列集合)

1.HashMap:存储数据采用的哈希表结构,元素的存取顺序不能保证一致。由于要保证键的唯一、不重复,需
要重写键的hashCode()方法、equals()方法。

2.LinkedHashMap:HashMap下有个子类LinkedHashMap,存储数据采用的哈希表结构+链表结构通过链
表结构可以保证元素的存取顺序一致;通过哈希表结构可以保证的键的唯一、不重复
,需要重写键的
hashCode()方法、equals()方法。

//常用的语法格式
public V put(K key, V value) : 把指定的键与指定的值添加到Map集合中。
public V remove(Object key) : 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的
值。
public V get(Object key) 根据指定的键,在Map集合中获取对应的值。
public Set<K> keySet() : 获取Map集合中所有的键,存储到Set集合中。
public Set<Map.Entry<K,V>> entrySet() : 获取到Map集合中所有的键值对对象的集合(Set集合)

一般来说,Map集合都是键(key)是唯一的,value是可以重复多个的,所以在遍历集合时,可以采取键找值的方式进行。

拓展

HashTable与HashMap的区别联系
(1)HashTable和HashMap都实现了Map接口,但是HashTable的实现是基于Dictionary抽象类。

(2)在HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,既可以表示HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键,而应该用containsKey()方法来判断。而在HashTable中,无论是key还是value都不能为null。

(3)HashTable是线程安全的,它的方法是同步了的,可以直接用在多线程环境中。HashMap则不是线程安全的。在多线程环境中,需要手动实现同步机制。

(4)底层实现细节不同:HashMap底层是数组 + 链表的形式,当阈值超过8,会转为数组+红黑树。HashMap初始化时,会建立一个16位的数组,数组内存储的是键值对,也就是entry,每个entry的在数组中存储的位置(下标值)通过key的hash值%数组的长度得到,如果有两个entry的下标值相同,则会将其插入在对应的链表头部;
计算index:hash(key.hashCode())%len
打个比方, 第一个键值对A进来,通过计算其key的hash得到的index=0,记做:Entry[0] = A。一会后又进来一个键值对B,通过计算其index也等于0,现在怎么办?HashMap会这样做:B.next = A,Entry[0] = B,如果又进来C,index也等于0,那么C.next = B,Entry[0] = C;这样我们发现index=0的地方其实存取了A,B,C三个键值对,他们通过next这个属性链接在一起。所以疑问不用担心。

在这里插入图片描述
扩容机制: HashMap内存储数据的Entry数组默认是16,如果没有对Entry扩容机制的话,当存储的数据一多,Entry内部的链表会很长,这就失去了HashMap的存储意义了。所以HasnMap内部有自己的扩容机制。HashMap内部有:
变量size,记录hashmap底层数组中已用槽的数量;
变量threshold,它是hashmap的阈值,用于判断是否需要调整hashmap的容量(threshold = 容量*加载因子),加载因子默认是0.75;
当size大于threshold时,默认扩容,也就是3/4的size被用完时,就会扩容,每次扩容为oldsize *2;

HashTable底层:数组+链表,初始化数组容量为11,下标索引则是key的hash值与0x7FFFFFFF进行与运算,然后再对tab.length取模
(最大整数值)
扩容:newsize = olesize*2+1
计算index的方法:index = (hash & 0x7FFFFFFF) % tab.length

2、更好的选择:ConcurrentHashMap Java 5中新增了ConcurrentMap接口和它的实现类ConcurrentHashMap。 ConcurrentHashMap提供了和HashTable以及SynchronizedMap中所不同的锁机制。HashTable中采用的锁机制是一次锁住整个hash表,从而同一时刻只能有一个线程对其进行操作;而ConcurrentHashMap中则是一次锁住一个桶。ConcurrentHashMap默认将hash表分为16个桶,诸如get,put,remove等常用操作只锁住当前需要用到的桶。这样,原来只能一个线程进入,现在却能同时有16个写线程执行,并发性能的提升是显而易见的。 上面说到的16个线程指的是写线程,而读操作大部分时候都不需要用到锁。只有在size等操作时才需要锁住整个hash表。 在迭代方面,ConcurrentHashMap使用了一种不同的迭代方式。在这种迭代方式中,当iterator被创建后集合再发生改变就不再是抛出ConcurrentModificationException,取而代之的是,在改变时new新的数据从而不影响原有的数据,iterator完成后再将头指针替换为新的数据,这样iterator可以使用原来老的数据,而写线程也可以并发的完成改变。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值