java集合之间的关系及实现细节——Set与Map

    首先,先谈一下Set和Map的一些特性及体系结构:

  1.1 Set和Map

  Set代表一种无序的、元素不可重复的集合。Map则代表是一种key-value对组成的集合,Map集合类似于传统的关联数组。表面上看它们之间的关系的相似性很少,实则Map和Set之间有着莫大的关联,可以这样说Map集合实则是Set集合的扩展。

  至于为什么是Set是一种无序的、元素不可重复的集合;Map集合类似传统的关系数组。理解这个非常重要,这个我在后面会进行补充说明。

  1.2 Set和Map之间的关系

  先看看Set集合的继承体系,再来看Map集合的类继承体系:

  从上图灰色阴影部分可以看出Map和Set的集合实现类除了后面Set和Map部分不一样,前面的类或接口的名称以及其继承结构完全一样。是偶然吗?答案绝对不是。而且你若是用过Map的话,你会发现Map不允许再现相同的key,且Map在遍历的时候,key是无序的,正是对应Map中keySet()方法。这与上述Set集合的特征又是惊人的相似。下面我会用一段小程序来说明Set为何与Map这么相似了。

  先说一下我的思路: 

  (1)在我的印象中:map的key与value存在的关系如下图:

  (2)既然Map中的key与value存在一一对应关系,那么,现在我们换一种思路来思考,把key-value如下图:

  由此可见,如上述图3.4表明的一样,如果将key-value绑定在一起,那么Map说白了就是个(key-value)的Set集合

  由上述思路,下面是程序实现由Set实现Map:

(1)包含key-value的entry实现代码:

 1 package com.ngu4k.test.collection;
 2
 3 import java.io.Serializable;
 4 import java.util.Map.Entry;
 5
 6 public class SimpleEntry<K,V> implements Entry<K,V>,Serializable{
 7     private static final long serialVersionUID = -4352059623055803486L;
 8     private final K key;
 9     private V value;
10     //定义两个如下构造器
11     public SimpleEntry(K key,V value)
12     {
13         this.key = key;
14         this.value = value;
15     }
16
17     public SimpleEntry(Entry<? extends K,? extends V> entry)
18     {
19         this.key = entry.getKey();
20         this.value = entry.getValue();
21     }
22     //获取key
23     public K getKey()
24     {
25         return key;
26     }
27     //获取value
28     public V getValue()
29     {
30         return value;
31     }
32     //改变该key-value对的value值
33     public V setValue(V value)
34     {
35         V oldValue = this.value;
36         this.value = value;
37         return oldValue;
38     }
39     //根据key比较两个对象是否相等
40     public boolean equals(Object o)
41     {
42         if(o == this){
43             return true;
44         }
45         if(o.getClass() == SimpleEntry.class){
46             SimpleEntry se = (SimpleEntry)o;
47             return se.getKey().equals(getKey());
48         }
49         return false;
50     }
51     //根据key获得hashCode的值
52     public int hashCode(){
53         return key == null ? 0 : key.hashCode();
54     }
55
56     public String toString(){
57         return key + "=" + value;
58     }
59 }

(2)由Set到Map的简单实现代码:

  1 package com.ngu4k.test.collection.map;
  2
  3 import java.util.HashSet;
  4 import java.util.Iterator;
  5 import java.util.Map;
  6
  7 import com.ngu4k.test.collection.SimpleEntry;
  8
  9 /**
 10  * Set到Map的简单实现
 11  * @author ikouer
 12  * @param <K>
 13  * @param <V>
 14  */
 15 public class Set2Map<K,V> extends HashSet<SimpleEntry<K,V>>{
 16
 17     private static final long serialVersionUID = 1596710712757978024L;
 18
 19     //清空Set2Map中key-value对
 20     public void clear()
 21     {
 22         super.clear();
 23     }
 24     //查看是否包含指定的key
 25     public boolean containsKey(K key)
 26     {
 27         return super.contains(new SimpleEntry<K, V>(key,null));
 28     }
 29     //查看是否包含指定的value
 30     public boolean containsValue(V value)
 31     {
 32         for(SimpleEntry<K,V> se : this)
 33         {
 34             if(se.getValue().equals(value))
 35             {
 36                 return true;
 37             }
 38         }
 39         return false;
 40     }
 41     //根据指定的key获取对应的value
 42     public V get(K key)
 43     {
 44         for(SimpleEntry<K,V> se : this)
 45         {
 46             if(se.getKey().equals(key)){
 47                 return se.getValue();
 48             }
 49         }
 50         return null;
 51     }
 52     //把指定的key-value添加到集合中
 53     public V put(K key,V value)
 54     {
 55         this.add(new SimpleEntry<K,V>(key,value));
 56         return value;
 57     }
 58     //把一个Map集合添加到Set2Map集合中
 59     public void putAll(Map<? extends K,? extends V> om)
 60     {
 61         for(K key : om.keySet())
 62         {
 63             this.add(new SimpleEntry<K,V>(key,om.get(key)));
 64         }
 65     }
 66     //根据指定的key移除对应的key-value
 67     public V remove(K key)
 68     {
 69         for(Iterator<SimpleEntry<K,V>> it = this.iterator(); it.hasNext();){
 70             SimpleEntry<K,V> se = it.next();
 71             if(se.getKey().equals(key))
 72             {
 73                 V rv = se.getValue();
 74                 it.remove();
 75                 return rv;
 76             }
 77         }
 78         return null;
 79     }
 80     //获取集合大小
 81     public int size(){
 82         return super.size();
 83     }
 84
 85     public static void main(String[] args) {
 86         Set2Map<String,Integer> smap = new Set2Map<String,Integer>();
 87         //将key-value放入集合
 88         smap.put("语文", 88);
 89         smap.put("数学", 99);
 90         smap.put("英语", 102);
 91         System.out.println(smap);
 92         System.out.println(smap.size());
 93         //执行移除对称key的entry
 94         smap.remove("数学");
 95         System.out.println("删除key为\"数学\"的Entry之后:"+smap);
 96         //获取key为语文的value值
 97         System.out.println("key为\"语文\"的value值:"+smap.get("语文"));
 98         //判断是否包含key
 99         System.out.println("是否包含key为\"英语\"的entry:"+smap.containsKey("英语"));
100         //判断是否包含value
101         System.out.println("是否包含value为102:"+smap.containsValue(102));
102         //执行clear方法
103         smap.clear();
104         System.out.println("执行完clear()方法之后的集合:"+smap);
105
106     }
107 }

此处的提供的Set2Map集合的功能甚至可以媲美Map集合的功能

而TreeSet底层也是采用TreeMap实现的。至于Tree(二叉树)是怎么实现,读者可参考疯狂java系列书籍或到网上自行搜索。

至此,我想大家应该知道Set中的元素为什么是无序且不可重复的了吧。(因为Set集合的底层全部采用Map集合来实现的)

下面再和大家分析一下java中的Map的实现--HashMap的原理:

1.3 HashMap的实现原理

  要搞清hashmap是什么,首先要清楚它的数据结构,在java编程语言中,最基本的结构就是数组和模拟指针了,几乎所有的数据都可以用这两具基本的结构来构造的,hashmap也不例外。java中的hashmap实际上是一个数组和链表的结合体(在数据结构中,一般称之为“链表散列”)

  java中的hashmap是以key-value的模式存取的,实际上它也是存放在数组当中的。过程是这样的:首先会得到key的hashcode,然后通过hashcode(key)%size,来得到数组的索引,把entry放入数组中。请看下图(横排表示数组,纵排表示链表):

  

由上图可知,hashMap其实是就是一个数组。看一下hashMap的源代码:

上面table中的定义为:  transient Entry[] table;

由此可见hashmap在初始化时会创建一个Entry类型的数组。再看一下Entry的源代码:

  可以看到entry中持有一个指向下一个元素的引用,这样就构成了链表。

  当我们往hashmap中put元素中,首先根据key的hash值得到这个元素在数组中的位置(即下标),然后可这个元素放入到对应的位置就行了。如果这个位置已经有了其它元素,那么在同一个位置的元素将以链表的形式存储,新加入的元素放在链头,最先加入的元素放在链尾。从hashmap中get元素的时候,首先根据传入的key值的hash得到元素在数组中的存放位置,然后再通过key的equals方法来得到需要的元素。

  java中的Set与Map并不是我们想像中的那么神秘,其实很简单。

  本文参考:《疯狂java》、《java中的哈希表》

  上述是Map与Set的关系及一些实现细节。若有不到之处,敬请各位指导并谅解,谢谢!

  下篇文章我会把List与Map的关系及ArrayList,LinkList的实现细节做一些详细的记录。

欢迎大家阅读与转载。转载请注入本文原址,谢谢!

java集合之间的关系及实现细节——Set与Map

时间: 2024-10-05 08:19:39

java集合之间的关系及实现细节——Set与Map的相关文章

Java 集合的继承关系(简化)

最近在看<Java编程思想>的第17章时,发现集合的继承关系中缺了Queue的类图,因此准备把图补上.另外,在绘制的过程中只保留了常用的集合对象,使整个继承看起来比较简洁.如果有错误,请大家指出.

Scala集合和Java集合对应转换关系

作者:Syn良子 出处:http://www.cnblogs.com/cssdongl 转载请注明出处 用Scala编码的时候,经常会遇到scala集合和Java集合互相转换的case,特意mark一下,加深记忆 scala.collection.Iterable <=> java.lang.Iterable scala.collection.Iterable <=> java.util.Collection scala.collection.Iterator <=>

我所理解Java集合框架的部分的使用(Collection和Map)

所谓集合,就是和数组类似--一组数据.java中提供了一些处理集合数据的类和接口,以供我们使用. 由于数组的长度固定,处理不定数量的数据比较麻烦,于是就有了集合. 以下是java集合框架(短虚线表示接口,长虚线表示抽象类,实线表示类,箭头表示实现接口或者继承)(在网络上找的图,不知道原作者,侵权请联系我删除)(总之,关系很复杂,所以不用记得这个图,只是用来吓吓人而已的). 下面贴上个人理解之精简版之Collection(集)和Map(地图?暂且这么理解吧),话说思维导图蛮好用,以下是两幅思维导图

android java unicode 之间的关系

背景 使用正则表达式寻找emoji字符,进行过滤 1.通过 http://apps.timwhitlock.info/emoji/tables/unicode 确定emoji 的字符码点范围在 \u1F600-\u1F6FF 之间 需要查看unicode码点和UTF-8 UTF-16 UTF-32的童鞋可以参考这篇文章 http://www.ruanyifeng.com/blog/2014/12/unicode.html 2.使用正则开始匹配 string 就是那个含有emoji unicode

Java集合体系结构(List、Set、Collection、Map的区别和联系)

1.Collection 接口存储一组不唯一,无序的对象 2.List 接口存储一组不唯一,有序(插入顺序)的对象 3.Set 接口存储一组唯一,无序的对象 4.Map接口存储一组键值对象,提供key到value的映射.Key无序,唯一.value不要求有序,允许重复.(如果只使用key存储,而不使用value,那就是Set) 原文地址:https://www.cnblogs.com/Yanss/p/11718085.html

Java集合(2)——深入理解ArrayList、Vector和LinkedList

回顾 Java集合主要分为两个体系结构,Collection和Map.这篇博客主要介绍Collection子接口List下的三个经常使用的实现类:ArrayList.Vector和LinkedList. 详细内容参见<Java基础--集合> 先看下关系图: 1.ArrayList 这是List最常用的实现类,想一想为什么他最常用? Array,在java中意为"数组".猜想ArrayList和数组应该关系很密切,其实ArrayList可以看作是一个可以改变大小的数组. 举个

Java总结——常见Java集合实现细节(1)

Java提高--常见Java集合实现细节(1) 2018年04月18日 15:07:35 阅读数:25 集合关系图 Set和Map set代表一种集合元素无序.集合元素不可重复的集合 map代表一种由多个key-value对组成的集合 set和map的关系 set和map的接口十分类似. Map的key有一个特征:所有key不能重复,且key之间没有顺序,也就是说将所有key组合起来就是一个Set集合. Map-->Set : Map中提供了  Set<k> keySet()  返回所有

Java集合关系图表

JAVA的集合图各个函数之间的继承关系----可以参照Java教程总结随笔8对照理解: 整理的集合继承的关系,便于理解Java在原有的机制上进行扩展丰富的思维逻辑!

常见Java集合的实现细节

1. Set和Map Set代表一种集合元素无序.集合元素不可重复的集合,Map则代表一种由多个key-value对组成的集合,Map集合类似于传统的关联数组.表面上看它们之间相似性很少,但实际上Map和Set之间有莫大的关联. 1.1 Set和Map的关系 在看Set和Map之间的关系之前,先来看看Set集合的继承体系. 再看Map集合的类继承关系: 仔细观察图3.2中的Map集合的继承体系里被灰色覆盖的区域,可以发现,这些Map接口.实现类和Set集合的接口.实现类的类名完全类似,这绝不是偶