1.Hashtableï¼HashMapåTreeMapçåºå«
2.java面试精讲,对比Hashtable、HashMap、TreeMap有什么不同?
Hashtableï¼HashMapåTreeMapçåºå«
Java为æ°æ®ç»æä¸çæ å°å®ä¹äºä¸ä¸ªæ¥å£java.util.Mapï¼å®æå个å®ç°ç±»ï¼åå«æ¯HashMapãHashTableãLinkedHashMapåTreeMapã
è¿éä»ç»è¿4ä¸å®ä¾çç¨æ³ååºå«ã
å ³é®ææ¯åæï¼
Mapç¨äºåå¨é®å¼å¯¹ï¼æ ¹æ®é®å¾å°å¼ï¼å æ¤ä¸å 许é®éå¤ï¼å¼å¯ä»¥éå¤ã
l ï¼1ï¼HashMapæ¯ä¸ä¸ªæ常ç¨çMapï¼å®æ ¹æ®é®çhashCodeå¼åå¨æ°æ®ï¼æ ¹æ®é®å¯ä»¥ç´æ¥è·åå®çå¼ï¼å ·æå¾å¿«ç访é®é度ãHashMapæå¤åªå 许ä¸æ¡è®°å½çé®ä¸ºnullï¼ä¸å 许å¤æ¡è®°å½çå¼ä¸ºnullãHashMapä¸æ¯æ线ç¨çåæ¥ï¼å³ä»»ä¸æ¶å»å¯ä»¥æå¤ä¸ªçº¿ç¨åæ¶åHashMapï¼å¯è½ä¼å¯¼è´æ°æ®çä¸ä¸è´ãå¦æéè¦åæ¥ï¼å¯ä»¥ç¨Collections.synchronizedMap(HashMap map)æ¹æ³ä½¿HashMapå ·æåæ¥çè½åã
l ï¼2ï¼Hashtableä¸HashMap类似ï¼ä¸åçæ¯ï¼å®ä¸å 许记å½çé®æè å¼ä¸ºç©ºï¼å®æ¯æ线ç¨çåæ¥ï¼å³ä»»ä¸æ¶å»åªæä¸ä¸ªçº¿ç¨è½åHashtableï¼ç¶èï¼è¿ä¹å¯¼è´äºHashtableå¨åå ¥æ¶ä¼æ¯è¾æ ¢ã
l ï¼3ï¼LinkedHashMapä¿åäºè®°å½çæå ¥é¡ºåºï¼å¨ç¨IteraoréåLinkedHashMapæ¶ï¼å å¾å°çè®°å½è¯å®æ¯å æå ¥çãå¨éåçæ¶åä¼æ¯HashMapæ ¢ãæHashMapçå ¨é¨ç¹æ§ã
l ï¼4ï¼TreeMapè½å¤æå®ä¿åçè®°å½æ ¹æ®é®æåºï¼é»è®¤æ¯æååºæåºï¼ä¹å¯ä»¥æå®æåºçæ¯è¾å¨ãå½ç¨IteraoréåTreeMapæ¶ï¼å¾å°çè®°å½æ¯æè¿åºçãTreeMapçé®åå¼é½ä¸è½ä¸ºç©ºã
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
public class TestMap {
public static void init(Map map){
if (map != null){
String key = null;
for (int i=5; i>0; i--){
key = new Integer(i).toString() + ".0";
map.put(key, key.toString());
//Mapä¸çé®æ¯ä¸éå¤çï¼å¦ææå ¥ä¸¤ä¸ªé®å¼ä¸æ ·çè®°å½ï¼
//é£ä¹åæå ¥çè®°å½ä¼è¦çå æå ¥çè®°å½
map.put(key, key.toString() + "0"); }
}
}
public static void output(Map map){
if (map != null){
Object key = null;
Object value = null;
//使ç¨è¿ä»£å¨éåMapçé®ï¼æ ¹æ®é®åå¼
Iterator it = map.keySet().iterator();
while (it.hasNext()){
key = it.next();
value = map.get(key);
System.out.println("key: " + key + "; value: " + value );
}
//æè 使ç¨è¿ä»£å¨éåMapçè®°å½Map.Entry
Map.Entry entry = null;
it = map.entrySet().iterator();
while (it.hasNext()){
//ä¸ä¸ªMap.Entry代表ä¸æ¡è®°å½
entry = (Map.Entry)it.next();
//éè¿entryå¯ä»¥è·å¾è®°å½çé®åå¼
//System.out.println("key: " + entry.getKey() + "; value: " + entry.getValue());
}
}
}
public static boolean containsKey(Map map, Object key){
if (map != null){
return map.containsKey(key);
}
return false;
}
public static boolean containsValue(Map map, Object value){
if (map != null){
return map.containsValue(value);
}
return false;
}
public static void testHashMap(){
Map myMap = new HashMap();
init(myMap);
//HashMapçé®å¯ä»¥ä¸ºnull
myMap.put(null,"ddd");
//HashMapçå¼å¯ä»¥ä¸ºnull
myMap.put("aaa", null);
output(myMap);
}
public static void testHashtable(){
Map myMap = new Hashtable();
init(myMap);
//Hashtableçé®ä¸è½ä¸ºnull
//myMap.put(null,"ddd");
//Hashtableçå¼ä¸è½ä¸ºnull
//myMap.put("aaa", null);
output(myMap);
}
public static void testLinkedHashMap(){
Map myMap = new LinkedHashMap();
init(myMap);
//LinkedHashMapçé®å¯ä»¥ä¸ºnull
myMap.put(null,"ddd");
myMap.put(null,"aaa");
//LinkedHashMapçå¼å¯ä»¥ä¸ºnull
myMap.put("aaa", null);
output(myMap);
}
public static void testTreeMap(){
Map myMap = new TreeMap();
init(myMap);
//TreeMapçé®ä¸è½ä¸ºnull
//myMap.put(null,"ddd");
//TreeMapçå¼ä¸è½ä¸ºnull
//myMap.put("aaa", null);
output(myMap);
}
public static void main(String[] args) {
System.out.println("éç¨HashMap");
TestMap.testHashMap();
System.out.println("éç¨Hashtable");
TestMap.testHashtable();
System.out.println("éç¨LinkedHashMap");
TestMap.testLinkedHashMap();
System.out.println("éç¨TreeMap");
TestMap.testTreeMap();
Map myMap = new HashMap();
TestMap.init(myMap);
System.out.println("æ°åå§åä¸ä¸ªMap: myMap");
TestMap.output(myMap);
//æ¸ ç©ºMap
myMap.clear();
System.out.println("å°myMap clearåï¼myMap空äºä¹? " + myMap.isEmpty());
TestMap.output(myMap);
myMap.put("aaa", "aaaa");
myMap.put("bbb", "bbbb");
//å¤æMapæ¯å¦å å«æé®æè æå¼
System.out.println("myMapå å«é®aaa? "+ TestMap.containsKey(myMap, "aaa"));
System.out.println("myMapå å«å¼aaaa? "+ TestMap.containsValue(myMap, "aaaa"));
//æ ¹æ®é®å é¤Mapä¸çè®°å½
myMap.remove("aaa");
System.out.println("å é¤é®aaaåï¼myMapå å«é®aaa? "+ TestMap.containsKey(myMap, "aaa"));
//è·åMapçè®°å½æ°
System.out.println("myMapå å«çè®°å½æ°: " + myMap.size());
}
}
è¾åºç»æï¼
éç¨HashMap
key: null; value: ddd
key: 3.0; value: 3.
key: aaa; value: null
key: 4.0; value: 4.
key: 1.0; value: 1.
key: 5.0; value: 5.
key: 2.0; value: 2.
éç¨Hashtable
key: 4.0; value: 4.
key: 1.0; value: 1.
key: 3.0; value: 3.
key: 5.0; value: 5.
key: 2.0; value: 2.
éç¨LinkedHashMap
key: 5.0; value: 5.
key: 4.0; value: 4.
key: 3.0; value: 3.
key: 2.0; value: 2.
key: 1.0; value: 1.
key: null; value: aaa
key: aaa; value: null
éç¨TreeMap
key: 1.0; value: 1.
key: 2.0; value: 2.
key: 3.0; value: 3.
key: 4.0; value: 4.
key: 5.0; value: 5.
æ°åå§åä¸ä¸ªMap: myMap
key: 3.0; value: 3.
key: 4.0; value: 4.
key: 1.0; value: 1.
key: 5.0; value: 5.
key: 2.0; value: 2.
å°myMap clearåï¼myMap空äºä¹? true
myMapå å«é®aaa? true
myMapå å«å¼aaaa? true
å é¤é®aaaåï¼myMapå å«é®aaa? false
myMapå å«çè®°å½æ°: 1
æºç åæï¼
éåMapæ两ç§æ¹æ³ï¼
ï¼1ï¼mapçkeySet()æ¹æ³è·å¾é®çéåï¼åè°ç¨é®éåçiteratoræ¹æ³è·å¾é®çè¿ä»£å¨ï¼ä»¥æ¤è¿ä»£å°ååºMapä¸çé®ï¼ç¨getæ¹æ³è·å¾é®å¯¹åºçå¼ï¼ä¾¿å®æäºMapçéåã代ç å¦ä¸æ示ï¼
//使ç¨è¿ä»£å¨éåMapçé®ï¼æ ¹æ®é®åå¼
Iterator it = map.keySet().iterator();
while (it.hasNext()){
key = it.next();
value = map.get(key);
System.out.println("key: " + key + "; value: " + value );
}
ï¼2ï¼ä½¿ç¨MapçentrySetæ¹æ³è·å¾Mapä¸è®°å½çéåï¼æ¯æ¡å¯¹è±¡é½æ¯ä¸ä¸ªMap.Entry对象ï¼ä½¿ç¨å ¶getKeyæ¹æ³è·å¾è®°å½çé®ï¼ä½¿ç¨å ¶getValueæ¹æ³è·å¾è®°å½çå¼ã代ç å¦ä¸æ示ï¼
//æè 使ç¨è¿ä»£å¨éåMapçè®°å½Map.Entry
Map.Entry entry = null;
it = map.entrySet().iterator();
while (it.hasNext()){
//ä¸ä¸ªMap.Entry代表ä¸æ¡è®°å½
entry = (Map.Entry)it.next();
//éè¿entryå¯ä»¥è·å¾è®°å½çé®åå¼
//System.out.println("key: " + entry.getKey() + "; value: " + entry.getValue());
java面试精讲,对比Hashtable、HashMap、竞拍系统 源码TreeMap有什么不同?
面试中经常被问及的Java核心数据结构问题之一是对比Hashtable、HashMap和TreeMap的区别。这三种Map类型在Java集合框架中扮演着重要角色,尤其是HashMap,因其广泛使用而备受关注。
Hashtable是早期Java提供的哈希表实现,同步但不支持null键值对,android源码面试其同步特性导致性能较低,现今已较少推荐。HashMap相比之下,更受欢迎,是非同步的,支持null键值对,极限旋转源码其put和get操作通常能达到常数时间,是键值对存储和访问的首选,比如用户ID与信息的关联。
TreeMap则是基于红黑树的有序Map,get、put、libgdx源码下载remove操作的时间复杂度为O(log(n)),顺序由Comparator或键的自然顺序决定。这对于需要保持特定顺序的场景,如资源池的自动释放策略,是有用的。
面试时,源码封装算了可能会询问HashMap的设计实现细节,如并发问题、容量和负载因子的影响,以及HashMap和LinkedHashMap的区别,比如插入顺序和访问顺序。HashMap的底层是数组和链表结构,容量和负载因子决定了性能,当链表过长时,会进行树化以提高查询效率。
理解Map的整体结构,以及hashCode和equals的使用规则至关重要,比如LinkedHashMap的遍历顺序和TreeMap的键值顺序依赖于Comparator。同时,了解HashMap源码,包括resize、树化和容量调整等,是面试中不可忽视的部分。
总结来说,面试中会考察你对这些Map类型特性的掌握,以及在实际编程中的应用和理解,确保你能够正确处理并发场景,并根据需求选择合适的Map实现。