zoukankan      html  css  js  c++  java
  • Java集合的实现细节—Set集合和Map集合

    • Set:代表无序、不可重复的集合
    • Map:代表key-value对集合,也称为关联数组

            从表面上看,Set和Map相似性很少,但实际上可以说Map集合时Set集合的扩展。


    1、Set集合和Map集合的继承体系



    Set集合的继承体系


    Map集合的继承体系

    2、Set集合和Map集合的关系


            仔细观察上面两张图,可以发现以下规律:

    • Set   <--->   Map
    • EnumSet   <--->   EnumMap
    • SortedSet   <--->   SortedMap
    • TteeSet   <--->   TreeMap
    • NavigableSet   <--->   NavigableMap
    • HashSet   <--->   HashMap
    • LinkedHashSet   <--->   LinkedHashMap

            以上的关系绝对不是偶然的,Map集合的key不能重复,而且也是无序的。亦即Map集合中的key可以组成一个Set集合。实际上,Map集合提供了如下方法返回key所组成的Set集合。

    • Set<K>   keySet()

            由此,即可实现从Map到Set的转换。其实,还可以实现从Set到Map的扩展——Map集合就相当于一个Set集合,只是此时Set集合中的元素都是key-value对。如下图所示:

                

                                                                       Map集合示意图                                                       将关联数组的key-value对捆绑在一起

    3、实现把Set扩展成“Map”集合


            为了把Set扩展成“Map”,可以考虑重新定义一个SimpleEntry类,使用这个类来代表一个key-value对。当Set集合的元素都是SimpleEntry对象时,该Set集合就变成了“Map”集合。


    SimpleEntry.java

    import java.io.Serializable;
    import java.util.Map.Entry;
    
    
    public 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;
    	}
    
    
    	@Override
    	public V setValue(V value) {	//改变key-value对的value值
    		V oldValue = this.value;
    		this.value = value;
    		return oldValue;
    	}
    	
    	@Override
    	public boolean equals(Object obj) {		//根据key比较两个SimpleEntry是否相等
    		if(obj == this) {
    			return true;
    		}
    		if(obj.getClass() == SimpleEntry.class) {
    			SimpleEntry se = (SimpleEntry)obj;
    			return se.getKey().equals(getKey());
    		}
    		return false;
    	}
    	
    	//根据key计算hashCode
    	public int hashCode() {
    		return key == null ? 0 : key.hashCode();
    	}
    	
    	public String toString() {
    		return key + "=" + value;
    	}
    }


    Set2Map.java:继承HashSet实现一个Map

    import java.util.HashSet;
    import java.util.Map;
    import java.util.Iterator;
    
    
    public class Set2Map<K, V> extends HashSet<SimpleEntry<K, V>> {
    	//实现清空所有key-value对的方法
    	public void clear() {
    		super.clear();
    	}
    	
    	//判断是否包含某个key
    	public boolean containsKey(K key) {
    		return super.contains(new SimpleEntry<K, V>(key, null));
    	}
    	
    	//判断是否包含某个value
    	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;
    	}
    	
    	//将key-value对放入集合中
    	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> m) {
    		for(K key : m.keySet()) {
    			add(new SimpleEntry<K, V>(key, m.get(key)));
    		}
    	}
    	
    	//根据指定的key删除对应的key-value对
    	public V removeENtry(Object key) {
    		for(Iterator<SimpleEntry<K, V>> it = this.iterator(); it.hasNext(); ) {
    			SimpleEntry<K, V> en = (SimpleEntry<K, V>)it.next();
    			if(en.getKey().equals(key)) {
    				V v = en.getValue();
    				it.remove();
    				return v;
    			}
    		}
    		return null;
    	}
    	
    	//获取key-value对的总数
    	public int size() {
    		return super.size();
    	}
    }
    


            上面两段代码中的粗体部分定义了一个先是定义了一个 SimpleEntry<K, V>类。当一个Set集合中的所有元素都是SimpleEntry<K, V>对象时,该Set就变成了一个Map<K, V>集合。

            接下来,程序以HashSet<SimpleEntry<K, V>>为父类派生了一个子类Set2Map<K, V>,这个Set2Map<K, V>扩展类完全可以被当成Map使用,因此Set2Map<K, V>中也提供了Map集合应该提供的绝大部分方法。


    Set2MapTest.java:测试扩展出来的“Map”集合

    public class Set2MapTest {
    	public static void main(String[] args) {
    		Set2Map<String, Integer> scores = new Set2Map<String, Integer>();
    		
    		//将key-value对放入集合中
    		scores.put("C", 70);
    		scores.put("C++", 80);
    		scores.put("Java", 90);
    		//输出集合中的内容
    		System.out.println(scores);
    		
    		//访问Map集合中的key-value对
    		System.out.println("key-value对的数目:" + scores.size());
    		scores.removeENtry("C");
    		System.out.println("删除key为"C"的Entry之后:" + scores);
    		
    		//根据key取出value
    		System.out.println("C++的成绩:" + scores.get("C++"));
    		
    		//判断是否包含指定的key
    		System.out.println("是否包含"Java"key:" + scores.containsKey("Java"));
    		
    		//判断是否包含指定的value
    		System.out.println("是否包含 100 value:" + scores.containsValue(100));
    		
    		//清空集合
    		scores.clear();
    		System.out.println("清空集合后:" + scores);
    	}
    }

    运行结果:



            由此可以看出,只要对Set稍做改造,就可将Set改造成可以和系统媲美的Map集合。



  • 相关阅读:
    [洛谷P2745] [USACO5.3]窗体面积Window Area
    [洛谷P2751] [USACO4.2]工序安排Job Processing
    [洛谷P2738] [USACO4.1]篱笆回路Fence Loops
    [洛谷P4609] [FJOI2016]建筑师
    [洛谷P3228] [HNOI2013]数列
    解决Qt5使用SSL的“qt.network.ssl: QSslSocket: cannot resolve SSLv2_client_method”错误
    qt查看是否支持SSL
    qt获取依赖的openssl的版本
    qt关闭ssl验证,解决不能正常使用自签署ssl证书API的问题
    使用OpenSSL创建HTTPS所使用的SSL证书
  • 原文地址:https://www.cnblogs.com/keanuyaoo/p/3347977.html
Copyright © 2011-2022 走看看