前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >常见Java集合的实现细节(一):Map和Set的关系

常见Java集合的实现细节(一):Map和Set的关系

作者头像
CoderJed
发布2018-11-09 15:05:32
1.4K0
发布2018-11-09 15:05:32
举报
文章被收录于专栏:Jed的技术阶梯Jed的技术阶梯

以下是 Java 常用集合类的继承结构图:

注意观察 Set 和 Map 的继承结构:

这些接口和类名如此相似绝不是偶然的现象,实际上,这些Map集合的key有一个特征:所有的key不能重复,key之间没有顺序,也就是说,这些Map的key可以组成一个Set集合,所有我们发现Map集合提供了Set<K> keySet()这个方法,而Map的value是可以重复的,Map的values()方法直接返回Collection,不同的Map实现类有不同的values()方法,这个会在本文之后的内容进行分析,总的来说,Map所有的key其实是一个Set,Map所有的value是某种可以存储重复数据的集合,而把 key组成的Set中的元素和value组成的某种的集合中的元素一一对应起来后,就组成了一个Map

既然Map的key和value有很强的关联关系,那么我们干脆把key和value当做一个整体来存放到Set中让这个Set具有Map的功能,以下是原理图:

以下为实现的代码:

代码语言:javascript
复制
import java.io.Serializable;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

class SimpleEntry<K, V> implements Entry<K, V>, Serializable {
    
    private final K key;
    private V value;
    
    public SimpleEntry(K key, V value) {
        this.key = key;
        this.value = value;
    }
    
    public SimpleEntry(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;
    }

    /**
     * 改变 key-value 对的 value 值
     */
    @Override
    public V setValue(V value) {
        V oldValue = this.value;
        this.value = value;
        return oldValue;
    }

    @Override
    public int hashCode() {
        return key == null ? 0 : key.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if(obj == this) {
            return true;
        }
        if(obj.getClass() == this.getClass()) {
            SimpleEntry that = (SimpleEntry) obj;
            return that.getKey().equals(this.getKey());
        }
        return false;
    }

    @Override
    public String toString() {
        return this.key + "=" + this.value;
    }
    
}

public class Set2Map<K, V> extends HashSet<SimpleEntry<K, V>> {
    
    // 清空 Set
    public void clean() {
        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> entry : this) {
            if(entry.getValue().equals(value)) {
                return true;
            }
        }
        return false;
    }
    
    // 根据指定 key 取出对应的 value
    public V get(K key) {
        for(SimpleEntry<K, V> entry : this) {
            if(entry.getKey().equals(key)) {
                return entry.getValue();
            }
        }
        return null;
    }
    
    // 将指定 key-value 对放入Set中
    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) {
        Iterator<SimpleEntry<K, V>> iterator = this.iterator();
        while(iterator.hasNext()) {
            SimpleEntry<K, V> entry = iterator.next();
            if(entry.getKey().equals(key)) {
                V value = entry.getValue();
                iterator.remove();
                return value;
            }
        }
        return null;
    }
    
    public int size() {
        return super.size();
    }
    
}

以下为测试代码:

代码语言:javascript
复制
public class Set2MapTest {

    public static void main(String[] args) {
        
        Set2Map<String, Integer> scores = new Set2Map<>();

        scores.put("语文", 89);
        scores.put("数学", 83);
        scores.put("英文", 80);
        System.out.println(scores);
        System.out.println(scores.size());
        scores.removeEntry("数学");
        System.out.println(scores);
        System.out.println(scores.get("语文"));
        System.out.println(scores.containsKey("英文"));
        System.out.println(scores.containsValue(89));
        scores.clean();
        System.out.println(scores);
        
    }
    
}

运行结果:
[英文=80, 数学=83, 语文=89]
3
[英文=80, 语文=89]
89
true
true
[]

以上程序说明,只要对传统Set稍做改造,就可以将Set改造为Map集合。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.10.23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档