问:无序性和不可重复性的含义是什么
无序性不等于随机性,无序性是指存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数据的哈希值决定的。
不可重复性是指添加的元素按照 equals()判断时,返回 false,需要同时重写 equals()方法和 HashCode()方法。
问:HashSet、LinkedHashSet 和 TreeSet 的异同
HashSet 是Set 接口的主要实现类 ,底层是 HashMap,线程不安全的,可以存储 null 值;
LinkedHashSet 是 HashSet 的子类,能够按照添加的顺序遍历;
TreeSet 底层使用红黑树,元素是有序的,排序的方式有自然排序和定制排序
问:比较 Queue 与 Deque 的区别
Queue 是单端队列,只能从一端插入元素,另一端删除元素,实现上一般遵循 先进先出(FIFO) 规则。
Queue 扩展了 Collection 的接口,根据 因为容量问题而导致操作失败后处理方式的不同 可以分为两类方法: 一种在操作失败后会抛出异常,另一种则会返回特殊值。
Queue 接口 |
抛出异常 |
返回特殊值 |
插入队尾 |
add(E e) |
offer(E e) |
删除队首 |
remove() |
poll() |
查询队首元素 |
element() |
peek() |
Deque 是双端队列,在队列的两端均可以插入或删除元素。
Deque 扩展了 Queue 的接口, 增加了在队首和队尾进行插入和删除的方法,同样根据失败后处理方式的不同分为两类:
Deque 接口 |
抛出异常 |
返回特殊值 |
插入队首 |
addFirst(E e) |
offerFirst(E e) |
插入队尾 |
addLast(E e) |
offerLast(E e) |
删除队首 |
removeFirst() |
pollFirst() |
删除队尾 |
removeLast() |
pollLast() |
查询队首元素 |
getFirst() |
peekFirst() |
查询队尾元素 |
getLast() |
peekLast() |
事实上,Deque 还提供有 push() 和 pop() 等其他方法,可用于模拟栈。
问:对 PriorityQueue 的认识
PriorityQueue 是在 JDK1.5 中被引入的, 其与 Queue 的区别在于元素出队顺序是与优先级相关的,即总是优先级最高的元素先出队。
要点:
PriorityQueue 利用了二叉堆的数据结构来实现的,底层使用可变长的数组来存储数据
PriorityQueue 通过堆元素的上浮和下沉,实现了在 O(logn) 的时间复杂度内插入元素和删除堆顶元素。
PriorityQueue 是非线程安全的,且不支持存储 NULL 和 non-comparable 的对象。
PriorityQueue 默认是小顶堆,但可以接收一个 Comparator 作为构造参数,从而来自定义元素优先级的先后。
问:HashSet 如何检查重复
当把对象加入HashSet时,HashSet 会先计算对象的hashcode值来判断对象加入的位置,同时也会与其他加入的对象的 hashcode 值作比较,如果没有相符的 hashcode,HashSet 会假设对象没有重复出现。但是如果发现有相同 hashcode 值的对象,这时会调用equals()方法来检查 hashcode 相等的对象是否真的相同。如果两者相同,HashSet 就不会让加入操作成功。
在openjdk8中,HashSet的add()方法只是简单的调用了HashMap的put()方法,并且判断了一下返回值以确保是否有重复元素。 也就是说,在openjdk8中,实际上无论HashSet中是否已经存在了某元素,HashSet都会直接插入,只是会在add()方法的返回值处告诉我们插入前是否存在相同元素。
问:TreeMap 和 TreeSet 在排序时如何比较元素
TreeSet 要求存放的对象所属的类必须实现 Comparable 接口,该接口提供了比较元素的 compareTo()方法,当插入元素时会回调该方法比较元素的大小。TreeMap 要求存放的键值对映射的键必须实现 Comparable 接口从而根据键对元素进行排序。
问:Collections工具类中的sort()方法如何比较元素
Collections 工具类的 sort 方法有两种重载的形式:
第一种要求传入的待排序容器中存放的对象比较实现 Comparable 接口以实现元素的比较。
第二种不强制性的要求容器中的元素必须可比较,但是要求传入第二个参数,参数是Comparator 接口的子类型(需要重写 compare 方法实现元素的比较),相当于一个临时定义的排序规则,其实就是通过接口注入比较元素大小的算法,也是对回调模式的应用(Java 中对函数式编程的支持)。
问:Collection 和 Collections 有什么区别
java.util.Collection 是一个集合接口(集合类的一个顶级接口)。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式,其直接继承接口有List与Set。
Collections则是集合类的一个工具类/帮助类,其中提供了一系列静态方法,用于对集合中元素进行排序、搜索以及线程安全等各种操作。
问:fail-fast 和 fail-safe
fail-fast是Java中的一种 快速失败 机制,java.util包下所有的集合都是快速失败的,快速失败会抛出ConcurrentModificationException异常,fa il-fast 可以理解为一种快速检测机制,它只能用来检测错误,不会对错误进行恢复,fail-fast不一定只在多线程环境下存在,ArrayList也会抛出这个异常,主要原因是由于modCount 不等于expectedModCount。
fail-safe是Java中的一种安全失败机制,它表示的是在遍历时不是直接在原集合上进行访问,而是先复制原有集合内容,在拷贝的集合上进行遍历。由于迭代时是对原集合的拷贝进行遍历,所以在遍历过程中对原集合所作的修改并不能被迭代器检测到所以不会触发 ConcurrentModificationException。java.util.concurrent包下的容器都是安全失败的,可以在多线程条件下使用,并发修改。