Java Se :Map 系列

之前对Java Se中的线性表作了简单的说明。这一篇就来看看Map。

Map系列的类,并不是说所有的类都继承了Map接口,而是说他们的元素都是以<Key, Value>形式设计的。

Dictionary

这个类现在不推荐使用了,但也有必要说一下,在它的描述中,有这么一句:Any non-null object can be used as a key and as a value。

现在都改用Map接口了。

Map

这个接口用于替换Dictionary的。这种集合提供了三种视图方式:

1)a set of keys

2)collection of Values

3)set of Entry<key, value>

Hashtable

这个类继承了Dictionary实现了Map。下面就重点看看这个类如何实现。

从这里看Hashtable是一个数组,数组的元素是Entry。

在看看Entry的设计:

这个Entry是一个单链表。

所以Hashtable的数据结构就可以认为是这样的:

为什么会这样设计?

以为硬件的原因,支持数组和链表两种形式,所以其他的数据结构(集合)都是基于这两类基础结构实现的。

Hashtable的设计,关键一点是hash,它计算的是key的hash,通过key的hashcode来计算这个元素所在的单链表在数组中的索引,然后根据索引取到单链表,然后进行其他的操作。

接下来看看它的几个重要方法如何实现:

put

public synchronized V put(K key, V value) {

   // Make sure the value is not null

   if (value == null) {

       throw new NullPointerException();

   }

   // 如果key已经在这个hashtable中存在,就覆盖原有的value,并返回原有的value。

   // 从这一小段代码中,我们就可以看出hashtable的结构确实如上面所想的那样。

Entry tab[] = table;

   int hash = key.hashCode();

   int index = (hash & 0x7FFFFFFF) % tab.length;

   for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {

       if ((e.hash == hash) && e.key.equals(key)) {

      V old = e.value;

      e.value = value;

      return old;

       }

   }

   modCount++;

   if (count >= threshold) {

       // Rehash the table if the threshold is exceeded

       rehash();

            tab = table;

            index = (hash & 0x7FFFFFFF) % tab.length;

   }

   // 如果不存在,就把key value 封装成一个Entry,然后插入到相应位置

// 在之前的代码中已经计算出它的索引了,接下来的任务就是把entry插入到数组索引位置处的单链表里。插入的时候是从头部插入的。

  Entry<K,V> e = tab[index];

   tab[index] = new Entry<K,V>(hash, key, value, e);

   count++;

   return null;

    }

Hashtable#put(key, value)

常用的方法get(key),remove(key)的方法就不分析了,因为没有必要,只要你了解了这个数据结构,自己就可以实现它的几个常用的方法。

keys

拿到的结果其实是一个枚举器(不过这个枚举器比较特殊,实现了Enumeration接口和Iterable接口),并不是一个集合。

同样的道理,elements也是如此,拿到的结果是一个遍历value的枚举器。

HashMap

HashMap的存储结构如下图所示,因为源码部分太多,所以就截了这么一张图,但也足够说明问题了:

从图上很容易看出,HashMap也是使用了数组实现的,数组中的元素是Node,再看看Node的设计:

Node也是一个单链表,看来HashMap与Hashtable在结构上是基本一致的。

也就是说他的模型也是下面图中所示:

如果说HashMap的结构只是这个样子的话,就没有必要存在了。为什么这么说呢,关键点还是在Node上,看看他的两个子类:

Entry:

每个节点又添加了一两个引用:before,after,这样一来结构就可以猜想为:

但其实并不是这个样子的,会根据hashcode进行一些算法处理,形成链式结构,也就是LinkedHashMap了。

如果有兴趣可以了解一些LinkedHashMap是如何实现的。

TreeNode:

每个节点都可以是一个树。就让结构变得更为复杂了。

时间: 2024-07-30 06:24:36

Java Se :Map 系列的相关文章

Java Se 基础系列(笔记) -- BasicDataType

java.lang.String类代表不可变的字符序列 String类常用方法:1.public char charAt(int index); -- 返回下标为index的字符 2.public int length(); 3.public int indexOf(String str); -- 返回字符串中第一次出现字符串str的下标   4.public int indexOf(String str, int fromIndex); 5.public boolean equalsIgnor

Java Se 基础系列(笔记) -- Exception

Exception 1.java 异常是java提供的用于处理程序中错误(指在程序运行的过程中发生的一些异常事件)的一种机制 2.java程序的执行过程中如果发生异常事件则自动生产一个异常类对象,该对象封装了异常事件的信息并被提交给java运行时系统,这过程称为throw异常: 当java运行时系统接收到异常对象时会寻找能处理这一异常的代码并交其处理,这过程称为catch异常 1 public class TestEx1 { 2 public static void main(String[]

java se系列(十二)集合

1.     集合 1.1. 什么是集合 存储对象的容器,面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,存储对象,集合是存储对象最常用的一种方式. 集合的出现就是为了持有对象.集合中可以存储任意类型的对象, 而且长度可变.在程序中有可能无法预先知道需要多少个对象, 那么用数组来装对象的话, 长度不好定义, 而集合解决了这样的问题. 1.2. 集合和数组的区别 数组和集合类都是容器 数组长度是固定的,集合长度是可变的.数组中可以存储基本数据类型,集合只能存储对象数组中存储

Java总结篇系列:java.lang.Object

从本篇开始,将对Java中各知识点进行一次具体总结,以便对以往的Java知识进行一次回顾,同时在总结的过程中加深对Java的理解. Java作为一个庞大的知识体系,涉及到的知识点繁多,本文将从Java中最基本的类java.lang.Object开始谈起. Object类是Java中其他所有类的祖先,没有Object类Java面向对象无从谈起.作为其他所有类的基类,Object具有哪些属性和行为, 是Java语言设计背后的思维体现. Object类位于java.lang包中,java.lang包包

java书籍推荐:《Java SE 6 技術手册》

Java SE 6 技術手册 或  Java SE 6 技術手册 Java SE 6 技術手册 為什麼選擇用 Markdown?仅仅是單純把文件又一次排版太無聊了,不如趁這個機會學些新東西.所以我就藉這個機會來學著用 Markdown,並看看它有什麼好處與壞處 ... 假设你须要 PDF 與 epub 格式.而又有點懶自己轉換,那麼能够考慮在 Google Play 或 Pubu 上向便當價致敬,假设你须要 mobi 格式,能够使用 calibre 把 epub 轉為 mobi ... :) 我

深入Java集合学习系列:HashMap的实现原理

参考文献 引用文献:深入Java集合学习系列:HashMap的实现原理,大部分参考这篇博客,只对其中进行稍微修改 自己曾经写过的:Hashmap实现原理 1. HashMap概述: HashMap是基于哈希表的Map接口的非同步实现(Hashtable跟HashMap很像,唯一的区别是Hashtalbe中的方法是线程安全的,也就是同步的).此实现提供所有可选的映射操作,并允许使用null值和null键.此类不保证映射的顺序,特别是它不保证该顺序恒久不变. 2. HashMap的数据结构: 在ja

《写给大忙人看的java se 8》笔记

现在才来了解java8,是不是后知后觉了点? 新的编程技术,个人不喜欢第一时间跟进. 待社区已有实践积淀再切入似乎更划算些? 一点点精明的考虑. 不多说,上代码. //读<写给大忙人看的java se 8>做的笔记代码 //希望对忙到连这书都没工夫看的你,匆匆一瞥,留下印象 //祝编程愉快 public class MainTest { //第一章,讲lambda表达式 //lambda表达式类似javascript的函数字面量,可用于替代java的匿名内部类 //基本型为 (形参列表)-&g

Monitor and diagnose performance in Java SE 6--转载

Java SE 6 provides an in-depth focus on performance, offering expanded tools for managing and monitoring applications and for diagnosing common problems. The improvements include: Monitoring and management API enhancements Official support for an imp

深入Java集合学习系列:LinkedHashMap的实现原理

1. LinkedHashMap概述: LinkedHashMap是Map接口的哈希表和链接列表实现,具有可预知的迭代顺序.此实现提供所有可选的映射操作,并允许使用null值和null键.此类不保证映射的顺序,特别是它不保证该顺序恒久不变.   LinkedHashMap实现与HashMap的不同之处在于,后者维护着一个运行于所有条目的双重链接列表.此链接列表定义了迭代顺序,该迭代顺序可以是插入顺序或者是访问顺序.   注意,此实现不是同步的.如果多个线程同时访问链接的哈希映射,而其中至少一个线