Java集合面试题汇总篇 (12)

注意:这里异常的抛出条件是检测到 modCount!=expectedmodCount 这个条件。如果集合发生变化时修改modCount 值刚好又设置为了 expectedmodCount 值,则异常不会抛出。因此,不能依赖于这个异常是否抛出而进行并发操作的编程,这个异常只建议用于检测并发修改的bug。

场景:java.util包下的集合类都是快速失败的,不能在多线程下发生并发修改(迭代过程中被修改)。

安全失败(fail—safe)

采用安全失败机制的集合容器,在遍历时不是直接在集合内容上访问的,而是先复制原有集合内容,在拷贝的集合上进行遍历。

原理:由于迭代时是对原集合的拷贝进行遍历,所以在遍历过程中对原集合所作的修改并不能被迭代器检测到,所以不会触发 Concurrent Modification Exception。

缺点:基于拷贝内容的优点是避免了Concurrent Modification Exception,但同样地,迭代器并不能访问到修改后的内容,即:迭代器遍历的是开始遍历那一刻拿到的集合拷贝,在遍历期间原集合发生的修改迭代器是不知道的。

场景:java.util.concurrent包下的容器都是安全失败,可以在多线程下并发使用,并发修改。

快速失败和安全失败是对迭代器而言的。 快速失败:当在迭代一个集合的时候,如果有另外一个线程在修改这个集合,就会抛出ConcurrentModification异常,java.util下都是快速失败。 安全失败:在迭代时候会在集合二层做一个拷贝,所以在修改集合上层元素不会影响下层。在java.util.concurrent下都是安全失败

如何避免fail-fast

在单线程的遍历过程中,如果要进行remove操作,可以调用迭代器 ListIterator 的 remove 方法而不是集合类的 remove方法。看看 ArrayList中迭代器的 remove方法的源码,该方法不能指定元素删除,只能remove当前遍历元素。

public void remove() { if (lastRet < 0) throw new IllegalStateException(); checkForComodification(); try { SubList.this.remove(lastRet); cursor = lastRet; lastRet = -1; expectedModCount = ArrayList.this.modCount; // } catch (IndexOutOfBoundsException ex) { throw new ConcurrentModificationException(); } }

使用并发包(java.util.concurrent)中的类来代替 ArrayList 和 hashMap

CopyOnWriterArrayList 代替 ArrayList

ConcurrentHashMap 代替 HashMap

Iterator 和 Enumeration 区别

在Java集合中,我们通常都通过 “Iterator(迭代器)” 或 “Enumeration(枚举类)” 去遍历集合。

public interface Enumeration<E> { boolean hasMoreElements(); E nextElement(); } public interface Iterator<E> { boolean hasNext(); E next(); void remove(); }

函数接口不同,Enumeration只有2个函数接口。通过Enumeration,我们只能读取集合的数据,而不能对数据进行修改。Iterator只有3个函数接口。Iterator除了能读取集合的数据之外,也能数据进行删除操作。

Iterator支持 fail-fast机制,而Enumeration不支持。Enumeration 是JDK 1.0添加的接口。使用到它的函数包括Vector、Hashtable等类,这些类都是JDK 1.0中加入的,Enumeration存在的目的就是为它们提供遍历接口。Enumeration本身并没有支持同步,而在Vector、Hashtable实现Enumeration时,添加了同步。
而Iterator 是JDK 1.2才添加的接口,它也是为了HashMap、ArrayList等集合提供遍历接口。Iterator是支持fail-fast机制的:当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件

Comparable 和 Comparator接口有何区别?

Java中对集合对象或者数组对象排序,有两种实现方式:

对象实现Comparable 接口

Comparable 在 java.lang 包下,是一个接口,内部只有一个方法 compareTo()

public interface Comparable<T> { public int compareTo(T o); }

Comparable 可以让实现它的类的对象进行比较,具体的比较规则是按照 compareTo 方法中的规则进行。这种顺序称为 自然顺序

实现了 Comparable 接口的 List 或则数组可以使用 Collections.sort() 或者 Arrays.sort() 方法进行排序

定义比较器,实现 Comparator接口

Comparator 在 java.util 包下,也是一个接口,JDK 1.8 以前只有两个方法:

public interface Comparator<T> { public int compare(T lhs, T rhs); public boolean equals(Object object); }

comparable相当于内部比较器。comparator相当于外部比较器

区别:

Comparator 位于 java.util 包下,而 Comparable 位于 java.lang 包下

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyssfz.html