Java的TreeMap和HashMap的介绍和使用

1. TreeMap的介绍和使用

第1部分 TreeMap介绍

TreeMap 简介

TreeMap 是一个有序的key-value集合,它是通过红黑树实现的。
TreeMap 继承于AbstractMap,所以它是一个Map,即一个key-value集合。
TreeMap 实现了NavigableMap接口,意味着它支持一系列的导航方法。比如返回有序的key集合。
TreeMap 实现了Cloneable接口,意味着它能被克隆
TreeMap 实现了java.io.Serializable接口,意味着它支持序列化

TreeMap基于红黑树(Red-Black tree)实现。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法。
TreeMap的基本操作 containsKey、get、put 和 remove 的时间复杂度是 log(n) 。
另外,TreeMap是非同步的。 它的iterator 方法返回的迭代器是fail-fastl的。

TreeMap的构造函数

// 默认构造函数。使用该构造函数,TreeMap中的元素按照自然排序进行排列。  
TreeMap()  
  
// 创建的TreeMap包含Map  
TreeMap(Map<? extends K, ? extends V> copyFrom)  
  
// 指定Tree的比较器  
TreeMap(Comparator<? super K> comparator)  
  
// 创建的TreeSet包含copyFrom  
TreeMap(SortedMap<K, ? extends V> copyFrom) 


TreeMap的API

Map.Entry<K,V>    ceilingEntry(K key)   
         返回一个键-值映射关系,它与大于等于给定键的最小键关联;如果不存在这样的键,则返回 null。  
K   ceilingKey(K key)   
         返回大于等于给定键的最小键;如果不存在这样的键,则返回 null。  
void    clear()   
         从此映射中移除所有映射关系。  
Object  clone()   
         返回此 TreeMap 实例的浅表副本。  
Comparator<? super K> comparator()   
         返回对此映射中的键进行排序的比较器;如果此映射使用键的自然顺序,则返回 null。  
boolean containsKey(Object key)   
         如果此映射包含指定键的映射关系,则返回 true。  
boolean containsValue(Object value)   
         如果此映射为指定值映射一个或多个键,则返回 true。  
NavigableSet<K>   descendingKeySet()   
         返回此映射中所包含键的逆序 NavigableSet 视图。  
NavigableMap<K,V> descendingMap()   
         返回此映射中所包含映射关系的逆序视图。  
Set<Map.Entry<K,V>> entrySet()   
         返回此映射中包含的映射关系的 Set 视图。  
Map.Entry<K,V>    firstEntry()   
         返回一个与此映射中的最小键关联的键-值映射关系;如果映射为空,则返回 null。  
K   firstKey()   
         返回此映射中当前第一个(最低)键。  
Map.Entry<K,V>    floorEntry(K key)   
         返回一个键-值映射关系,它与小于等于给定键的最大键关联;如果不存在这样的键,则返回 null。  
K   floorKey(K key)   
         返回小于等于给定键的最大键;如果不存在这样的键,则返回 null。  
V   get(Object key)   
         返回指定键所映射的值,如果对于该键而言,此映射不包含任何映射关系,则返回 null。  
SortedMap<K,V>    headMap(K toKey)   
         返回此映射的部分视图,其键值严格小于 toKey。  
NavigableMap<K,V> headMap(K toKey, boolean inclusive)   
         返回此映射的部分视图,其键小于(或等于,如果 inclusive 为 true)toKey。  
Map.Entry<K,V>    higherEntry(K key)   
         返回一个键-值映射关系,它与严格大于给定键的最小键关联;如果不存在这样的键,则返回 null。  
K   higherKey(K key)   
         返回严格大于给定键的最小键;如果不存在这样的键,则返回 null。  
Set<K>    keySet()   
         返回此映射包含的键的 Set 视图。  
Map.Entry<K,V>    lastEntry()   
         返回与此映射中的最大键关联的键-值映射关系;如果映射为空,则返回 null。  
K   lastKey()   
         返回映射中当前最后一个(最高)键。  
Map.Entry<K,V>    lowerEntry(K key)   
         返回一个键-值映射关系,它与严格小于给定键的最大键关联;如果不存在这样的键,则返回 null。  
K   lowerKey(K key)   
         返回严格小于给定键的最大键;如果不存在这样的键,则返回 null。  
NavigableSet<K>   navigableKeySet()   
         返回此映射中所包含键的 NavigableSet 视图。  
Map.Entry<K,V>    pollFirstEntry()   
         移除并返回与此映射中的最小键关联的键-值映射关系;如果映射为空,则返回 null。  
Map.Entry<K,V>    pollLastEntry()   
         移除并返回与此映射中的最大键关联的键-值映射关系;如果映射为空,则返回 null。  
V   put(K key, V value)   
         将指定值与此映射中的指定键进行关联。  
void    putAll(Map<? extends K,? extends V> map)   
         将指定映射中的所有映射关系复制到此映射中。  
V   remove(Object key)   
         如果此 TreeMap 中存在该键的映射关系,则将其删除。  
int size()   
         返回此映射中的键-值映射关系数。  
NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive)   
         返回此映射的部分视图,其键的范围从 fromKey 到 toKey。  
SortedMap<K,V>    subMap(K fromKey, K toKey)   
         返回此映射的部分视图,其键值的范围从 fromKey(包括)到 toKey(不包括)。  
SortedMap<K,V>    tailMap(K fromKey)   
         返回此映射的部分视图,其键大于等于 fromKey。  
NavigableMap<K,V> tailMap(K fromKey, boolean inclusive)   
         返回此映射的部分视图,其键大于(或等于,如果 inclusive 为 true)fromKey。  
Collection<V> values()   
         返回此映射包含的值的 Collection 视图。  


第2部分 TreeMap数据结构

TreeMap的继承关系

java.lang.Object
	java.util.AbstractMap<K, V>
		java.util.TreeMap<K, V>
public class TreeMap<K,V>
    extends AbstractMap<K,V>
    implements NavigableMap<K,V>, Cloneable, java.io.Serializable {}


TreeMap与Map关系如下图:

从图中可以看出:
(01) TreeMap实现继承于AbstractMap,并且实现了NavigableMap接口。
(02) TreeMap的本质是R-B Tree(红黑树),它包含几个重要的成员变量: rootsizecomparator
  root 是红黑数的根节点。它是Entry类型,Entry是红黑数的节点,它包含了红黑数的6个基本组成成分:key(键)、value(值)、left(左孩子)、right(右孩子)、parent(父节点)、color(颜色)。Entry节点根据key进行排序,Entry节点包含的内容为value。 
  红黑数排序时,根据Entry中的key进行排序;Entry中的key比较大小是根据比较器comparator来进行判断的。
  size是红黑数中节点的个数。

关于红黑数的具体算法,请参考"红黑树(一) 原理和算法详细介绍"。


第3部分 TreeMap遍历方式

3.1 遍历TreeMap的键值对

第一步:根据entrySet()获取TreeMap的“键值对”的Set集合。
第二步:通过Iterator迭代器遍历“第一步”得到的集合。

// 假设map是TreeMap对象  
// map中的key是String类型,value是Integer类型  
Integer integ = null;  
Iterator iter = map.entrySet().iterator();  
while(iter.hasNext()) {  
    Map.Entry entry = (Map.Entry)iter.next();  
    // 获取key  
    key = (String)entry.getKey();  
        // 获取value  
    integ = (Integer)entry.getValue();  
}


3.2 遍历TreeMap的键

第一步:根据keySet()获取TreeMap的“键”的Set集合。
第二步:通过Iterator迭代器遍历“第一步”得到的集合。

// 假设map是TreeMap对象  
// map中的key是String类型,value是Integer类型  
String key = null;  
Integer integ = null;  
Iterator iter = map.keySet().iterator();  
while (iter.hasNext()) {  
        // 获取key  
    key = (String)iter.next();  
        // 根据key,获取value  
    integ = (Integer)map.get(key);  
}  


3.3 遍历TreeMap的值

第一步:根据value()获取TreeMap的“值”的集合。
第二步:通过Iterator迭代器遍历“第一步”得到的集合。

// 假设map是TreeMap对象  
// map中的key是String类型,value是Integer类型  
Integer value = null;  
Collection c = map.values();  
Iterator iter= c.iterator();  
while (iter.hasNext()) {  
    value = (Integer)iter.next();  
}


以上转自:http://www.cnblogs.com/skywang12345/admin/EditPosts.aspx?postid=3310928


2. HashMap的介绍和使用

HashMap简介 
HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。 
HashMap 继承于AbstractMap,实现了Map、Cloneable、java.io.Serializable接口。 
HashMap 的实现不是同步的,这意味着它不是线程安全的。它的key、value都可以为null。此外,HashMap中的映射不是有序的。 
HashMap 的实例有两个参数影响其性能:“初始容量” 和 “加载因子”。容量 是哈希表中桶的数量,初始容量 只是哈希表在创建时的容量。加载因子 是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行 rehash 操作(即重建内部数据结构),从而哈希表将具有大约两倍的桶数。 
通常,默认加载因子是 0.75, 这是在时间和空间成本上寻求一种折衷。加载因子过高虽然减少了空间开销,但同时也增加了查询成本(在大多数 HashMap 类的操作中,包括 get 和 put 操作,都反映了这一点)。在设置初始容量时应该考虑到映射中所需的条目数及其加载因子,以便最大限度地减少 rehash 操作次数。如果初始容量大于最大条目数除以加载因子,则不会发生 rehash 操作。

HashMap的继承关系 

HashMap与Map关系如下图: 
 
HashMap的构造函数 
HashMap共有4个构造函数,如下:

复制代码 代码如下:

// 默认构造函数。 
HashMap() 
// 指定“容量大小”的构造函数 
HashMap(int capacity) 
// 指定“容量大小”和“加载因子”的构造函数 
HashMap(int capacity, float loadFactor) 
// 包含“子Map”的构造函数 
HashMap(Map<? extends K, ? extends V> map)

HashMap的API

复制代码 代码如下:

void                 clear() 
Object               clone() 
boolean              containsKey(Object key) 
boolean              containsValue(Object value) 
Set<Entry<K, V>>     entrySet() 
V                    get(Object key) 
boolean              isEmpty() 
Set<K>               keySet() 
V                    put(K key, V value) 
void                 putAll(Map<? extends K, ? extends V> map) 
V                    remove(Object key) 
int                  size() 
Collection<V>        values()


以上转自:https://www.cnblogs.com/mkfywj/p/5543600.html#top


3. HashMap,LinkedHashMap,TreeMap的有序性

HashMap 是将 Key 做 Hash 算法,然后将 Hash 值映射到内存地址,直接取得 Key 所对应的数据。在 HashMap 中,底层数据结构使用的是数组,所谓的内存地址即数组的下标索引。HashMap 的高性能需要保证以下几点:


Hash 算法必须是高效的;
Hash 值到内存地址 (数组索引) 的算法是快速的;
根据内存地址 (数组索引) 可以直接取得对应的值。
HashMap 实际上是一个链表的数组。基于 HashMap 的链表方式实现机制,只要 HashCode() 和 Hash() 方法实现得足够好,能够尽可能地减少冲突的产生,那么对 HashMap 的操作几乎等价于对数组的随机访问操作,具有很好的性能。但是,如果 HashCode() 或者 Hash() 方法实现较差,在大量冲突产生的情况下,HashMap 事实上就退化为几个链表,对 HashMap 的操作等价于遍历链表,此时性能很差。


HashMap 的一个功能缺点是它的无序性,被存入到 HashMap 中的元素,在遍历 HashMap 时,其输出是无序的。如果希望元素保持输入的顺序,可以使用 LinkedHashMap 替代。


LinkedHashMap 继承自 HashMap,具有高效性,同时在 HashMap 的基础上,又在内部增加了一个链表,用以存放元素的顺序。


HashMap 通过 hash 算法可以最快速地进行 Put() 和 Get() 操作。TreeMap 则提供了一种完全不同的 Map 实现。从功能上讲,TreeMap 有着比 HashMap 更为强大的功能,它实现了 SortedMap 接口,这意味着它可以对元素进行排序。TreeMap 的性能略微低于 HashMap。如果在开发中需要对元素进行排序,那么使用 HashMap 便无法实现这种功能,使用 TreeMap 的迭代输出将会以元素顺序进行。LinkedHashMap 是基于元素进入集合的顺序或者被访问的先后顺序排序,TreeMap 则是基于元素的固有顺序 (由 Comparator 或者 Comparable 确定)。


LinkedHashMap 是根据元素增加或者访问的先后顺序进行排序,而 TreeMap 则根据元素的 Key 进行排序。


测试代码:

package mapKeySet;  
  
import java.util.HashMap;  
import java.util.LinkedHashMap;  
import java.util.Map;  
import java.util.TreeMap;  
  
/** 
 * 2015年4月9日下午3:33:44 
 * @version 1.0 
 */  
public class KeySetTest {  
    public static void main(String[] args) {  
        Map<String, String> map = new HashMap<String, String>();  
        map.put("a", "1");  
        map.put("b", "2");  
        map.put("c", "3");  
        map.put("d", "4");  
          
        System.out.print("HashMap:");  
        for(String key : map.keySet()) {  
            System.out.print(map.get(key) + " ");  
        }  
          
        Map<String, String> linkedMap = new LinkedHashMap<String, String>();  
        linkedMap.put("a", "1");  
        linkedMap.put("b", "2");  
        linkedMap.put("c", "3");  
        linkedMap.put("d", "4");  
          
        System.out.print("LinkedHashMap:");  
        for(String key : linkedMap.keySet()) {  
            System.out.print(linkedMap.get(key) + " ");  
        }  
          
        Map<String, String> treeMap = new TreeMap<String, String>();  
        treeMap.put("a", "1");  
        treeMap.put("b", "2");  
        treeMap.put("c", "3");  
        treeMap.put("d", "4");  
          
        System.out.print("TreeMap:");  
        for(String key : treeMap.keySet()) {  
            System.out.print(treeMap.get(key) + " ");  
        }  
    }  
}


输出结果:

HashMap:4 2 3 1 LinkedHashMap:1 2 3 4 TreeMap:1 2 3 4


以上转自:http://blog.csdn.net/zhuhao717/article/details/47444763


4. 二维HashMap

声明:

HashMap<String,HashMap<String,Integer>> map1;

添加元素:

HashMap<String,Integer> temp_hash=new HashMap<String,Integer>();  
temp_hash.put(string1, 1);  
map1.put(string2,temp_hash);

遍历:

申请一个迭代器:

Iterator<String> it1=map1.keySet().iterator();

访问:

while(it_verb.hasNext()){  
   String temp=it.next();  
   HashMap<String,Integer> temp_map=verb_map.get(temp);  
}  


以上参考:http://blog.csdn.net/sdcyzjq/article/details/6609137


// 代码实现
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

public class TestTreeMap {
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		TreeMap<Integer, String> map = new TreeMap<>();
		map.put(3, "aa");
		map.put(2, "bb");
		map.put(4, "cc");
		map.put(1, "dd");
		map.put(5, "dd");
		map.put(6, "ee");
		System.out.print("original: ");
		Iterator it = map.entrySet().iterator();
		while(it.hasNext()) {
			Map.Entry e = (Map.Entry)it.next();
			int key = (Integer)e.getKey();
			String val = (String)e.getValue();
			System.out.print(key + " " + val + (it.hasNext() ? ", " : "."));
		}
		System.out.println();
		System.out.println("-------------------------------");
		map.remove(6);
		System.out.print("after remove: ");
		it = map.entrySet().iterator();
		while(it.hasNext()) {
			Map.Entry e = (Map.Entry)it.next();
			int key = (Integer)e.getKey();
			String val = (String)e.getValue();
			System.out.print(key + " " + val + (it.hasNext() ? ", " : "."));
		}
		System.out.println();
		System.out.println("-------------------------------");
		System.out.println(3 + "'s val: " + map.get(3));
		System.out.println(3 + "'s higherKey: " + map.higherKey(3));
		Map.Entry tmp1 = map.higherEntry(3);
		System.out.println(3 + "'s higherEntry: " + (Integer)tmp1.getKey() + " " + (String)tmp1.getValue());

		System.out.println(3 + "'s lowerKey: " + map.lowerKey(3));
		Map.Entry tmp2 = map.lowerEntry(3);
		System.out.println(3 + "'s lowerEntry: " + (Integer)tmp2.getKey() + " " + (String)tmp2.getValue());
		
		System.out.println("firstKey: " + map.firstKey() + ", " + "lastKey: " + map.lastKey());
		System.out.println();
		
		TestUserDefined();
		
		TestTwoDimensional();
		
	}
	
	private static class Node implements Comparable<Node> {
		int a, b;
		public Node(int a, int b) {
			this.a = a;
			this.b = b;
		}
		@Override
		public int compareTo(Node o) {
			// TODO Auto-generated method stub
			if(this.a == o.a) {
				return (this.b < o.b) ? 1 : -1;
			}
			else {
				return (this.a > o.a) ? 1 : -1;
			}
		}
		public String toString() {
			return "{ " + this.a + "," + this.b + " }";
		}
	}
	
	private static class mycmp implements Comparator<Node> {

		@Override
		public int compare(Node o1, Node o2) {
			// TODO Auto-generated method stub
			if(o1.a == o2.a) {
				return o1.b - o2.b;
			}
			return o2.a - o1.a;
		}
		
	}
	
	private static void TestUserDefined() {
		// By Comparable接口
		TreeMap<Node, String> map1 = new TreeMap<>();
		map1.put(new Node(3, 2), "aa");
		map1.put(new Node(3, 4), "bb");
		map1.put(new Node(5, 8), "cc");
		map1.put(new Node(5, 7), "dd");
		map1.put(new Node(6, 9), "ee");
		Iterator it1 = map1.entrySet().iterator();
		while(it1.hasNext()) {
			Map.Entry e = (Map.Entry)it1.next();
			System.out.println((Node)e.getKey() + ": " + (String)e.getValue());
		}
		
		System.out.println();
		System.out.println("-------------------------------");
		System.out.println();
		
		// By Comparator接口
		TreeMap<Node, String> map2 = new TreeMap<>(new mycmp());
		map2.put(new Node(3, 2), "aa");
		map2.put(new Node(3, 4), "bb");
		map2.put(new Node(5, 8), "cc");
		map2.put(new Node(5, 7), "dd");
		map2.put(new Node(6, 9), "ee");
		Iterator it2 = map2.entrySet().iterator();
		while(it2.hasNext()) {
			Map.Entry e = (Map.Entry)it2.next();
			System.out.println((Node)e.getKey() + ": " + (String)e.getValue());
		}
		System.out.println();
	}
	
	private static void TestTwoDimensional() {
		TreeMap<Integer, TreeMap<Integer, String>> mmp = new TreeMap<>();
		TreeMap<Integer, String> tmpMap = new TreeMap<>();
		tmpMap.put(1, "a");
		tmpMap.put(3, "b");
		tmpMap.put(2, "c");
		mmp.put(1, tmpMap);
		mmp.put(3, tmpMap);
		mmp.put(2, tmpMap);
		Iterator it = mmp.entrySet().iterator();
		while(it.hasNext()) {
			Map.Entry e = (Map.Entry)it.next();
			int key = (Integer)e.getKey();
			tmpMap = (TreeMap<Integer, String>)e.getValue();
			System.out.print(key + "-> { ");
			
			Iterator tmpIt = tmpMap.entrySet().iterator();
			while(tmpIt.hasNext()) {
				Map.Entry tmpe = (Map.Entry)tmpIt.next();
				int tmpkey = (Integer)tmpe.getKey();
				String tmpval = (String)tmpe.getValue();
				System.out.print(tmpkey + " " + tmpval + (tmpIt.hasNext() ? ", " : ""));
			}
			System.out.println(" }");
		}
	}
	
}


继续加油~

  • 7
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值