首页 > 代码库 > java集合之间的关系及实现细节——Set与Map
java集合之间的关系及实现细节——Set与Map
首先,先谈一下Set和Map的一些特性及体系结构:
1.1 Set和Map
Set代表一种无序的、元素不可重复的集合。Map则代表是一种key-value对组成的集合,Map集合类似于传统的关联数组。表面上看它们之间的关系的相似性很少,实则Map和Set之间有着莫大的关联,可以这样说Map集合实则是Set集合的扩展。
至于为什么是Set是一种无序的、元素不可重复的集合;Map集合类似传统的关系数组。理解这个非常重要,这个我在后面会进行补充说明。
1.2 Set和Map之间的关系
先看看Set集合的继承体系,再来看Map集合的类继承体系:
从上图灰色阴影部分可以看出Map和Set的集合实现类除了后面Set和Map部分不一样,前面的类或接口的名称以及其继承结构完全一样。是偶然吗?答案绝对不是。而且你若是用过Map的话,你会发现Map不允许再现相同的key,且Map在遍历的时候,key是无序的,正是对应Map中keySet()方法。这与上述Set集合的特征又是惊人的相似。下面我会用一段小程序来说明Set为何与Map这么相似了。
先说一下我的思路:
(1)在我的印象中:map的key与value存在的关系如下图:
(2)既然Map中的key与value存在一一对应关系,那么,现在我们换一种思路来思考,把key-value如下图:
由此可见,如上述图3.4表明的一样,如果将key-value绑定在一起,那么Map说白了就是个(key-value)的Set集合
由上述思路,下面是程序实现由Set实现Map:
(1)包含key-value的entry实现代码:
1 package com.ngu4k.test.collection; 2 3 import java.io.Serializable; 4 import java.util.Map.Entry; 5 6 public class SimpleEntry<K,V> implements Entry<K,V>,Serializable{ 7 private static final long serialVersionUID = -4352059623055803486L; 8 private final K key; 9 private V value;10 //定义两个如下构造器11 public SimpleEntry(K key,V value)12 {13 this.key = key;14 this.value =http://www.mamicode.com/ value;15 }16 17 public SimpleEntry(Entry<? extends K,? extends V> entry)18 {19 this.key = entry.getKey();20 this.value =http://www.mamicode.com/ entry.getValue();21 }22 //获取key23 public K getKey() 24 {25 return key;26 }27 //获取value28 public V getValue() 29 {30 return value;31 }32 //改变该key-value对的value值33 public V setValue(V value) 34 {35 V oldValue = http://www.mamicode.com/this.value;36 this.value =http://www.mamicode.com/ value;37 return oldValue;38 }39 //根据key比较两个对象是否相等40 public boolean equals(Object o)41 {42 if(o == this){43 return true;44 }45 if(o.getClass() == SimpleEntry.class){46 SimpleEntry se = (SimpleEntry)o;47 return se.getKey().equals(getKey());48 }49 return false;50 }51 //根据key获得hashCode的值52 public int hashCode(){53 return key == null ? 0 : key.hashCode();54 }55 56 public String toString(){57 return key + "=" + value;58 }59 }
(2)由Set到Map的简单实现代码:
1 package com.ngu4k.test.collection.map; 2 3 import java.util.HashSet; 4 import java.util.Iterator; 5 import java.util.Map; 6 7 import com.ngu4k.test.collection.SimpleEntry; 8 9 /** 10 * Set到Map的简单实现 11 * @author ikouer 12 * @param <K> 13 * @param <V> 14 */ 15 public class Set2Map<K,V> extends HashSet<SimpleEntry<K,V>>{ 16 17 private static final long serialVersionUID = 1596710712757978024L; 18 19 //清空Set2Map中key-value对 20 public void clear() 21 { 22 super.clear(); 23 } 24 //查看是否包含指定的key 25 public boolean containsKey(K key) 26 { 27 return super.contains(new SimpleEntry<K, V>(key,null)); 28 } 29 //查看是否包含指定的value 30 public boolean containsValue(V value) 31 { 32 for(SimpleEntry<K,V> se : this) 33 { 34 if(se.getValue().equals(value)) 35 { 36 return true; 37 } 38 } 39 return false; 40 } 41 //根据指定的key获取对应的value 42 public V get(K key) 43 { 44 for(SimpleEntry<K,V> se : this) 45 { 46 if(se.getKey().equals(key)){ 47 return se.getValue(); 48 } 49 } 50 return null; 51 } 52 //把指定的key-value添加到集合中 53 public V put(K key,V value) 54 { 55 this.add(new SimpleEntry<K,V>(key,value)); 56 return value; 57 } 58 //把一个Map集合添加到Set2Map集合中 59 public void putAll(Map<? extends K,? extends V> om) 60 { 61 for(K key : om.keySet()) 62 { 63 this.add(new SimpleEntry<K,V>(key,om.get(key))); 64 } 65 } 66 //根据指定的key移除对应的key-value 67 public V remove(K key) 68 { 69 for(Iterator<SimpleEntry<K,V>> it = this.iterator(); it.hasNext();){ 70 SimpleEntry<K,V> se = it.next(); 71 if(se.getKey().equals(key)) 72 { 73 V rv = se.getValue(); 74 it.remove(); 75 return rv; 76 } 77 } 78 return null; 79 } 80 //获取集合大小 81 public int size(){ 82 return super.size(); 83 } 84 85 public static void main(String[] args) { 86 Set2Map<String,Integer> smap = new Set2Map<String,Integer>(); 87 //将key-value放入集合 88 smap.put("语文", 88); 89 smap.put("数学", 99); 90 smap.put("英语", 102); 91 System.out.println(smap); 92 System.out.println(smap.size()); 93 //执行移除对称key的entry 94 smap.remove("数学"); 95 System.out.println("删除key为\"数学\"的Entry之后:"+smap); 96 //获取key为语文的value值 97 System.out.println("key为\"语文\"的value值:"+smap.get("语文")); 98 //判断是否包含key 99 System.out.println("是否包含key为\"英语\"的entry:"+smap.containsKey("英语"));100 //判断是否包含value101 System.out.println("是否包含value为102:"+smap.containsValue(102));102 //执行clear方法103 smap.clear();104 System.out.println("执行完clear()方法之后的集合:"+smap);105 106 }107 }