Java学习笔记(39)-----------Map集合

可以这样说哦!

Map 与 Set 有着惊人的相似 ,其Set 为无序列,Map为有序列!

虽然Map集合中存放的是key-value对,Set集合中放的是单个对象,但如果我们把key-value对中的value当成key的附庸:key在哪里,value就在那里。这样我们就可以像对待Set一样对待Map了,事实上,map提供一个Entry内部类来封装key-value对,二计算Entry存储是则只考虑Entry封装的key.

 

 

 

Map简介

     将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。

 

 

 

Map 接口提供三种collection 视图,允许以键集、值集或键-值映射关系集的形式查看某个映射的内容。

映射顺序定义为迭代器在映射的 collection 视图上返回其元素的顺序。某些映射实现可明确保证其顺序,如 TreeMap 类;另一些映射实现则不保证顺序,如HashMap 类。

 

 

 

  常用操作说明

 

 

  void clear()

  从此映射中移除所有映射关系(可选操作)。

  boolean containsKey(Object key)

  如果此映射包含指定键的映射关系,则返回 true。

  boolean containsValue(Object value)

  如果此映射将一个或多个键映射到指定值,则返回 true。

  Set<Map.Entry<K,V>> entrySet()

  返回此映射中包含的映射关系的 Set 视图。

  boolean equals(Object o)

  比较指定的对象与此映射是否相等。

  V get(Object key)

  返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。

  int hashCode()

  返回此映射的哈希码值。

  boolean isEmpty()

  如果此映射未包含键-值映射关系,则返回 true。

  Set<K> keySet()

  返回此映射中包含的键的 Set 视图。

  V put(K key, V value)

  将指定的值与此映射中的指定键关联(可选操作)。

  void putAll(Map<? extends K,? extends V> m)

  从指定映射中将所有映射关系复制到此映射中(可选操作)。

  V remove(Object key)

  如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。

  int size()

  返回此映射中的键-值映射关系数。

  Collection<V> values()

  返回此映射中包含的值的 Collection 视图。

 

 

 

Map的一般用法

 

 

1.声明一个Map :

   Map map = new HashMap();

2 .向map中放值 ,注意: map是key-value的形式存放的,如:

       map.put("sa","dd");

3 .从map中取值 :

    String str = map.get("sa").toString,

    结果是: str = "dd'

4 .遍历一个map,从中取得key和value :

    Map m= new HashMap();

    for(Object obj : map.keySet()){

          Object value = map.get(obj );

    }

 

Java的HashMap和HashTable

1. HashMap

1)  hashmap的数据结构 

     Hashmap是一个数组和链表的结合体(在数据结构称“链表散列“),如下图示:

        当我们往hashmap中put元素的时候,先根据key的hash值得到这个元素在数组中的位置(即下标),然后就可以把这个元素放到对应的位置中了。如果这个元素所在的位子上已经存放有其他元素了,那么在同一个位子上的元素将以链表的形式存放,新加入的放在链头,最先加入的放在链尾。

 

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <span style="font-size:18px;">Map map = new HashMap();  
  2. map.put("Rajib Sarma","100");  
  3. map.put("Rajib Sarma","200");//The value "100" is replaced by "200".  
  4. map.put("Sazid Ahmed","200");  
  5.   
  6. Iterator iter = map.entrySet().iterator();  
  7. while (iter.hasNext()) {  
  8.     Map.Entry entry = (Map.Entry) iter.next();  
  9.     Object key = entry.getKey();  
  10.     Object val = entry.getValue();  
  11. }  
  12. </span>  


 

2. HashTable和HashMap区别

第一,继承不同

 

public class Hashtable extends Dictionary implements Map
public class HashMap  extends AbstractMap implements Map

 

第二

Hashtable 中的方法是同步的,而HashMap中的方法在缺省情况下是非同步的。在多线程并发的环境下,可以直接使用Hashtable,但是要使用HashMap的话就要自己增加同步处理了。

第三

Hashtable中,key和value都不允许出现null值。

在HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,即可以表示 HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键, 而应该用containsKey()方法来判断。

第四,两个遍历方式的内部实现上不同。

Hashtable、HashMap都使用了 Iterator。而由于历史原因,Hashtable还使用了Enumeration的方式 。

第五

哈希值的使用不同,HashTable直接使用对象的hashCode。而HashMap重新计算hash值。

第六

Hashtable和HashMap它们两个内部实现方式的数组的初始大小和扩容的方式。HashTable中hash数组默认大小是11,增加的方式是 old*2+1。HashMap中hash数组的默认大小是16,而且一定是2的指数。

 

 

LinkedHashMap实现类

1. LinkedHashMap概述:

  

1. LinkedHashMap概述:

LinkedHashMap是HashMap的一个子类,它保留插入的顺序,如果需要输出的顺序和输入时的相同,那么就选用LinkedHashMap。

   LinkedHashMap是Map接口的哈希表和链接列表实现,具有可预知的迭代顺序。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变
   LinkedHashMap实现与HashMap的不同之处在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序可以是插入顺序或者是访问顺序。
   注意,此实现不是同步的。如果多个线程同时访问链接的哈希映射,而其中至少一个线程从结构上修改了该映射,则它必须保持外部同步。

 

根据链表中元素的顺序可以分为:按插入顺序的链表,和按访问顺序(调用get方法)的链表。  

默认是按插入顺序排序,如果指定按访问顺序排序,那么调用get方法后,会将这次访问的元素移至链表尾部,不断访问可以形成按访问顺序排序的链表。  可以重写removeEldestEntry方法返回true值指定插入元素时移除最老的元素。

 

 


 

 

public class LinkedHashMap<K, V> extends HashMap<K, V> implements Map<K, V> 

 

实例:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.haixu.Map;  
  2.   
  3. import java.util.LinkedHashMap;  
  4.   
  5. public class LinkedHashtable {  
  6.       
  7.     public static void main(String[] args) {  
  8.         LinkedHashMap lhp = new LinkedHashMap();  
  9.           
  10.         lhp.put("Spring" ,1 );  
  11.         lhp.put("Struts" ,2 );  
  12.         lhp.put("Hibernate" , 3);  
  13.         for(Object key : lhp.keySet()){  
  14.             System.out.println(key + "--------------" + lhp.get(key));  
  15.         }  
  16.     }  
  17.   
  18. }  


此处引入http://blog.csdn.net/hudashi/article/details/6944059的博

 

SortMap与TreeMap

 

接口SortedMap<K,V>
public interface SortedMap<K,V>
extends Map<K,V>
 保证按照键的升序排列的映射,可以按照键的自然顺序(参见 Comparable 接口)进行排序, 或者通过创建有序映射时提供的比较器进行排序。对有序映射的集合视图
 (由 entrySet、keySet 和 values 方法返回)进行迭代时,此顺序就会反映出来。
 要采用此排序,还需要提供一些其他操作(此接口是相似于 SortedSet 接口的映射)。
 插入有序映射的所有键都必须实现 Comparable 接口(或者被指定的比较器所接受)。
 另外,所有这些键都必须是可互相比较的:k1.compareTo(k2)(或 comparator.compare(k1, k2))
 对有序映射中的任意两个元素 k1 和 k2 都不得抛出 ClassCastException。

 试图违反这些限制将导致违反方法或者构造方法的调用,从而抛出 ClassCastException。
 注意,如果有序映射正确实现了 Map 接口,则有序映射所保持的顺序(无论是否明确提供了比较器)都必须保持相等一致性。
 (相等一致性 的精确定义请参阅 Comparable 接口或 Comparator 接口)。
 这也是因为 Map 接口是按照 equals 操作定义的,但有序映射使用它的 compareTo(或 compare)方法对所有键进行比较,
 因此从有序映射的观点来看,此方法认为两个对象拥有相等的映射键则说明它们是相等的
 即使顺序没有保持相等一致性,树映射的行为仍然是 定义良好的,只不过没有遵守 Map 接口的常规协定。
 所有通用有序映射实现类都应该提供 4 个“标准”构造方法:
 1) void(不带参数)构造方法,创建空的有序映射,按照键的自然顺序 排序。
 2) 带有一个 Comparator 类型参数的构造方法,创建一个空的有序映射,根据指定的比较器排序。
 3) 带有一个 Map 类型参数的构造方法,创建一个键-值映射关系与参数相同的有序映射,按照键的自然顺序排序。
 4) 带有一个有序映射类型参数的构造方法,创建一个新的有序映射,键-值映射关系及排序方法与输入的有序映射相同。如
TreeMap(SortedMap<K,? extends V> m) 
 除了 JDK 实现(TreeMap 类)遵循此建议外,无法保证强制实施此建议(因为接口不能包含构造方法)。
SortedMap声明的接口

Public Methods
abstract Comparator<? super K>comparator()
Returns the comparator used to compare keys in this sorted map.
返回与此有序映射关联的比较器,如果使用键的自然顺序,则返回 null。
abstract KfirstKey()
Returns the first key in this sorted map.
返回有序映射中当前第一个(最小的)键。
abstract SortedMap<K, V>headMap(K endKey)
Returns a sorted map over a range of this sorted map with all keys that are less than the specified  endKey.
返回此有序映射的部分元素,其元素的键值应该小于 toKey。
abstract KlastKey()
Returns the last key in this sorted map.
返回有序映射中当前最后一个(最大的)键。
abstract SortedMap<K, V>subMap(K startKey, K endKey)
Returns a sorted map over a range of this sorted map with all keys greater than or equal to the specified  startKey and less than the specified  endKey.
返回此有序映射的部分视图,其键值从 fromKey(包括)到 toKey(不包括)。
abstract SortedMap<K, V>tailMap(K startKey)
Returns a sorted map over a range of this sorted map with all keys that are greater than or equal to the specified  startKey.
返回有序映射的部分视图,其键大于或等于 fromKey。
TreeMap(1.2)
 TreeMap是SortedMap接口的基于红黑树的实现。此类保证了映射按照升序顺序排列关键字, 根据使用的构造方法不同,可能会按照键的类的自然顺序进行排序(参见 Comparable), 或者按照创建时所提供的比较器进行排序。
 此实现为 containsKey、get、put 和 remove 操作提供了保证的 log(n) 时间开销。
 这些算法是 Cormen、Leiserson 和 Rivest 的《Introduction to Algorithms》中的算法的改编。
 注意,如果有序映射要正确实现 Map 接口,则有序映射所保持的顺序(无论是否明确提供比较器)都必须保持与等号一致。
(请参见与等号一致 的精确定义的 Comparable 或 Comparator。)这也是因为 Map 接口是按照等号操作定义的,
 但映射使用它的 compareTo(或 compare)方法对所有键进行比较,因此从有序映射的观点来看,
 此方法认为相等的两个键就是相等的。即使顺序与等号不一致,有序映射的行为仍然是 定义良好的;
 只不过没有遵守 Map 接口的常规约定。
 注意,此实现不是同步的。如果多个线程同时访问一个映射,并且其中至少一个线程从结构上修改了该映射,
 则其必须 保持外部同步。(结构上修改是指添加或删除一个或多个映射关系的操作;
 仅改变与现有键关联的值不是结构上的修改。)这一般通过对自然封装该映射的某个对象进行同步操作来完成。
 如果不存在这样的对象,则应该使用 Collections.synchronizedMap 方法来“包装”该映射。
 最好在创建时完成这一操作,以防止对映射进行意外的不同步访问,如下所示:
     Map m = Collections.synchronizedMap(new TreeMap(...));
 由所有此类的“collection 视图方法”所返回的迭代器都是快速失败的:在迭代器创建之后,
 如果从结构上对映射进行修改,除非通过迭代器自身的 remove 或 add 方法,其他任何时间任何方式的修改,
 迭代器都将抛出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就完全失败,
 而不是冒着在将来不确定的时间任意发生不确定行为的风险。
 注意,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证。
 快速失败迭代器会尽最大努力抛出 ConcurrentModificationException。
 因此,为提高这类迭代器的正确性而编写一个依赖于此异常的程序是错误的做法:迭代器的快速失败行为应该仅用于检测 bug。
注意1:此实现不是同步的。不是线程安全的。
注意2:TreeMap是用键来进行升序顺序来排序的。通过Comparable 或 Comparator来排序。
注意3:由所有此类的“collection 视图方法”所返回的迭代器都是快速失败的。
注意4:和HashMap一样,如果插入重复的元素,后面的元素会覆盖前面的。
注意5: 键不可以为null,但是值可以为null

实例:

 

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. package com.haixu.Map;  
  2.   
  3. import java.util.TreeMap;  
  4.   
  5. class R implements Comparable{  
  6.     int count;  
  7.     public R (int count){  
  8.         this.count = count;  
  9.     }  
  10.     public String toString(){  
  11.         return "R[count:" + count + "]";  
  12.     }  
  13.     public boolean equals (Object obj){  
  14.         if(this == obj)  
  15.             return true;  
  16.         if(obj != null && obj.getClass() == R.class){  
  17.             R r = (R) obj;  
  18.             return r.count == this.count;  
  19.         }  
  20.         return false;  
  21.     }  
  22.     public int compareTo(Object obj){  
  23.         R r = (R) obj;  
  24.         return count > r.count ? 1 : count < r.count -1 ? -1:0;  
  25.     }  
  26. }  
  27.   
  28.   
  29. public class TreeMapTest {  
  30.       
  31.     public static void main(String[] args) {  
  32.         TreeMap tm = new TreeMap();  
  33.         tm.put(new R(2), "struts");  
  34.         tm.put(new R(1), "Spring");  
  35.         tm.put(new R(3),"Hibernate");  
  36.           
  37.         System.out.println(tm);  
  38.           
  39.        System.out.println(tm.firstEntry());  
  40.          
  41.        System.out.println(tm.lastKey());  
  42.          
  43.        System.out.println(tm.higherKey(new R(2)));  
  44.          
  45.        System.out.println(tm.subMap(new R (2), new R(3)));  
  46.     }  
  47.       
  48.   
  49. }  


 

运行结果:

 

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. {R[count:2]=Spring, R[count:3]=Hibernate}  
  2. R[count:2]=Spring  
  3. R[count:3]  
  4. null  
  5. {}  

良心的公众号,更多精品文章,不要忘记关注哈

《Android和Java技术栈》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值