ArrayList与LinkedList异同
- 线程安全
- ArrayList和LinkedList都是不同步,不保证线程安全
- 底层数据结构
- Arraylist 底层使用的是Object数组
- LinkedList 底层使用的是双向链表数据结构
- 插入和删除是否受元素位置的影响
- ArrayList 采用数组存储(顺序存储),插入和删除时间复杂度受影响
- LinkedList 采用链表存储,不受影响
- 是否支持快速随机访问
- LinkedList不支持高效的随机元素访问,而ArrayList支持
- 内存空间占用
- ArrayList的空 间浪费主要体现在在list列表的结尾会预留一定的容量空间
- LinkedList每一个元素都需要消耗比ArrayList更多的空间(存放直接后继和前驱以及自身的数据)
- list遍历方式选择
- 实现了RandomAccess接口的list,优先选择普通for循环,其次foreach
- 未实现的,优先先选择iterator遍历
ArrayList与Vector区别
- Vector类的所有方法都是同步的(同步在多线程编程才有意义)。
- ArrayList非同步,在不需要保证线程安全时通常使用它。
HashMap底层实现
- 该类的
hash
方法也就是扰动函数是为了防止一些实现比较差的 hashCode() 方法,减少碰撞。 - 拉链法,将链表和数组相结合。
- 创建一个链表数组,数组中每一格就是一个链表。若遇到哈希冲突,则将冲突的值加到链表中即可。
HashMap和Hashtable的区别
- 线程是否安全
- HashMap是非线程安全
- HashTable是线程安全,其内部方法基本都经过synchronized修饰
- 效率 HashMap比HashTable高
- 对Null key 和 Null value的支持
- HashMap中null可以作为键,可有多个值为null
- HashTable中的put键值均不可为null
- 初始容量大小和每次扩容量大小的不同
- 创建时如果不指定容量初始值,Hashtable 默认的初始大小为11,之后每次扩充,容量变为原来的2n+1
- HashMap 默认的初始化大小为16。之后每次扩充,容量变为原来的2倍
- 创建时如果给定了容量初始值,那么 Hashtable 会直接使用你给定的大小,而 HashMap 会将其扩充为2的幂次方大小
- 底层数据结构
- JDK1.8 以后的 HashMap 当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间
HashMap 多线程操作导致死循环问题
- 原因在于 HashMap 的扩容 resize()方法
- 扩容是新建一个数组,复制原数据到数组
- 由于数组下标挂有链表,所以需要复制链表,但是多线程操作有可能导致环形链表。
HashSet 和 HashMap 区别
- HashSet 底层就是基于 HashMap 实现的
ConcurrentHashMap 和 Hashtable 的区别
ConcurrentHashMap 和 Hashtable 的区别主要体现在实现线程安全的方式上不同
- 底层数据结构
- JDK1.7的 ConcurrentHashMap 底层采用 分段的数组+链表 实现
- JDK1.8 采用的数据结构跟HashMap1.8的结构一样,数组+链表/红黑二叉树
- JDK1.8之前 数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的
- 实现线程安全的方式
- 在JDK1.7的时候,ConcurrentHashMap(分段锁),由 Segment 数组结构和 HashEntry 数组结构组成。
- JDK1.8直接用 Node 数组+链表+红黑树的数据结构来实现,并发控制使用 synchronized 和 CAS 来操作。
- Hashtable(同一把锁)
Collection底层数据结构总结
- List
- Arraylist: Object数组
- Vector: Object数组
- LinkedList: 双向链表(JDK1.6之前为循环链表,JDK1.7取消了循环)
- Set
- HashSet(无序,唯一): 基于 HashMap 实现的,底层采用 HashMap 来保存元素
- LinkedHashSet: LinkedHashSet 继承与 HashSet,并且其内部是通过 LinkedHashMap 来实现的
- TreeSet(有序,唯一): 红黑树(自平衡的排序二叉树。)
- Map
- HashMap jdk1.8+ 当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间
- LinkedHashMap
- 在上面结构的基础上,增加了一条双向链表,使得上面的结构可以保持键值对的插入顺序
- 同时通过对链表进行相应的操作,实现了访问顺序相关逻辑
- HashTable: 数组+链表组成的,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的
- TreeMap: 红黑树(自平衡的排序二叉树)
反射机制
- 定义:动态获取信息及动态调用对象的方法功能
- 编译
- 静态编译:
- 在编译时确定类型,绑定对象
- 动态编译:
- 运行时确定类型,绑定对象
- 静态编译:
- 反射特点
- 优点:运行期类型的判断,动态加载类,提高代码灵活度
- 缺点:性能瓶颈,相当于一系列解释操作
- 应用场景
- 通过反射去调用对应的字节码
- 通过反射机制实现动态代理设计模式
- 应用框架
- Spring/Hibernate
- JDBC连接数据库用Class.forName()通过反射加载数据库的驱动程序
- Spring经典的xml配置模式,装载Bean过程
- 将程序内所有 XML 或 Properties 配置文件加载入内存中
- Java类里面解析xml或properties里面的内容,得到对应实体类的字节码字符串以及相关的属性信息
- 使用反射机制,根据这个字符串获得某个类的Class实例
- 动态配置实例的属性
List,Set,Map之比较
- List 该接口存储一组不唯一的有序对象
- Set 不允许重复的对象集合
- Map 使用键值对存储,key不允许重复,可以是字符串,也可以是任意对象
comparable 和 comparator
- comparable接口实际上是出自java.lang包 它有一个
compareTo(Object obj)
方法用来排序 - comparator接口实际上是出自 java.util 包它有一个
compare(Object obj1, Object obj2)
方法用来定制排序 - 对objects数组排序,用Arrays.sort()
- 对objects集合进行排序,用Collections.sort()
数组与List转换
- List转数组 toArray(arraylist.size())
- 数组转List Arrays的asList(a)方法
- ArrayList操作接口方法
addAll(Collection<? extends E> c)
并集retainAll(Collection<?> c)
交集removeAll(Collection<?> c)
差集- 无重复并集
list2.removeAll(list1);list1.addAll(list2);