最怕,你以为你懂咯,其实你还不懂;

见贤思齐,看看那些我们习以为常的集合,通过相关定义、源码,思考分析,加深对其的理解,提高编码能力,能做一个略懂的程序员;

做几个我们常用的集合类。开篇HashMap

      

HashMap
 
1、基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。
2、为什么允许null的key呢?
  因为在put方法,会对是null值的可以进行特殊处理
     private V putForNullKey(V value) {
for (Entry<K,V> e = table[0]; e != null; e = e.next) {
if (e.key == null) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(0, null, value, 0);
return null;
}
3、默认大小:16,临界因子是:0.75,达到临界因子的时候,初始时候的长度就会扩大一倍,即 length*2,永永是2的倍数,当达到
     内部的table 使用while循环将原来entry 赋值到新的entry 中(这一步往往影响性能)
  HashMap由数组+链表组成的
    //初始化大小
static final int DEFAULT_INITIAL_CAPACITY = 16;
//1左移30位
static final int MAXIMUM_CAPACITY = 1 << 30;
//临界因子
static final float DEFAULT_LOAD_FACTOR = 0.75f; void addEntry(int hash, K key, V value, int bucketIndex) {
if ((size >= threshold) && (null != table[bucketIndex])) {
resize(2 * table.length);//长度扩大两倍,进行交换
hash = (null != key) ? hash(key) : 0;
bucketIndex = indexFor(hash, table.length);
} createEntry(hash, key, value, bucketIndex);
} void resize(int newCapacity) {
Entry[] oldTable = table;
int oldCapacity = oldTable.length;
if (oldCapacity == MAXIMUM_CAPACITY) {
threshold = Integer.MAX_VALUE;
return;
} Entry[] newTable = new Entry[newCapacity];
boolean oldAltHashing = useAltHashing;
useAltHashing |= sun.misc.VM.isBooted() &&
(newCapacity >= Holder.ALTERNATIVE_HASHING_THRESHOLD);
boolean rehash = oldAltHashing ^ useAltHashing;
transfer(newTable, rehash);
table = newTable;
threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
} //交换元素
void transfer(Entry[] newTable, boolean rehash) {
int newCapacity = newTable.length;
for (Entry<K,V> e : table) {
while(null != e) {
Entry<K,V> next = e.next;
if (rehash) {
e.hash = null == e.key ? 0 : hash(e.key);
}
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
}
}
}
     public synchronized V put(K key, V value) {
// hashtable 是不允许null值的
if (value == null) {
throw new NullPointerException();
}
...}
 
 
3、由于hashmap扩容的问题,所以使用hashmap保存较大的数的时候,尽量设置好长度,不然影响效率;
 
4、hashmap继承关系 对比右边是hashtable的继承关系,一个继承的是AbstractMap,另外一个是Dictionary
 
   
5、当put新key值相同,value值不同的时候,hashmap中entry会将,会将新的值付给原来key中的value,
       put方法有返回值,出现value值替换的时候会返回原来的值,其他情况返回的是 null
  public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key);
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
} modCount++;
addEntry(hash, key, value, i);
return null;
}
6、对比的话,不是线程安全
  hashtable,hashmap对比主要是线程安全问题;hashtable的方法中很多都有synchronized的同步设置;
  LinkedHashMap 是HashMap的一个子类,保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.也可以在构造时用带参数,按照应用次数排序。
  LinkedHashMap在遍历的时候会比HashMap慢,
  LinkedHashMapkey可以是null,只是重写init 以及get的方法
 
7、有containkey containvalue 方法
 
8、hashmap遍历的方法有什么?
  hashmap实现map接口,所以就可以使用keyset,entrySet(),values(),以及Iterator<Map.Entry<String, String>> it = map.entrySet().iterator(); (map实现的iterator接口实现遍历)
 
 
 
 

java基础,集合,HashMap,源码解析的更多相关文章

  1. 一、基础篇--1.2Java集合-HashMap源码解析

    https://www.cnblogs.com/chengxiao/p/6059914.html  散列表 哈希表是根据关键码值而直接进行访问的数据结构.也就是说,它能通过把关键码值映射到表中的一个位 ...

  2. java集合-HashMap源码解析

    HashMap 键值对集合 实现原理: HashMap 是基于数组 + 链表实现的. 通过hash值计算 数组索引,将键值对存到该数组中. 如果多个元素hash值相同,通过链表关联,再头部插入新添加的 ...

  3. Java中的容器(集合)之HashMap源码解析

    1.HashMap源码解析(JDK8) 基础原理: 对比上一篇<Java中的容器(集合)之ArrayList源码解析>而言,本篇只解析HashMap常用的核心方法的源码. HashMap是 ...

  4. 【转】Java HashMap 源码解析(好文章)

    ­ .fluid-width-video-wrapper { width: 100%; position: relative; padding: 0; } .fluid-width-video-wra ...

  5. HashMap源码解析 非原创

    Stack过时的类,使用Deque重新实现. HashCode和equals的关系 HashCode为hash码,用于散列数组中的存储时HashMap进行散列映射. equals方法适用于比较两个对象 ...

  6. 最全的HashMap源码解析!

    HashMap源码解析 HashMap采用键值对形式的存储结构,每个key对应唯一的value,查询和修改的速度很快,能到到O(1)的平均复杂度.他是非线程安全的,且不能保证元素的存储顺序. 他的关系 ...

  7. HashMap源码解析和设计解读

    HashMap源码解析 ​ 想要理解HashMap底层数据的存储形式,底层原理,最好的形式就是读它的源码,但是说实话,源码的注释说明全是英文,英文不是非常好的朋友读起来真的非常吃力,我基本上看了差不多 ...

  8. 详解HashMap源码解析(下)

    上文详解HashMap源码解析(上)介绍了HashMap整体介绍了一下数据结构,主要属性字段,获取数组的索引下标,以及几个构造方法.本文重点讲解元素的添加.查找.扩容等主要方法. 添加元素 put(K ...

  9. Java HashSet和HashMap源码剖析

    转自: Java HashSet和HashMap源码剖析 总体介绍 之所以把HashSet和HashMap放在一起讲解,是因为二者在Java里有着相同的实现,前者仅仅是对后者做了一层包装,也就是说Ha ...

  10. 死磕Java之聊聊HashMap源码(基于JDK1.8)

    死磕Java之聊聊HashMap源码(基于JDK1.8) http://cmsblogs.com/?p=4731 为什么面试要问hashmap 的原理

随机推荐

  1. Windows和Linux环境下搭建SVN服务器

    --------------------------Windows下搭建SVN服务器----------------------------- 一.安装SVN服务端 软件包Setup-Subversi ...

  2. The literal of int xxxxx is out of range

    有时候我们定义了long型的变量,当我们给该变量赋值过长的整数时,系统依旧会提示长度超过范围,解决的方法例如以下: long timeShow = 1437565243495L; 我们须要在整形变量的 ...

  3. dma_alloc_coherent (建立一致性 DMA 映射函数)

    1.函数申明 /** * dma_alloc_coherent - allocate consistent memory for DMA * @dev: valid struct device poi ...

  4. 后台程序处理 (一)python asyncio 协程使用

    由于脚本需要在完成事件处理后N秒检查事件处理结果,当执行失败时再执行另一个事件处理. 想要最小化完成这个功能.同时在第一时间就将执行完毕的结果反馈给接口. 因此想到使用协程. 使用之前先翻阅了一下现有 ...

  5. maven project module 依赖项目创建 ---转

    一.创建Maven Project 1.右击 --> New --> Other,--> Maven --> Maven Project --> Next 2.如下图,选 ...

  6. JavaScript中函数function fun(){}和 var fun=function(){}的区别

    function fun(){} 和 var fun=function(){}的区别 标题有点长···· 废话少说,其实他们的主要区别就是"函数声明的提前行为". var fun= ...

  7. iOS: FFmpeg编译和使用 学习

    ffmpeg是一个多平台多媒体处理工具,处理视频和音频的功能非常强大.目前在网上搜到的iOS上使用FFMPEG的资料都比较陈旧,而FFMPEG更新迭代比较快: 且网上的讲解不够详细,对于初次接触FFM ...

  8. Visual Studio Code 通过 Chrome插件Type Script断点调试Angular 2

    1. 下载Visual Studio Code (https://code.visualstudio.com/) 2. 安装插件Debugger for chrome 3. 确定tsconfig.js ...

  9. Linux 运行级别

    本文同时发表在https://github.com/zhangyachen/zhangyachen.github.io/issues/47 运行级别 不同运行级别的描述 运行级别0:系统停机状态,系统 ...

  10. Xamarin Android Fragment的两种加载方式

    android Fragment的重点: 3.0版本后引入,即minSdk要大于11 Fragment需要嵌套在Activity中使用,当然也可以嵌套到另外一个Fragment中,但这个被嵌套的Fra ...