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

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。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值