如果需要使用的Map中的key无序,选择HashMap;如果要求key有序,则选择TreeMap。

但是选择TreeMap就会有性能问题,因为TreeMap的get操作的时间复杂度是O(log(n))的,

相比于HashMap的O(1)还是差不少的,LinkedHashMap的出现就是为了平衡这些因素,使得

能够以O(1)时间复杂度增加查找元素,又能够保证key的有序性

此外,LinkedHashMap提供了两种key的顺序:

    • 访问顺序(access order)。非常实用,可以使用这种顺序实现LRU(Least Recently Used)缓存
    • 插入顺序(insertion orde)。同一key的多次插入,并不会影响其顺序

一。HashMap

1.HashMap构造函数

public HashMap(int initialCapacity, float loadFactor) {
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity);
if (initialCapacity > MAXIMUM_CAPACITY)
initialCapacity = MAXIMUM_CAPACITY;
if (loadFactor <= 0 || Float.isNaN(loadFactor))
throw new IllegalArgumentException("Illegal load factor: " + loadFactor);
this.loadFactor = loadFactor;
threshold = initialCapacity;
init(); //注意这个模板函数,在LinkHashMap中有使用
}

2.默认参数

//容量必须为2的指数(默认为16),想想原因?
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; static final int MAXIMUM_CAPACITY = 1 << 30; //默认的平衡因子为0.75,这是权衡了时间复杂度与空间复杂度之后的取值
//过高的因子可以增加存储空间利用率但是查找的时间就会增加。
static final float DEFAULT_LOAD_FACTOR = 0.75f;

3.重设索引

    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];
transfer(newTable, initHashSeedAsNeeded(newCapacity));
table = newTable;
threshold = (int)Math.min(newCapacity * loadFactor, MAXIMUM_CAPACITY + 1);
} /**
* Transfers all entries from current table to newTable.
*/
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;
}
}
}

4.

    static int indexFor(int h, int length) {
// assert Integer.bitCount(length) == 1 : "length must be a non-zero power of 2";
return h & (length-1);
}

二。LinkedHashMap

1.Entry

    private static class Entry<K,V> extends HashMap.Entry<K,V> {
// These fields comprise the doubly linked list used for iteration.
Entry<K,V> before, after; Entry(int hash, K key, V value, HashMap.Entry<K,V> next) {
super(hash, key, value, next);
}
}

2.删除

   //删除一个节点时,需要把
//1. 前继节点的后继指针 指向 要删除节点的后继节点
//2. 后继节点的前继指针 指向 要删除节点的前继节点
private void remove() {
before.after = after;
after.before = before;
}

3.增加

        private void addBefore(Entry<K,V> existingEntry) {
after = existingEntry; //当前节点的后继节点 指向 新节点
before = existingEntry.before; //
before.after = this; //
after.before = this; //
}

4.重写的init

    @Override
void init() {
header = new Entry<>(-1, null, null, null);
header.before = header.after = header;
}

5.重写transfer

    /**
* Transfers all entries to new table array. This method is called
* by superclass resize. It is overridden for performance, as it is
* faster to iterate using our linked list.
*/
@Override
void transfer(HashMap.Entry[] newTable, boolean rehash) {
int newCapacity = newTable.length;
for (Entry<K,V> e = header.after; e != header; e = e.after) { //把链表里的元素重排序
if (rehash)
e.hash = (e.key == null) ? 0 : hash(e.key);
int index = indexFor(e.hash, newCapacity);
e.next = newTable[index];
newTable[index] = e;
}
}

Java HashMap、LinkedHashMap的更多相关文章

  1. [Java] HashMap、TreeMap、Hashtable排序

    Java中对Map(HashMap,TreeMap,Hashtable等)的排序时间 首先简单说一下他们之间的区别: HashMap: 最常用的Map,它根据键的HashCode 值存储数据,根据键可 ...

  2. HashMap、LinkedHashMap、ConcurrentHashMap、ArrayList、LinkedList 底层实现

    HashMap相关问题 1.你用过HashMap吗?什么是HashMap?你为什么用到它? 用过,HashMap是基于哈希表的Map接口的非同步实现,它允许null键和null值,且HashMap依托 ...

  3. HashMap、LinkedHashMap和TreeMap对比

    共同点: HashMap,LinkedHashMap,TreeMap都属于Map:Map 主要用于存储键(key)值(value)对,根据键得到值,因此键不允许键重复,但允许值重复. 不同点: 1.H ...

  4. HashMap 、LinkedHashMap、HashTable、TreeMap 和 Properties 的区别

    HashMap 1.线程不安全: 2.允许null value 和 null key: 3.访问效率比较高: 4.Java1.2引进的Map接口的一个实现: 5.轻量级: 6.根据键的HashCode ...

  5. java HashMap和LinkedHashMap区别

    我们用的最多的是HashMap,在Map 中插入.删除和定位元素,HashMap 是最好的选择.但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好.如果需要输出的顺序和输入的相同,那么用 ...

  6. 对比分析HashMap、LinkedHashMap、TreeMap

    HashMap的原理 :简单地说,HashMap 在底层将 key-value 当成一个整体进行处理,这个整体就是一个 Entry 对象.HashMap 底层采用一个 Entry[] 数组来保存所有的 ...

  7. Java HashMap、HashTable与ConCurrentHashMap

    一.Java中数据存储方式最底层的两种结构 1.数组:存储空间连续,寻址迅速,增删较慢.(代表:ArrayList) 2.链表:存储空间不连续,寻址慢,增删较快.(代表:LinkedList) 二.哈 ...

  8. HashTable、HashMap、LinkedHashMap、TreeMap的比较

    HashTable:继承自Dictionary类,实现了Map接口,不允许键或值为空,线程同步: HashMap:继承自AbstractMap类,实现了Map接口,允许键或值为空,线程不同步: Lin ...

  9. Java HashMap、HashTable、TreeMap、WeakHashMap区别

    1.HashMap不是线程安全,而HashTable是线程安全

随机推荐

  1. HealthKit开发教程之HealthKit的复合数据

    HealthKit开发教程之HealthKit的复合数据 复合数据就是复合单位和值构成的数据.所谓复合单位就是由单位进行乘法.除法等得到的单位,如m/s.lb·ft等就是复合单位.本节将针对这些复合数 ...

  2. git将本地仓库上传到远程仓库

    在已有的Git库中搭建新库,并且将本地的git仓库,上传到远程服务器的git库中,从而开始一个新的项目 首先,在本地新建文件夹abc,进入到abc里面,然后git init.这样就在本地初始化了一个g ...

  3. ural 1286. Starship Travel

    1286. Starship Travel Time limit: 1.0 secondMemory limit: 64 MB It is well known that a starship equ ...

  4. [Unity2D]GameObject游戏对象的灵活运用

    Unity2D的游戏可以说是由一堆GameObject构成的,GameObject的使用非常灵活,不仅仅是给单个精灵使用,你可以发挥你一切的想象力来利用它来解决一些实际上的问题.比如: 1.给一个精灵 ...

  5. 【wikioi】1217 借教室

    题目链接http://www.wikioi.com/problem/1217/ 算法:二分答案(线段树可过wikioi数据) 二分:http://www.wikioi.com/solution/lis ...

  6. linux下安装7z命令及7z命令的使用

    本文主要介绍了在linux下安装7z命令的方法,同时介绍了7z命令的使用.7z压缩格式拥有众多优点,具有极高的压缩比率,如果你还不了解,请看文章:7z格式.LZMA压缩算法和7-Zip详细介绍. re ...

  7. 【C语言】15-预处理指令1-宏定义

    预处理指令简介 1.C语言在对源程序进行编译之前,会先对一些特殊的预处理指令作解释(比如之前使用的#include文件包含指令),产生一个新的源程序(这个过程称为编译预处理),之后再进行通常的编译 2 ...

  8. python的几个常用内置函数

    dir()查看属性(函数和数据对象) help()查看具体的帮助文档 id() 用来查看数据对象的地址 split 分隔(str ---> list): >>> s=" ...

  9. html5文章 -- 应用HTML5 开发手机APP

    因为HTML5暂时无法短期内在PC普及,主要方向在使用高端浏览器的高端移动设备,所以可以用作开发Android系统的App.但只有Android2.2以上.iOS3.2以上均支持HTML5,两大平台有 ...

  10. sql 语句大小写的问题

    关键字不区分大小写 例如 select ,from, 大小写均可 标识符区分大小写 例如 表名,列名 标识符如果不加双引号,默认是按大写执行 标识符如果加双引号,则是按原始大小写执行 但是,当表名加上 ...