40个Java面试问题和答案(2)
40个Java ___面试问题和答案xx
我们可以使用任何类作为Map的key,然而在使用它们之前,需要考虑以下几点:
(1)如果类重写了equals()方法,它也应该重写hashCode()方法。
(2)类的所有实例需要遵循与equals()和hashCode()相关的规则。请参考之前提到的这些规则。
(3)如果一个类没有使用equals(),你不应该在hashCode()中使用它。
(4)用户自定义key类的最佳实践是使之为不可变的,这样,hashCode()值可以被缓存起来,拥有更好的性能。不可变的类也可以确保hashCode()和equals()在未来不会改变,这样就会解决与可变相关的问题了。
比如,我有一个类MyKey,在HashMap中使用它。
//传递给MyKey的name参数被用于equals()和hashCode()中
MyKey key = new MyKey('Pankaj'); //assume hashCode=1234
myHashMap.put(key, 'Value');
// 以下的代码会改变key的hashCode()和equals()值
key.setName('Amit'); //assume new hashCode=7 ___0
//下面会返回null,因为HashMap会尝试查找存储同样索引的key,而key已被改变了,匹配失败,返回null
myHashMap.get(new MyKey('Pankaj'));
那就是为何String和Integer被作为HashMap的key大量使用。
Map接口提供三个 ___视图:
(1)Set keyset():返回 ___p中包含的所有key的一个Set视图。
___是受 ___p支持的, ___p的变化会在 ___中反映出来,反之亦然。当一个迭代器正在遍历一个 ___时,若 ___p被修改了(除迭代器自身的移除操作以外),迭代器的结果会变为未定义。
___支持通过Iterator的Remove、Set.remove、removeAll、retainAll和clear操作进行元素移除,从 ___p中移除对应的映射。它不支持add和addAll操作。
(2)Collection values():返回一个 ___p中包含的所有value的一个Collection视图。
这个collection受 ___p支持的, ___p的变化会在collection中反映出来,反之亦然。当一个迭代器正在遍历一个collection时,若 ___p被修改了(除迭代器自身的移除操作以外),迭代器的结果会变为未定义。
___支持通过Iterator的Remove、Set.remove、removeAll、retainAll和clear操作进行元素移除,从 ___p中移除对应的映射。它不支持add和addAll操作。
(3)Set > entrySet():返回一个 ___p钟包含的所有映射的一个 ___视图。
这个 ___受 ___p支持的, ___p的变化会在collection中反映出来,反之亦然。当一个迭代器正在遍历一个 ___时,若 ___p被修改了(除迭代器自身的移除操作,以及对迭代器返回的entry进行setValue外),迭代器的结果会变为未定义。
___支持通过Iterator的Remove、Set.remove、removeAll、retainAll和clear操作进行元素移除,从 ___p中移除对应的映射。它不支持add和addAll操作。
**********
(1)HashMap允许key和value为null,而HashTable不允许。
(2)HashTable是同步的,而HashMap不是。所以HashMap适合单线程环境,HashTable适合多线程环境。
(3)在Java1.4中引入了LinkedHashMap,HashMap的一个子类,假如你想要遍历顺序,你很容易从HashMap转向LinkedHashMap,但是HashTable不是这样的,它的顺序是不可预知的。
(4)HashMap提供对key的Set进行遍历,因此它是fail-fast的,但HashTable提供对key的Enumeration进行遍历,它不支持fail-fast。
(5)HashTable被认为是个遗留的类,如果你寻求在迭代的时候修改Map,你应该使用CocurrentHashMap。
对于在Map中插入、删除和定位元素这类操作,HashMap是最好的选择。然而,假如你需要对一个有序的key ___进行遍历,TreeMap是更好的选择。基于你的collection的大小,也许向HashMap中添加元素会更快,将 ___p换为TreeMap进行有序key的遍历。
ArrayList和Vector在很多时候都很类似。
(1)两者都是基于索引的,内部由一个数组支持。
(2)两者维护插入的顺序,我们可以根据插入顺序来获取元素。
(3)ArrayList和Vector的迭代器实现都是fail-fast的。