以下是 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的功能,以下是原理图:
以下为实现的代码:
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();
}
}
以下为测试代码:
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集合。