JDK集合分析Set和Map的关系(自己实现Set到Map的扩展)
2016-04-24 14:24
585 查看
Set代表的是一种集合元素无序,集合元素不可重复的集合,Map则代表一种由多个Key-Value对组成的集合,Map集合类似于传统的关联数组。表面上看,Map和Set毫无关联,但其实Map和Set之间有莫大的关联,可以说,Map是Set的扩展。
仔细观察上述两个集合的继承体系,发现Map和Set接口,实现类的类名几乎完全相试,把Map后缀改为Set后缀即可:
SortedMap <–>SortedSet
TreeMap <–> TreeSet
LinkedHashMap <–>LinkedHashSet
HaseMap <–> HaseSet
这些类名相似绝不是偶然的现象,肯定有其必然的原因。
我们来思考Map集合的key键的特征:所有的key具有一个特性:所有key不能重复,Key直接没有顺序。可以就是说将所有的key组合在一起,那么它就是一个Set集合。而Map集合也提供了相应的方法来实现将所有的key组合成Set集合。
由此可见,Map集合的所有key将具有Set集合的特性,只要把Map的所有key集中起来看,它就是一个Set,即实现了从Map到Set的转换。其实也可以实现从Set到Map的扩展—-对于Map而言,相当于每个元素都是key-value对的Set集合。转换一种思维来理解Map集合,如果把Map集合中的value当成key的一个附属物,那么Map集合在保存key-value时只考虑Key即可
现在我们考虑如何把Set集合扩展为一个Map集合:
为了把Set集合扩展为一个Map集合,我们可以考虑定义一个SimpleEntry类,该类代表一个key-value对。当Set集合中的元素全是SimpleEntry对象的时候,那么它就可以当成Map来使用。
SimpleEntry:
继承HashSet实现一个Map
当一个Set集合中的全部集合元素都是SimpleEntry
现在我们发现,只要对传统的Set稍作修改,就可以将Set集合改造成Map。而且这个Map集合在功能上几乎可以媲美JDK提供了Map。
Set集合的继承体系
Map集合的继承体系
仔细观察上述两个集合的继承体系,发现Map和Set接口,实现类的类名几乎完全相试,把Map后缀改为Set后缀即可:
SortedMap <–>SortedSet
TreeMap <–> TreeSet
LinkedHashMap <–>LinkedHashSet
HaseMap <–> HaseSet
这些类名相似绝不是偶然的现象,肯定有其必然的原因。
我们来思考Map集合的key键的特征:所有的key具有一个特性:所有key不能重复,Key直接没有顺序。可以就是说将所有的key组合在一起,那么它就是一个Set集合。而Map集合也提供了相应的方法来实现将所有的key组合成Set集合。
Set<K> keySet();
由此可见,Map集合的所有key将具有Set集合的特性,只要把Map的所有key集中起来看,它就是一个Set,即实现了从Map到Set的转换。其实也可以实现从Set到Map的扩展—-对于Map而言,相当于每个元素都是key-value对的Set集合。转换一种思维来理解Map集合,如果把Map集合中的value当成key的一个附属物,那么Map集合在保存key-value时只考虑Key即可
现在我们考虑如何把Set集合扩展为一个Map集合:
为了把Set集合扩展为一个Map集合,我们可以考虑定义一个SimpleEntry类,该类代表一个key-value对。当Set集合中的元素全是SimpleEntry对象的时候,那么它就可以当成Map来使用。
SimpleEntry:
package ListAndSet; import java.io.Serializable; import java.util.Map; import java.util.Objects; /** * Created by wang on 16-4-23. */ public class SimpleEntry<K,V> implements Map.Entry<K,V>,Serializable { private K key; private V value; public SimpleEntry(K key,V value){ this.key = key; this.value = value; } public SimpleEntry(Map.Entry<? extends K,? extends V> entry){ this.key = entry.getKey(); this.value = entry.getValue(); } @Override public K getKey() { return key; } @Override public V getValue() { return value; } @Override public V setValue(V value) { V oldValue = this.value; this.value = value; return oldValue; } public boolean equals(Object object){ if(object == this){ return true; } if(object.getClass() == SimpleEntry.class){ SimpleEntry se = (SimpleEntry) object; return se.getKey().equals(getKey()); } return false; } public int hashCode(){ return key == null?0:key.hashCode(); } @Override public String toString() { return key+"="+value; } }
继承HashSet实现一个Map
package ListAndSet; import java.util.HashSet; import java.util.Iterator; import java.util.Map; /** * Created by wang on 16-4-23. */ public class Set2Map<K,V> extends HashSet<SimpleEntry<K,V>> { @Override public void clear() { super.clear(); } //判断是否包含某个key public boolean containsKey(K key){ return super.contains(new SimpleEntry<K, V>(key,null)); } //判断是否包含某个value public boolean containsValue(V value){ for(SimpleEntry<K,V> se :this){ if(se.getValue().equals(value)){ return true; } } return false; } //根据Key取出Value public V get(K key){ for(SimpleEntry<K,V> se:this){ if(se.getKey().equals(key)){ return se.getValue(); } } return null; } //存放入该Map中 public V put(K key,V value){ add(new SimpleEntry<K, V>(key,value)); return value; } //存放一个Map的key-value对放入该Map中 public void putAll(Map<? extends K,? extends V> map){ for(K key:map.keySet()){ add(new SimpleEntry<K, V>(key,map.get(key))); } } //根据指定key删除指定key-value对 public V removeEntry(K key){ for(Iterator<SimpleEntry<K,V>> it = this.iterator();it.hasNext();){ SimpleEntry<K,V> en = it.next(); if(en.getKey().equals(key)){ V v = en.getValue(); it.remove(); return v; } } return null; } public int size(){ return super.size(); } }
当一个Set集合中的全部集合元素都是SimpleEntry
<K,V>对象时,该Set就变成了一个Map
<K,V>.下面我们测试我们自己的Map集合:
@Test public void testMyMap(){ Set2Map<String,Integer> set2Map = new Set2Map<String, Integer>(); set2Map.put("Linux",100); set2Map.put("Java",98); set2Map.put("Android",96); Assert.assertEquals(set2Map.size(),3); Assert.assertTrue(set2Map.containsKey("Java")); Assert.assertEquals(set2Map.get("Linux"),new Integer(100)); set2Map.removeEntry("Java"); Assert.assertEquals(set2Map.size(),2); }
现在我们发现,只要对传统的Set稍作修改,就可以将Set集合改造成Map。而且这个Map集合在功能上几乎可以媲美JDK提供了Map。
相关文章推荐
- Java return和finally执行顺序
- [疯狂Java]I/O:标准流重定向、JVM读写其它进程数据
- Java的泛型类
- springMVC的生命周期
- ssm整合说明与模板-Spring Spring MVC Mybatis整合开发
- ssm整合说明与模板-Spring Spring MVC Mybatis整合开发
- Java多线程中的interrupt方法的使用
- java内存回收机制
- HashMap源码注解 之 put()方法(六)
- springMVC(2)------springMVC配置实例(注解)
- [翻译]Java Garbage Collection Basics Java 垃圾回收基础 之2 Java 技术与JVM
- Maven+Spring+mybatis项目搭建
- java-一维数组的随机赋值
- JAVA 如何使用 MD5 和SHA1进行数据加密
- [翻译]Java Garbage Collection Basics Java 垃圾回收基础 之1 概览
- Java中的volatile关键字
- java-一维数据的应用
- [翻译]Java Garbage Collection Basics Java 垃圾回收基础 目录
- 我是一个Java class
- 用java开发编译器之Thompson构造:正则表达式的词法解析