* ArrayList
* 动态数组,底层是一个数组,默认的容量是10。刚new出来的时候容量是0,add之后是10。可以初始化时自定义容量。
* 当数组放满的时候,会自动扩容为原来的1.5倍。如果还是不够的话,会以当前数据量为容量。
* 查找和替换很快,直接根据下表就可以找到位置
* 插入和删除元素比较慢,它要把后面的元素进行一次复制,位移。再进行插入操作,还要考虑扩容的问题。
* Vector 类似与ArrayList,所有的方法都是被synchronized修饰的。扩容是直接2倍。
* LinkedList
* LinkedList底层是一个双向链表,有一个头节点和一个尾节点,提供了头插linkFirst(e)和尾插linkLast(e)方法
* 他的特点是查询的时候比较慢,插入和删除比较快
* 讲下hashmap底层结构,put操作怎么找到位置的,&运算等价于什么运算?为什么不是线程安全的,1.8是头插还是尾插?怎么保证线程安全
* 底层结构:
* 1.7 数组(16) + 单链表
* 做hash运算,找到要存放数组的位置
* 如果已经有元素在了,进行头插法加入新元素
* 当初使用头插法的原因是因为考虑到后来的数据更可能的被使用到,头插可以更早的别找到。
* 但是在多线程的时候,resize过程中,可能会导致死循环。
* 1.8 数组(16) + 单链表/红黑树(转换)
* 在链表这块使用的是尾插法,避免了死循环的问题。
* 在链表到了一定长度(8)的时候,链表会转换成红黑树,提高查询效率。当红黑树复杂度不够(个数小于6)时,也会转换回链表。
* 扩容:
* 负载因子 0.75,当数组的使用率达到0.75时候,就会进行一次扩容。会创造一个两倍长的数组,再把原来数组里面的元素做hash再put进来。
* 线程安全方案:
* Hashtable
* Collections.synchronized(map)
* ConcurrentHashMap
* ConcurrentHashMap底层,1.7怎么扩容的,1.8怎么保证线程安全
* 1.7 segment
* 使用了分段锁的技术,底层是一个segment数组加链表的形式,每个segment拥有一个锁,当一个线程访问这个segment的时候,不会影响到别的线程访问别的segment。从而提高效率。。
* 1.8 CAS+synchronized
* concurrent包常用的类,集合常用类相关的问题
* AQS
* CountDownLatch
* Semaphore
* CyclicBarrier
* ReentrantLock
* ArrayBlockingQueue
* AtomicInteger