作为新手学习java集合的学习笔记,仅为自用,欢迎交流,不喜勿喷哦
文章目录
前言
本文是对于Java集合一些基础知识点的总结,方便后续的回顾。
1.List,Set,Map三者的区别?
List,Set和Map是常见的集合数据类型。
- List :有序集合,可存储重复元素,可存储多个 null 。
- Set :无序集合,不可存储重复元素,只能存储一个 null 。
- Map:使用键值对的方式对元素进行存储, key 是无序的,且是唯一的。 value 值不唯一。不同
的 key 值可以对应相同的 value 值。
2.底层数据结构
- List:
ArrayList :数组
LinkedList :双线链表 - Set :
HashSet :底层基于 HashMap 实现, HashSet 存入读取元素的方式和 HashMap 中的 Key 是
一致的。
TreeSet :红黑树 - Map :
HashMap : JDK1.8之前 HashMap 由数组+链表组成的, JDK1.8之后有数组+链表/红黑树组
成,当链表长度大于8时,链表转化为红黑树,当长度小于6时,从红黑树转化为链表。
HashTable :数组+链表
TreeMap :红黑树
3.快速失败机制 “fail-fast”和安全失败机制“fail-safe”是什么?
- 快速失败:
Java的快速失败机制是Java集合框架中的一种错误检测机制,当多个线程同时对集合中的内容进行修改时可能就会抛出 ConcurrentModificationException 异常。其实不仅仅是在多线程状态下,在单线程中用增强 for 循环中一边遍历集合一边修改集合的元素也会抛出ConcurrentModificationException 异常。 - 安全失败
采用安全失败机制的集合容器,在遍历时不是直接在集合内容上访问的,而是先复制原有集合内容,在拷贝的集合上进行遍历。所以在遍历过程中对原集合所作的修改并不能被迭代器检测到,所以不会抛出 ConcurrentModificationException 异常。
4.Array 和 ArrayList 有何区别?
- Array 可以包含基本类型和对象类型, ArrayList 只能包含对象类型;
- Array 大小是固定的, ArrayList 的大小是动态变化的;
- ArrayList 有着更多的内置方法,如 addAll() , removeAll() ,Array没有。
5.comparable 和 comparator的区别?
Comparable和Comparator是Java中用于比较对象的两种接口,它们之间有以下区别:
- Comparable:
Comparable接口在Java.lang包中定义;
当一个类实现了Comparable接口时,它表明该类的对象是可比较的;
实现Comparable接口的类必须重写compareTo()方法,该方法定义了对象之间的自然排序规则;
自然排序是指类内部定义的默认排序顺序。
- Comparator:
Comparator接口在Java.util包中定义;
Comparator接口用于定义不同于对象自身的比较规则;
它允许在不修改对象本身的情况下定义多种比较方式;
实现Comparator接口的类必须重写compare()方法,该方法定义了两个对象之间的比较规则;
Comparator对象可以用于对集合中的元素进行排序。
6.Collection 和 Collections 有什么区别?
- Collection 是一个集合接口。它提供了对集合对象进行基本操作的通用接口方法。
- Collections 是一个包装类。它包含有各种有关集合操作的静态多态方法,例如常用的 sort()
方法。此类不能实例化,就像一个工具类,服务于Java的 Collection 框架。
7.List集合
遍历一个 List 有哪些不同的方式?
- 普通for 循环遍历:遍历者自己在集合外部维护一个计数器,依次读取每一个位置的元素。
- Iterator 遍历:基于顺序存储集合的 Iterator 可以直接按位置访问数据。基于链式存储集合的
Iterator ,需要保存当前遍历的位置,然后根据当前位置来向前或者向后移动指针。 - foreach 遍历: foreach 内部也是采用了 Iterator 的方式实现,但使用时不需要显示地声明
Iterator 。
ArrayList的扩容机制
ArrayList 的初始容量为10,扩容时对是旧的容量值加上旧的容量数值进行右移一位(位运算,相当于除以2,位运算的效率更高),所以每次扩容都是旧的容量的1.5倍。
ArrayList、Vector、LinkedList的区别
- 线程安全性:
ArrayList是非线程安全的,不同线程同时访问ArrayList可能导致不确定的结果。
Vector是线程安全的,它的方法都是同步的,多个线程可以安全地同时访问Vector。
LinkedList也是非线程安全的,和ArrayList类似,它不具备同步措施。
- 性能:
ArrayList的内部实现是基于数组的动态数组,因此在随机访问时性能较好,但在插入和删除元素时,由于需要移动元素位置,性能较差。
Vector在很大程度上与ArrayList相似,但由于它是线程安全的,因此在并发访问时性能通常较差。
LinkedList的内部实现是基于双向链表,因此在插入和删除元素时性能较好,但在随机访问时性能较差。
- 扩容机制:
ArrayList和Vector都使用了动态数组实现,当数组空间不足时会自动扩容。ArrayList默认情况下每次扩容为原来的1.5倍,而Vector默认情况下每次扩容为原来的2倍。
LinkedList的存储空间由节点组成,不需要像动态数组那样扩容,因为每次添加元素时都会创建一个新的节点。
- 迭代器性能:
在使用迭代器进行遍历时,ArrayList的性能通常优于LinkedList。这是因为ArrayList内部是基于数组的,可以通过索引快速访问元素;而LinkedList需要按照节点顺序一个一个地遍历。
8.Set集合
HashSet与HashMap的区别
HashMap | HashSet |
---|---|
实现了 Map 接口 | 实现了 Set 接口 |
存储键值对 | 存储对象 |
key 唯一, value 不唯一 | 存储对象唯一 |
HashMap 使用键( Key )计算 Hashcode | HashSet 使用成员对象来计算 hashcode 值 |
速度相对较快 | 速度相对较慢 |
9.Map集合
HashMap在JDK1.7和JDK1.8中的区别
JDK1.7 | JDK1.8 | |
---|---|---|
底层结构 | 数组+链表 | 数组+链表/红黑树(链表大于8) |
hash值计算方式 | 9次扰动 = 4次位运算 + 5次异或运算 | 2次扰动 = 1次位运算 + 1次异或运算 |
插入数据方式 | 头插法 | 尾插法 |
扩容后存储位置的计算方式 | 重新进行hash计算 | 原位置或原位置+旧容量 |
HashMap、ConcurrentHashMap及Hashtable 的区别
HashMap(JDK1.8) | ConcurrentHashMap(JDK1.8) | Hashtable | |
---|---|---|---|
底层实现 | 数组+链表/红黑树 | 数组+链表/红黑树 | 数组+链表 |
线程安全 | 不安全 | 安全( Synchronized 修饰Node节点) | 安全( Synchronized 修饰整个表) |
效率 | 高 | 较高 | 低 |
扩容 | 初始16,每次扩容成2n | 初始16,每次扩容成2n | 初始11,每次扩容成2n+1 |
是否支持Null key和Null Value | 可以有一个Null key,Null Value多个 | 不支持 | 不支持 |
总结
以上就是今天要讲的内容,本文仅仅简单介绍了Java集合的一些基础知识,后续还需要不断地深入探索。