• 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集合。

Java集合的实现细节—Set集合和Map集合的更多相关文章

  1. 【读书笔记】【深入理解ES6】#7-Set集合和Map集合

    ES6新标准中将Set集合和Map集合添加到JS中. ES5中Set集合和Map集合 在ES5中,开发者们用对象属性来模拟这两种集合. var set = Object.create(null); s ...

  2. 编写Java程序,使用List集合和Map集合输出 市和区

    如图: 代码: import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java ...

  3. Java List集合和Map集合的综合应用

    public static void main(String[] args) { //--------------------------------------------------------- ...

  4. 【spring set注入 注入集合】 使用set注入的方式注入List集合和Map集合/将一个bean注入另一个Bean

    Dao层代码: package com.it.dao; public interface SayHell { public void sayHello(); } Dao的Impl实现层: packag ...

  5. java基础33 Set集合下的HashSet集合和TreeSet集合

    单例集合体系: ---------| collection  单例集合的根接口--------------| List  如果实现了list接口的集合类,具备的特点:有序,可重复       注:集合 ...

  6. Collection集合和Collection集合常用功能

    Collection集合常用功能 方法: boolean add(E e); 向集合中添加元素 boolean remove(E e); 删除集合中的某个元素 void clear(); 清空集合所有 ...

  7. JAVA枚举操作(获取值,转map集合)

    JAVA枚举相对来说比.NET的枚举功能强大,感觉就像是一种简化版的类对象,可以有构造方法,可以重载,可以继承接口等等,但不能继承类,JAVA枚举在实际开发中应用相当频繁,以下几个封装方法在实际开发中 ...

  8. Java分享笔记:使用entrySet方法获取Map集合中的元素

    /*--------------------------------- 使用entrySet方法取出Map集合中的元素: ....该方法是将Map集合中key与value的关系存入到了Set集合中,这 ...

  9. Java分享笔记:使用keySet方法获取Map集合中的元素

    /*--------------------------- Map集合中利用keySet方法获取所有的元素值: ....keySet方法:将Map中的所有key值存入到Set集合中, ....利用Se ...

随机推荐

  1. 解决 'utf-8' codec can't decode byte 0x8b in position 1: invalid start byte

    "Accept-Encoding": "gzip, deflate", 这条信息代表本地可以接收压缩格式的数据,而服务器在处理时就将大文件压缩再发回客户端,IE ...

  2. css样式-表格优化

    1.表格的初步优化 index.html <!DOCTYPE html> <html> <head> <meta charset="UTF-8&qu ...

  3. MYSQL存储过程和函数学习笔记

    学至Tarena金牌讲师,金色晨曦科技公司技术总监沙利穆课程笔记的综合. 1. 什么是存储过程和函数 将SQL语句放入一个集合里,然后直接调用存储过程和函数来执行已经定义好的SQL语句,通过存储过程和 ...

  4. phpstorm xdebug调试设置样式

    由于本人比较喜欢白底的phpstorm开发环境,所以XDEBUG断点调试,F8时默认是没有背景色的,phpstorm中的设置方式如下 files -> settings -> Editor ...

  5. [深入React] 7.组件生命周期

    生命周期一共分三段:初始化,运行中,销毁.按照顺序: 初始化 getDefaultProps():Object 全局只会调用一次,为当前类生成的默认props,会被父组件传入的同名props覆盖. g ...

  6. Linux命令之exit

    本文链接:http://codingstandards.iteye.com/blog/836625   (转载请注明出处) 用途说明 exit命令用于退出当前shell,在shell脚本中可以终止当前 ...

  7. IE6下的怪异解析知识点补充

    转载请注明出处:HTMl5自由者      

  8. html拼接数据的时候一定要注意null值的问题

    后台会返回null文本  如果直接拼接 不仅仅格式问题 前台会显示null   如果是图片  用fiddle抓取 还会发现你请求了一个带域名/null的接口     所以要把null格式化为空文本

  9. Querylayer(查询图层) - 浅谈

    Querylayer(查询图层)是通过 SQL 查询定义的图层或独立表.通过 Querylayer 可将空间信息和非空间信息都存储在DBMS 中,从而使这些信息可以轻松地整合到 ArcMap 中的各 ...

  10. COM 浅谈

    ArcObject 是基于 COM(Microsoft Component Object Model),即组件对象模型.虽然ArcGIS的终端用户不用理解什么是COM,但是作为基于ArcObject的 ...