第九讲
1、对比Hashtable、HashMap、TreeMap有什么不同?
(1)Hashtable、HashMap、TreeMap都是最常见的一些Map实现,是以键值对的形式存储和操作数据的容器类型。
(2)Hashtable是早期Java类库提供的一个哈希表实现,本身是同步的,不支持null键和值,由于同步导致的性能开销,所以已经很少被推荐使用。
(3)HashMap是应用更加广泛的哈希表实现,行为上大致上与HashTable一致,主要区别在于HashMap不是同步的,支持null键和值等。通常情况下,HashMap进行put或者get操 作,可以达到常数时间的性能,所以它是绝大部分利用键值对存取场景的首选,比如,实现一个用户ID和用户信息对应的运行时存储结构。
(4)TreeMap则是基于红黑树的一种提供顺序访问的Map,和HashMap不同,它的get、put、remove之类操作都是O(log(n))的时间复杂度,具体顺序可以由指定 的Comparator来决定,或者根据键的自然顺序来判断。
2、解决哈希冲突的常用方法有:
(1)开放定址法
基本思想是:当关键字key的哈希地址p=H(key)出现冲突时,以p为基础,产生另一个哈希地址p1,如果p1仍然冲突,再以p为基础,产生另一个哈希地址p2,…,直到找出一个不冲突的哈 希地址pi ,将相应元素存入其中。
(2)再哈希法
这种方法是同时构造多个不同的哈希函数: Hi=RH1(key) i=1,2,…,k 当哈希地址Hi=RH1(key)发生冲突时,再计算Hi=RH2(key)……,直到冲突不再产生。
这种方法不易产生聚集,但增加了计算时间。
(3)链地址法
这种方法的基本思想是将所有哈希地址为i的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。
链地址法适用 于经常进行插入和删除的情况。
(4)建立公共溢出区
这种方法的基本思想是:将哈希表分为基本表和溢出表两部分,凡是和基本表发生冲突的元素,一律填入溢出表。
第十讲
1、如何保证容器是线程安全的?ConcurrentHashMap如何实现高效地线程安全?
(1)Java提供了不同层面的线程安全支持。在传统集合框架内部,除了Hashtable等同步容器,还提供了所谓的同步包装器(Synchronized Wrapper),我们可以调用Collections工 具类提供的包装方法,来获取一个同步的包装容器(如Collections.synchronizedMap),但是它们都是利用非常粗粒度的同步方式,在高并发情况下,性能比较低下。
(2)另外,更加普遍的选择是利用并发包提供的线程安全容器类,它提供了:
各种并发容器,比如ConcurrentHashMap、CopyOnWriteArrayList。
各种线程安全队列(Queue/Deque),如ArrayBlockingQueue、SynchronousQueue。
各种有序容器的线程安全版本等。
(3)具体保证线程安全的方式,包括有从简单的synchronize方式,到基于更加精细化的,比如基于分离锁实现的ConcurrentHashMap等并发实现等。具体选择要看开发的场景需求, 总体来说,并发包内提供的容器通用场景,远优于早期的简单同步实现。
第十一讲
1、Java提供了哪些IO方式? NIO如何实现多路复用?
Java IO方式有很多种,基于不同的IO抽象模型和交互方式,可以进行简单区分。
(1)首先,传统的java.io包,它基于流模型实现,提供了我们最熟知的一些IO功能,比如File抽象、输入输出流等。交互方式是同步、阻塞的方式,也就是说,在读取输入流或者写入输 出流时,在读、写动作完成之前,线程会一直阻塞在那里,它们之间的调用是可靠的线性顺序。
java.io包的好处是代码比较简单、直观,缺点则是IO效率和扩展性存在局限性,容易成为应用性能的瓶颈。
很多时候,人们也把java.net下面提供的部分网络API,比如Socket、ServerSocket、HttpURLConnection也归类到同步阻塞IO类库,因为网络通信同样是IO行为。
(2)第二,在Java 1.4中引入了NIO框架(java.nio包),提供了Channel、Selector、Bufer等新的抽象,可以构建多路复用的、同步非阻塞IO程序,同时提供了更接近操作系统底层 的高性能数据操作方式。
(3)第三,在Java 7中,NIO有了进一步的改进,也就是NIO 2,引入了异步非阻塞IO方式,也有很多人叫它AIO(Asynchronous IO)。异步IO操作基于事件和回调机制,可以简单 理解为,应用操作直接返回,而不会阻塞在那里,当后台处理完成,操作系统会通知相应线程进行后续工作。
第十二讲
1、Java有几种文件拷贝方式?哪一种最高效?
Java有多种比较典型的文件拷贝实现方式,比如:
(1)利用java.io类库,直接为源文件构建一个FileInputStream读取,然后再为目标文件构建一个FileOutputStream,完成写入工作。
(2)利用java.nio类库提供的transferTo或transferFrom方法实现。
(3)当然,Java标准类库本身已经提供了几种Files.copy的实现。 对于Copy的效率,这个其实与操作系统和配置等情况相关,总体上来说,NIO transferTo/From的方式可能更快,因为它更能利用现代操作系统底层机制,避免不必要拷贝和上下 文切换。