• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
lamber
博客园    首页    新随笔       管理    订阅  订阅

Java中HashMap Hashtable HashSet LinkedHashMap 和TreeMap理解

           HashMap Hashtable LinkedHashMap 和TreeMap 加HashSet

java.lang.Object

↑java.util.AbstractCollection<E>

↑java.util.AbstractSet<E>

↑java.util.HashSet<E>

 

1.    HashSet允许null值。

2.      HashSet中值不能重复。

3.       Hashset在判断是否存在同一个对象的时候首先会判断对象的hashcode是否相等,然后在判断对象的equals()是否相等。当你向HashSet中存入重复元素时,他会按照正常的流程执行存入操作
底层的数据结构采用的是数组+链表的存储结构(明白这一点对于理解HashSet的原理非常重要),
也就是说数组中的每一个元素都是一个链表(对应java中的List的某一具体实现),
这样当有元素要存入HashSet中时,便会首先通过hashCode()方法得到该对象的一个哈希码,并利用该哈希码通过一些转换算法映射成数组的下标索引(当查找时也是如此,因此会非常的快),接下来便会判断该下标处是否为null若为null则会创建一个列表,此时将待插入的对象直接插入,若列表已经存在则利用equals()方法将带插入对象与列表中的元素逐个比较,相等则忽略,不存在相等元素则直接插入。
因此不同对象的hashCode()是可以相同的(最好是均匀的散列开,这样才能充分的提高访问及插入的速度),
根据equals()判定相等的对象所产生的hashCode()必须相等(根据其原理不难理解,否则的话便会有重复元素出现了)
保证一点  hashCode()与equals()必须能够唯一的确定一个对象。

 

此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。此类为基本操作提供了稳定性能,这些基本操作包括 add、remove、contains 和 size,假定哈希函数将这些元素正确地分布在桶中。对此 set 进行迭代所需的时间与 HashSet 实例的大小(元素的数量)和底层 HashMap 实例(桶的数量)的“容量”的和成比例。因此,如果迭代性能很重要,则不要将初始容量设置得太高(或将加载因子设置得太低。

注意:此实现不是同步的。如果多个线程同时访问一个哈希 set,而其中至少一个线程修改了该 set,那么它必须 保持外部同步。这通常是通过对自然封装该 set 的对象执行同步操作来完成的。如果不存在这样的对象,则应该使用 Collections.synchronizedSet 方法来“包装” set。最好在创建时完成这一操作,以防止对该 set 进行意外的不同步访问.

 

java为数据结构中的映射定义了一个接口java.util.Map;它有四个实现类,分别是HashMap Hashtable LinkedHashMap 和TreeMap

Map主要用于存储健值对,根据键得到值,因此不允许键重复,但允许值重复。

java.lang.Object

↑java.util.AbstractMap<K,V>

↑java.util.HashMap<K,V>

Hashmap 是一个 最常用的Map,它根据键的HashCode 值存储数据,根据键可以直接获取它的值,具有很快的访问速度。HashMap最多只允许一条记录的键为Null;允许多条记录的值为Null;HashMap不支持线程的同步,即任一时刻可以有多个线程同时写HashMap;可能会导致数据的不一致。如果需要同步,可以用Collections的synchronizedMap方法使HashMap具有同步的能力.

java.lang.Object

↑java.util.Dictionary<K,V>

↑java.util.Hashtable<K,V>

Hashtable 与 HashMap类似,不同的是:它不允许记录的键或者值为空;它支持线程的同步,即任一时刻只有一个线程能写Hashtable,因此也导致了Hashtale在写入时会比较慢。

java.lang.Object

↑java.util.AbstractMap<K,V>

↑java.util.HashMap<K,V>

↑java.util.LinkedHashMap<K,V>

LinkedHashMap保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.在遍历的时候会比HashMap慢。

java.lang.Object

↑java.util.AbstractMap<K,V>

↑java.util.TreeMap<K,V>

TreeMap能够把它保存的记录根据键排序,默认是按升序排序,也可以指定排序的比较器,当用Iterator 遍历TreeMap时,得到的记录是排过序的。

public class TestMap { 
/** 
* 初始化一个Map 
* @param map 
*/ 
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");  } 
} 
} 
/** 
* 输出一个Map 
* @param map 
*/ 
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()); 
} 
} 
} 
/** 
* 判断map是否包含某个键 
* @param map 
* @param key 
* @return 
*/ 
public static boolean containsKey(Map map, Object key){ 
if (map != null){ 
return map.containsKey(key); 
} 
return false; 
} 
/** 
* 判断map是否包含某个值 
* @param map 
* @param value 
* @return 
*/ 
public static boolean containsValue(Map map, Object value){ 
if (map != null){ 
return map.containsValue(value); 
} 
return false; 
} 
/** 
* 演示HashMap 
*/ 
public static void testHashMap(){ 
Map myMap = new HashMap(); 
init(myMap); 
//HashMap的键可以为null 
myMap.put(null,"ddd"); 
//HashMap的值可以为null 
myMap.put("aaa", null); 
output(myMap); 
} 
/** 
* 演示Hashtable 
*/ 
public static void testHashtable(){ 
Map myMap = new Hashtable(); 
init(myMap); 
//Hashtable的键不能为null 
//myMap.put(null,"ddd"); 
//Hashtable的值不能为null 
//myMap.put("aaa", null); 
output(myMap); 
} 
/** 
* 演示LinkedHashMap 
*/ 
public static void testLinkedHashMap(){ 
Map myMap = new LinkedHashMap(); 
init(myMap); 
//LinkedHashMap的键可以为null 
myMap.put(null,"ddd"); 
//LinkedHashMap的值可以为null 
myMap.put("aaa", null); 
output(myMap); 
} 
/** 
* 演示TreeMap 
*/ 
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());

想要获得成功,首先要自己相信自己,再者要赢得周围朋友的信任!
posted @ 2012-04-17 23:08  android5k  阅读(1389)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2026
浙公网安备 33010602011771号 浙ICP备2021040463号-3