• 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. Python Cookbook笔记

    字符串:s.strip()  删除字符串开始和结尾的空白字符. s.lstrip() 删除左边的,s.rstrip()  删除右边的. 随机数:random.random()  生成0-1之间的数. ...

  2. @JoinTable和@JoinColumn

    默认情况下,JPA 持续性提供程序在映射多对多关联(或在单向的一对多关联中)的拥有方上的实体关联时使用一个连接表.连接表名称及其列名均在默认情况下指定,且 JPA 持续性提供程序假设:在关系的拥有方上 ...

  3. 浅谈C++中的那些内存泄露

    尽管学过C语言.可是C++里面的一些基础还是不太懂,还须要再掌握. 老范也開始要讲C++设计模式了,必须快点看了.不然就要白花窝滴钱了. 对于内存泄露,我的个人理解就是程序在执行过程中,自己开辟了空间 ...

  4. Linux实现密钥登陆

    公司为了安全,一直都采用密钥登陆远程SSH,现在有了自己的服务器,自己又学者配了一把,下面就是配置笔记. 1.登陆未设置密钥的Linux服务器 2.工具新建用户密钥生成向导 3.选择生成密钥的加密方式 ...

  5. 把Nginx加入系统服务 service nginx (start | stop | restart | reload)

    vim /etc/init.d/nginx 1 #!/bin/bash  2 # nginx Startup script for the Nginx HTTP Server  3 # it is v ...

  6. 毕业设计 ASP.Net+EasyUI开发 X X露天矿调度管理信息系统(一)

    开篇介绍关于EasyUI技术,界面部分的一些使用知识,包括控件的赋值.取值.清空,以及相关的使用. 我们知道,一般Web界面包括的界面控件有:单行文本框.多行文本框.密码文本框.下拉列表Combobo ...

  7. Android --------- 命名规范

    工程 软件名称,最好是英文首字母大写:如MobileSafe. 包 企业单位网址的倒序+软件名称:如com.baidu.mobilesafe. 类 类中分为:(头字母小写,其他每个单子首字母大写) 1 ...

  8. Swift--集合类型 数组 字典 集合

    数组 1.创建一个数组 var someInts = [Int]()空数组 someInts = []清空 var threeDoubles = Array(repeating: 0.0, count ...

  9. Xcode7 iOS9网络配置

    iOS9为了增强数据访问安全,将所有的http请求都改为了https,为了能够在iOS9中正常使用地图SDK,请在"Info.plist"中进行如下配置,否则影响SDK的使用. & ...

  10. SignalR2.0开发实例之——私聊

    一.前言 继续上一章的补充,这章介绍使用私聊的功能.主要通过一个方法   Clients.Client(Context.ConnectionId).showMessage(msg); SignalR框 ...