第三周复习题
1.ArrayList和LinkedList有什么区别?
ArrayList底层数据结构:基于动态数组实现,根据索引进行数据查询,使用于频繁查询的场景
LinkedList基于双向链表,查询需要遍历查询,但可以根据指针进行插入和删除,适用于频繁插入和删除的场景
2.ArrayList的扩容机制是如何进行的?
ArratList的扩容是通过grow()方法是实现的。当触发扩容时,首先会计算新的容量。新容量一般为旧容量的1.5倍,具体通过
oldCapacity +(oldCapacity>> 1)计算得出
计算出的新容量可能仍然无法满足需求,比如要添加大量元素时,新元素会直接设置为所需的最小容量
新容量还不能超过所允许的最大容量MAX_ARRAY_SIZE(Integer.MAX_VALUE-8),会调用hugeCapacity方法来确定最终容量。
3.LinkedList是单向链表还是双向链表,链表的增删改查
LinkedList在java中是双向链表,它的每个节点都包含了指向前一个节点和后一个节点的引用,这使得它可以在两个方向上进行遍历
增:使用add(E e)方法,将元素添加到链表的尾部。时间复杂度为O(1)
在指定位置插入元素:通过add(int index,E element)方法,可在指定索引位置插入元素O(n)
删除元素:调用remove(Object o),根据索引删除remove(int index)
修改元素:使用set(int index,E element)方法,将指定索引位置元素替换为新元素
查找元素:根据元素查找索引:通过indexOf(Object o)方法,返回指定元素在链表中首次出现的索引,若不存在则返回-1
根据索引获取元素:调用get(int index)
4.如何让ArrayList变的线程安全
Vector是矢量队列,其底层和ArrayList一样是数组,除线程安全外,大多数实现方法和ArrayList逻辑基本一致。从jdk1.2以后,java提供了系统的集合框架,将vector改为实现List接口
Vector 的实现,就是在方法上都加上synchronized
被弃用啦
Collections.synchronizedList,基于集合类的实现,可以简单的使用函数来操作
List list2 = Collections.synchronizedList(new ArrayList)
CopyOnWriteArrayList
CopyOnWriteArrayList是1.5后引入,属于JUC的一部分。他基本的原理还是和ArrayList一样,涉及线程安全的部分,是通过写时复制的方式来实现(从名字中就可以看出)。它内部有个volatile数组来保持数据。在“添加/修改/删除”数据时,会先获取互斥锁,再新建一个数组,并将更新后的数据拷贝到新建的数组中,最后再将该数组赋值给volatile数组,然后再释放互斥锁。
5.HashSet是如何去重的
HahSet在是实现时使用了HashMap的键部分,而值部分总是同一个静态对象PRESENT,这是一个new Object()的实例
这样做可以确保HahSet中的元素是唯一的,因为HashMap保证了键的唯一性,而底层是根据元素的方法 hashCode()和equals()方法共同决定的当向 HashSet 中添加元素时,它会调用该元素的 h