栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java集合

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java集合

 Java集合类框架用过哪些? / Java 中常用的容器有哪些?

Collection 接口下的有:

List:
  • ArrayList
  • LinkedList
  • Vector

Set:
  • HashSet
  • TreeSet
  • LinkedHashSet

Queue:
  • LinkedList
  • PriorityQueue

Map 接口下的有:
  • HashMap

HashMap 主要用来存放键值对,可以存储 null 的 key 和 value,但 null 作为键只能有一个,null 作为值可以有多个。它不保证元素顺序,并且是非线程安全的。

  • TreeMap
  • LinkedHashMap

这几个就够啦,剩下的要么不常用,要么就是淘汰的集合,面试你不提 基本没人问。

要想加深认识,就得去JavaGuide 、全栈知识,多深入学习

ArrayList和LinkedList的区别
  1. 底层数据结构:ArrayList 底层使用的是 Object 数组elementData。LinkedList 底层使用的是双向链表。(JDK1.6 之前为循环链表,JDK1.7 取消了循环)
  2. 是否支持快速随机访问:ArrayList 支持高效的随机元素访问,通过元素的序号快速获取元素对象( get(int index) ),LinkedList 不支持。
  3. 内存空间占用:ArrayList 的空间占用主要体现在在 list 的结尾会预留一定的容量空间。LinkedList 的空间花费则体现在它的每一个元素都需要消耗比 ArrayList 更多的空间(因为要存放两个引用以及数据)
  4. 插入数据的效率:
  • 在尾部插入数据,数据量较小时LinkedList比较快,因为ArrayList要频繁扩容,当数据量大时ArrayList比较快,因为ArrayList扩容是当前容量*1.5,大容量扩容一次就能提供很多空间,当ArrayList不需扩容时效率明显比LinkedList高,因为是直接对数组元素赋值而不需new Node
  • 在首部插入数据,LinkedList较快,因为LinkedList遍历插入位置花费时间很小,而ArrayList需要将原数组所有元素进行一次 arraycopy
  • 插入位置越往中间,LinkedList效率越低,因为它遍历获取插入位置是从两头往中间搜,index越往中间遍历越久,因此ArrayList的插入效率可能会比LinkedList高
  • 插入位置越往后,ArrayList效率越高,因为数组需要复制后移的数据少了,那么 arraycopy 就快了,因此在首部插入数据LinkedList效率比ArrayList高,尾部插入数据ArrayList效率比LinkedList高
HashMap的实现原理 / 底层数据结构?

JDK1.8 之前,HashMap 底层是 数组和链表 实现的,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的。采用拉链法解决冲突。

JDK1.8 以后,HashMap 底层是由 数组+链表+红黑树 组成的。以前在查找的时候,首先根据 hash 值快速定位到数组的具体下标,之后需要顺着链表一个个找下去,时间复杂度取决于链表的长度,为 O(n)。为了降低这部分的开销,JDK1.8中,当链表长度大于默认为 8 的阈值时,会判断当前数组长度是否小于 64,如果小于则先进行数组扩容,否则将链表转化为红黑树,来减少搜索时间。

解决hash冲突的方法?
  1. 开放地址法:一旦发生了冲突,就去寻找下一个空的散列地址。
  2. 再哈希法:对于冲突的哈希值再次进行哈希处理,直到没有哈希冲突。
  3. 拉链法:对于相同的值,使用链表进行连接。这个就是HashMap使用的方法。
  4. 建立公共溢出区:建立公共溢出区存储所有哈希冲突的数据。

用过concurrenthashmap吗,讲一下?

JDK1.7底层实现:

Java使用了分段锁机制实现ConcurrentHashMap。 

ConcurrentHashMap的数据结构是由一个Segment 数组和多个HashEntry组成,Segment 数组的意义就是将一个大的Hash表分割成多个段,而每一个Segment 元素存储的是 HashEntry数组+链表,类似HashMap。

Segment 通过继承 ReentrantLock 来进行加锁,所以每次需要加锁的操作锁住的是一个 segment元素,这样只要保证每个 segment 是线程安全的,也就实现了全局的线程安全。

并发环境下,对于同一个 segment 的操作才需考虑线程同步,不同的 segment 不需要考虑。

默认 Segment 数组长度为 16,并且一旦初始化就不能改变。

也可以认为 ConcurrentHashMap 默认支持最多16个线程并发。

JDK1.8底层实现: 

在JDK1.7之前,ConcurrentHashMap 最大并发度受Segment的个数限制。

因此,在JDK1.8中,ConcurrentHashMap的实现原理 选择了与HashMap类似的数组+链表+红黑树的方式实现,而加锁则采用CAS和synchronized实现。

一个list拼接另一个list用什么方法? 

addAll() 方法:  addAll(int index, Collection c)

其中 index 是可选参数,用来指定插入的位置。默认是添加到末尾。

HashMap怎么遍历key?  创建HashMap对象
Map map = new HashMap<>();
1.EntrySet 遍历:
for (Map.Entry entry : map.entrySet()) {
        System.out.println(entry.getKey() + ":" + entry.getValue());
    }
2.KeySet 遍历:
for (String key : map.keySet()) {
        System.out.println(key + ":" + map.get(key));
    }
3.EntrySet 迭代器遍历:
Iterator> entryIterator = map.entrySet().iterator();
while (entryIterator.hasNext()) {
    Map.Entry entry = entryIterator.next();
    System.out.println(entry.getKey() + ":" + entry.getValue());
}
4.KeySet 迭代器遍历:
Iterator keySetIterator = map.keySet().iterator();
while (keySetIterator.hasNext()) {
    String key = keySetIterator.next();
    System.out.println(key + ":" + map.get(key));
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1020024.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号