您的位置:首页 > 编程语言 > Java开发

JDK集合分析Set和Map的关系(自己实现Set到Map的扩展)

2016-04-24 14:24 585 查看
Set代表的是一种集合元素无序,集合元素不可重复的集合,Map则代表一种由多个Key-Value对组成的集合,Map集合类似于传统的关联数组。表面上看,Map和Set毫无关联,但其实Map和Set之间有莫大的关联,可以说,Map是Set的扩展。

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。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: