1.数组和集合的区别
数组初始化之后长度就固定了,集合不固定
数组中只能存放同一种数据类型。集合中可以存放多种
数组中只能存放有序的元素,可以添加重复元素。集合可以无序,不可以出现无序的元素。
2.ArrayList 1.7版本和1.8版本底层扩容的实现原理
通过一个空参的构造器创建对象时1.7底层创建了长度是10的数组。当我们向集合中添加第11个元素时,底层会进行扩容,扩容为原来数组长度的1.5倍。同时将原数组中的内容复制新的数组中。 元素要求所在的类必须重写equals方法(饿汉式),1.8中并没有直接就创建长度为10的数组,调用add的时候才创建。(懒汉式)
3.collection接口下有什么常用的子类集合,说说底层原理
有List 和 set
list下面有
arrayList :底层是数组,线程不安全,查找快增删慢
LinkedList:底层是双向链表。查找慢,增删插入快
Vector:底层是object数组,线程安全效率低
set下面有
HashSet :是Set的主要实现类,线程不安全,底层是hashMap。初始容量和加载因子都和hashMap一样。
treeSet:可以按照对象的指定属性进行排序
LinkedHashSet:是按照添加元素的顺序进行遍历,因为底层维护了一张链表用来记录添加的顺序
4.说一下map接口中的常用子类。以及底层实现原理
Map分为hashmap和linkedhashmap,hashtable,treemap,
HashMap:是线程不安全的,可以存放null的key和vaule,如果是null默认从第0个查找。
LinkedHashMap:和Hashmap一样,只是可以按照元素添加的顺序进行遍历。底层用双向链表来记录元素添加顺序。
HashTable:是线程安全的。不可能存null。但是Hashtable是表级锁底层方法都是使用synchronized来保证线程安全,而ConcurrentHashMap是段级锁
TreeMap:添加的key-vaule对进行排序,可以考虑订制排序和自然排序,实现Comparator和 Comparable接口。
5.ArrayList 和 Vector 的区别
Vector与ArrayList一样,也是通过数组实现的,Vector类的所有方法都是同步的。它也是线程安全的,而Arraylist是线程异步(ASynchronized)的,是不安全的。如果不考虑到线程的安全因素,一般用Arraylist效率比较高。
使用ArrayList时,如果不指定大小,会生成一个空的数组;使用Vector时,如果不指定大小,会默认生成一个10个元素大小的数组
扩容方面。Vector默认在大小为0的时候就会扩容,第一次扩容容量是2倍,如果还达不到要求,则直接扩容到指定容量
6.ArrayList和LinkedList 的区别和联系
LinkeList 和 ArrayList 都实现了List接口,但是LinkeList还额外实现了Deque接口。
LinkeList 底层是链表,因为实现的Deque接口,所以她还是一个双端队列。链表的结构支持她高效的插入和删除。对查找方法很低效。但是实现的Deque接口的双端队列会一直维护她的头指针和尾指针,所以她对于头部和尾部的查找还是很高效的。
ArrayList和LinkedList都是线程不安全的
底层数据结构不同,ArrayList 是数组,LinkedList 是链表
插入和删除受影响。ArrayList 采用数组存储插入删除的时间复杂度受位置的影响近似为 O(n)。
LinkeList采用链表结构,插入删除不受位置影响,时间复杂度为O(1)
ArrayList支持快速访问随机位置,LinkedList不支持高效访问
内存空间占用问题:ArrayList空间浪费,分配的内存空间即使用了一点点,剩下的空间也会占着。
7.Set不能存放重复元素,其底层是如何实现的
hashcode() 和 equals()…hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置。散列表存储的是键值对(key-value),它的特点是:能根据“键”快速的检索出对应的“值”。这其中就利用到了散列码!(可以快速找到所需要的对象)。
当你把对象加入 HashSet 时,HashSet 会先计算对象的 hashcode 值来判断对象加入的位置,同时也会与其他已经加入的对象的 hashcode 值作比较,如果没有相同的hashcode,HashSet会假设对象没有重复出现。但是如果发现有相同 hashcode 值的对象,这时会调用 equals()方法来检查 hashcode 相等的对象。如果equals方法返回为true,HashSet 就不会让其加入操作成功。如果返回false,就会重新散列到其他位置。
8.HashMap的数据结构
在Java1.8之前 HashMap底层是 数组+链表
在Java1.8之后 HashMap底层是 数组+链表+红黑树。链表长度超过8的时候链表转化成红黑树
9.HashMap中put方法的过程?
调用哈希函数获取Key对应的hash值,再计算其数组下标;
如果没有出现哈希冲突,则直接放入数组;如果出现哈希冲突,则以链表的方式放在链表后面;
如果链表长度超过阀值(TREEIFYTHRESHOLD==8),就把链表转成红黑树,链表长度低于6,就把红黑树转回链表;
如果结点的key已经存在,则替换其value即可;
如果集合中的键值对大于12,调用resize方法进行数组扩容。
10.Hashmap为什么使用红黑树,红黑树是什么?
因为链表长了就会查询慢的问题,红黑树相当于排序数据。可以自动的使用二分法进行定位。性能较高。
红黑树是一种平衡二叉查找树,他的节点是红色或者黑色,根节点是黑色,每个叶子节点都是黑色的空节点,红色的节点他的子节点都是黑色,他可以用变色和旋转来调整平衡