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集合。
Java集合的实现细节—Set集合和Map集合的更多相关文章
- 【读书笔记】【深入理解ES6】#7-Set集合和Map集合
ES6新标准中将Set集合和Map集合添加到JS中. ES5中Set集合和Map集合 在ES5中,开发者们用对象属性来模拟这两种集合. var set = Object.create(null); s ...
- 编写Java程序,使用List集合和Map集合输出 市和区
如图: 代码: import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java ...
- Java List集合和Map集合的综合应用
public static void main(String[] args) { //--------------------------------------------------------- ...
- 【spring set注入 注入集合】 使用set注入的方式注入List集合和Map集合/将一个bean注入另一个Bean
Dao层代码: package com.it.dao; public interface SayHell { public void sayHello(); } Dao的Impl实现层: packag ...
- java基础33 Set集合下的HashSet集合和TreeSet集合
单例集合体系: ---------| collection 单例集合的根接口--------------| List 如果实现了list接口的集合类,具备的特点:有序,可重复 注:集合 ...
- Collection集合和Collection集合常用功能
Collection集合常用功能 方法: boolean add(E e); 向集合中添加元素 boolean remove(E e); 删除集合中的某个元素 void clear(); 清空集合所有 ...
- JAVA枚举操作(获取值,转map集合)
JAVA枚举相对来说比.NET的枚举功能强大,感觉就像是一种简化版的类对象,可以有构造方法,可以重载,可以继承接口等等,但不能继承类,JAVA枚举在实际开发中应用相当频繁,以下几个封装方法在实际开发中 ...
- Java分享笔记:使用entrySet方法获取Map集合中的元素
/*--------------------------------- 使用entrySet方法取出Map集合中的元素: ....该方法是将Map集合中key与value的关系存入到了Set集合中,这 ...
- Java分享笔记:使用keySet方法获取Map集合中的元素
/*--------------------------- Map集合中利用keySet方法获取所有的元素值: ....keySet方法:将Map中的所有key值存入到Set集合中, ....利用Se ...
随机推荐
- JS浏览器对象-Screen对象
代码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title ...
- mybatis + log4j 打印mybatis的sql
项目中使用log4j管理日志,同时使用了mybatis 在log4j中rootLogger级别是info的情况下正常是不会打印sql出来的,这个时候设置如下: log4j.rootLogger=inf ...
- mac 环境下使用virtual box 虚拟机(win7)与主机之间互相ping通
首先选择virtual box设置网络连接方式为网桥 混杂模式设置为全部允许 如下图: 进入虚拟机把虚拟机IP设置和主机在一个网段.如主机是192.168.1.100虚拟机可以设置为192.168.1 ...
- C++经典题目:有n个人围成一圈,顺序排号,然后数数进行淘汰的解法和一些思考
问题描述: 有n个人围成一圈,顺序排号.从第一个人开始报数(1~3报数),凡报到3的人退出圈子,问最后留下的人原来排在第几号. 分析: 首先由用户输入人数n,然后对这n个人进行编号[因为如果不编号的话 ...
- ViewPager切换动画PageTransformer使用
Android从3.0开始,就添加了很多动画,ViewPager当然也不例外,相对于非常平庸的默认切换动画,Google给我们展示了两个动画例子:DepthPageTransformer和ZoomOu ...
- rhel Linux系统yum的配置
yum是一个很方便的linux系统软件管理工具,但是很多新手还是不会配置yum,下面详细的介绍下yum的配置方法,其实很简单. 1.首先确保系统ISO镜像已经成功挂载,可以用df -h命令查看.2.创 ...
- 网页、JavaScript 数据类型
JavaScript 数据类型 一.基本数据类型: 字符串.数字.布尔.日期和时间 JavaScript 拥有动态类型 JavaScript 拥有动态类型.这意味着相同的变量可用作不同的类型: 1 v ...
- 回顾:Linq To SQL语法 - 实体类
第一篇博客,还望各位大神勿喷 小弟在此代码奉上........ 借用NorthWind数据库,实现一个商品展示的小功能.上代码: 添加对Linq的引用 using System.Data.Linq;/ ...
- [c#]asp.net开发微信公众平台(6)阶段总结、服务搭建、接入
经过前5篇,跟着一步步来的话,任何人都能搭建好一个能处理各种微信消息的框架了,总结一下最容易忽略的问题: 1.文本消息中可以使用换行符\n : 2.微信发来的消息中带的那个长整型的时间,我们完全 ...
- ORA-02095: specified initialization parameter cannot be modified
输入命令:alter system set utl_file_dir='/home/oracle/logmnr' scope=spfile; 报错: 出错原因:没有用spfile文件启动数据库 解决办 ...