1.基础
1.1 交换两个数字
两数相加保存和值—-中规中矩的办法
1 | private void swap(){ |
两数异或保存两数状态—-高大上的方法
1 | // 一个数对其他数异或两次,该数本身不变。一个数对其自身异或,结果为0 |
1.2 try..finally返回值
1 | public int a () { |
1 | public int a () { |
1.3 StringBuffer、StringBuilder
相同点:
- 三者都是final,不允许被继承
- 都是char[]数组实现的
不同点:
- String是不可变对象,其他两者是可变的
- StringBuilder效率快,不加锁,线程不安全。StringBuffer加锁,保证线程安全。
- String适合操作少量字符串。StringBuilder适合单线程下大量字符串操作。StringBuffer适合多线程下大量字符串操作。
2.集合
2.1 Vector,List的区别
线程安全:
- ArrayList:底层是基于数组实现,线程不安全,查询和修改快,插入和删除慢
- LinkedList:底层是基于双向链表实现,线程不安全,查询和修改慢,插入和删除快
- Vector:底层是基于数组实现,线程安全,使用Synchronized加锁
使用场景:
- Vector已经很少使用了
- 增加和删除场景多,使用LinkedList
- 查询和修改场景多,使用ArrayList
2.2 ArrayList保证线程安全
- 自己封装一个类,进行加锁操作
- 使用Collections.synchronizedList,使用synchronized加锁
- 使用CopyOnWriteArrayList,使用ReenterLock加锁
2.3 CopyOnWriteArrayList
- CopyOnWriteArrayList适用于读多写少的场景。读操作是不需要加锁的,写操作需要加锁。
- SynchronizedLock读写操作都使用synchronized加锁,写的性能比CopyOnWriteArrayList好,但是读的操作比CopyOnWriteArrayList差
- CopyOnWriteArrayList的设计思想:读写分离 + 最终一致。读操作的时候,读取的是旧的数组。而写数据的时候是加锁的,只有把新的数组引用赋值后,才能读取到新的数据,这就保证了最终一致性。
- 缺点:内存占用问题,由于写时复制,内存里面同时存在两个对象占用的空间,如果对象大则容易发生YoungGC和FullGC
2.4 List扩容机制
JDK1.7之前默认容量是10,JDK1.7之后默认容量是0.
未指定集合容量,默认是0,若已经指定大小则集合大小为指定大小。
当集合第一次添加元素时,集合容量扩容为10。当集合容量超过10的时候,扩容的计算方法为
原始容量 + 原始容量 / 2
.
2.5 HashMap、TreeMap
HashMap是基于数组和链表实现的,可以实现快速的存储和检索,但是元素是无序的。适合插入、删除和定位元素。
TreeMap使用存储结构是平衡二叉树,可以通过Comparator接口实现自定义排序,但是一般性能比HashMap差。
2.6 线程安全的HashMap
- 使用Collections.synchronizedMap
- 使用ConcurrentHashMap