Java-Map源码分析及特性

Map架构:

如上图:

(1)Map是映射接口,Map中存储的内容是键值对(key-value)

(2)AbstractMap是继承于Map的抽象类,实现了Map中的大部分API。

(3)SortedMap是继承于Map的接口,SortedMap中的内容是排序的键值对,排序的方法是通过比较器。

(4)NavigableMap继承于SortedMap,其中有一系列的导航方法,如“获取大于或等于某对象的键值对”等等

(5)TreeMap继承于AbstractMap和NavigableMap接口,因此TreeMap中的内容是有序的键值对。

(6)HashMap继承于AbstractMap,内容也是键值对,但不保证次序。

(7)WeakHashMap继承于AbstractMap,它和HashMap的键类型不同,WeakHashMap是弱键。

(8)HashTable继承于Directionary同时也实现了Map,因此是键值对的,但不保证次序,同时是线程安全的。

总结:

HashMap是基于”拉链法“实现的散列表,一般用于单线程,键值都可以为空,支持Iterator(迭代器)遍历

Hashtable是基于”拉链法“实现的散列表,是线程安全的,可以用于多线程程序中。支持Iterator(迭代器)遍历和Enumeration(枚举器)两种遍历方式。

WeakHashMap也是基于”拉链法“实现的散列表,同时是弱键

TreeMap 是有序的散列表,通过红黑树来实现的,键值都不能为空。

Java8的Map接口的源码:

public interface Map<K,V> {int size();//数目boolean isEmpty();//判断是否为空boolean containsKey(Object key);//判断是否含有某个keyboolean containsValue(Object value);//判断是否含有某个值V get(Object key);//通过key获得valueV put(K key, V value);//插入键值对V remove(Object key);//通过key删除void putAll(Map<? extends K, ? extends V> m);//将一个Map插入void clear();//清空Set<K> keySet();//返回key集合Collection<V> values();//返回valueSet<Map.Entry<K, V>> entrySet();//实体集合,Map的改变会影响到它interface Entry<K,V> {K getKey();//获得keyV getValue();//获得valueV setValue(V value);//设置值boolean equals(Object o);//判断对象是否相等int hashCode();//返回hashCode        //比较器,比较两个keypublic static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K,V>> comparingByKey() {return (Comparator<Map.Entry<K, V>> & Serializable)                    (c1, c2) -> c1.getKey().compareTo(c2.getKey());}//比较两个值public static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K,V>> comparingByValue() {return (Comparator<Map.Entry<K, V>> & Serializable)                    (c1, c2) -> c1.getValue().compareTo(c2.getValue());}//比较两个keypublic static <K, V> Comparator<Map.Entry<K, V>> comparingByKey(Comparator<? super K> cmp) {            Objects.requireNonNull(cmp);            return (Comparator<Map.Entry<K, V>> & Serializable)                    (c1, c2) -> cmp.compare(c1.getKey(), c2.getKey());}//比较两个值public static <K, V> Comparator<Map.Entry<K, V>> comparingByValue(Comparator<? super V> cmp) {            Objects.requireNonNull(cmp);            return (Comparator<Map.Entry<K, V>> & Serializable)                    (c1, c2) -> cmp.compare(c1.getValue(), c2.getValue());}    }//比较map是否相等boolean equals(Object o);    int hashCode();//hashCodedefault V getOrDefault(Object key, V defaultValue) {V v;        return (((v = get(key)) != null) || containsKey(key))                ? v                : defaultValue;}default void forEach(BiConsumer<? super K, ? super V> action) {        Objects.requireNonNull(action);        for (Map.Entry<K, V> entry : entrySet()) {K k;V v;            try {                k = entry.getKey();v = entry.getValue();} catch(IllegalStateException ise) {// this usually means the entry is no longer in the map.throw new ConcurrentModificationException(ise);}            action.accept(k, v);}    }default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {        Objects.requireNonNull(function);        for (Map.Entry<K, V> entry : entrySet()) {K k;V v;            try {                k = entry.getKey();v = entry.getValue();} catch(IllegalStateException ise) {// this usually means the entry is no longer in the map.throw new ConcurrentModificationException(ise);}

// ise thrown from function is not a cme.v = function.apply(k, v);

try {                entry.setValue(v);} catch(IllegalStateException ise) {// this usually means the entry is no longer in the map.throw new ConcurrentModificationException(ise);}        }    }default V putIfAbsent(K key, V value) {V v = get(key);        if (v == null) {            v = put(key, value);}

return v;}//删除某个key和value对应的对象default boolean remove(Object key, Object value) {        Object curValue = get(key);        if (!Objects.equals(curValue, value) ||                (curValue == null && !containsKey(key))) {return false;}        remove(key);        return true;}//将某个key和oldValue对应的值替换为newValuedefault boolean replace(K key, V oldValue, V newValue) {        Object curValue = get(key);        if (!Objects.equals(curValue, oldValue) ||                (curValue == null && !containsKey(key))) {return false;}        put(key, newValue);        return true;}//替换key的值default V replace(K key, V value) {V curValue;        if (((curValue = get(key)) != null) || containsKey(key)) {            curValue = put(key, value);}return curValue;}default V computeIfAbsent(K key,Function<? super K, ? extends V> mappingFunction) {        Objects.requireNonNull(mappingFunction);V v;        if ((v = get(key)) == null) {V newValue;            if ((newValue = mappingFunction.apply(key)) != null) {                put(key, newValue);                return newValue;}        }

return v;}default V computeIfPresent(K key,BiFunction<? super K, ? super V, ? extends V> remappingFunction) {        Objects.requireNonNull(remappingFunction);V oldValue;        if ((oldValue = get(key)) != null) {V newValue = remappingFunction.apply(key, oldValue);            if (newValue != null) {                put(key, newValue);                return newValue;} else {                remove(key);                return null;}        } else {return null;}    }default V compute(K key,BiFunction<? super K, ? super V, ? extends V> remappingFunction) {        Objects.requireNonNull(remappingFunction);V oldValue = get(key);

V newValue = remappingFunction.apply(key, oldValue);        if (newValue == null) {// delete mappingif (oldValue != null || containsKey(key)) {// something to removeremove(key);                return null;} else {// nothing to do. Leave things as they were.return null;}        } else {// add or replace old mappingput(key, newValue);            return newValue;}    }default V merge(K key, V value,BiFunction<? super V, ? super V, ? extends V> remappingFunction) {        Objects.requireNonNull(remappingFunction);Objects.requireNonNull(value);V oldValue = get(key);V newValue = (oldValue == null) ? value :                remappingFunction.apply(oldValue, value);        if(newValue == null) {            remove(key);} else {            put(key, newValue);}return newValue;}}

版权声明:知识在于分享,技术在于交流,转载时请留一个博主的链接就好

时间: 2024-10-12 20:31:44

Java-Map源码分析及特性的相关文章

sync.Map源码分析

sync.Map源码分析 背景 众所周知,go普通的map是不支持并发的,换而言之,不是线程(goroutine)安全的.博主是从golang 1.4开始使用的,那时候map的并发读是没有支持,但是并发写会出现脏数据.golang 1.6之后,并发地读写会直接panic: fatal error: concurrent map read and map write package main func main() { m := make(map[int]int) go func() { for

JAVA Collection 源码分析(一)之ArrayList

到今天为止,差不多已经工作一年了,一直在做的是javaweb开发,一直用的是ssh(sh)别人写好的框架,总感觉自己现在高不成低不就的,所以就像看看java的源码,顺便学习一下大牛的思想和架构,read and write一直是提高自己编程水平的不二法门,写博客只是记录自己的学习历程,方便回顾,写的不好的地方,请多多包含,不喜勿喷,好了废话少说,现在让我们开始我们的历程把,Let's go!!!!!!!! 想看源码无从下手,不知道有没有跟我一样感觉的人们,今天用Intellij发现了可以找出类与

JAVA Collection 源码分析(二)之SubList

昨天我们分析了ArrayList的源码,我们可以看到,在其中还有一个类,名为SubList,其继承了AbstractList. // AbstractList类型的引用,所有继承了AbstractList都可以传进来 private final AbstractList<E> parent; // 这个是其实就是parent的偏移量,从parent中的第几个元素开始的 private final int parentOffset; private final int offset; int s

Java 集合源码分析(一)HashMap

目录 Java 集合源码分析(一)HashMap 1. 概要 2. JDK 7 的 HashMap 3. JDK 1.8 的 HashMap 4. Hashtable 5. JDK 1.7 的 ConcurrentHashMap 6. JDK 1.8 的 ConcurrentHashMap 7. 最后补充一下 HashMap 中的一些属性和方法 附:更这个系列感觉自己像是又挖了一个坑??,不过趁自己刚好工作不太忙,有空闲期,静下心来研究学习源码也是一件很值得做的事,自己尽量会把这个坑填完??.

超赞!推荐一个专注于Java后端源码分析的Github项目!

大家好,最近有小伙伴们建议我把源码分析文章及源码分析项目(带注释版)放到github上,这样小伙伴们就可以把带中文注释的源码项目下载到自己本地电脑,结合源码分析文章自己本地调试,总之对于学习开源项目源码会更方便. 因此下面提供[源码笔记]的Github地址,若您觉得不错,欢迎Star点亮哦: Github主页:https://github.com/yuanmabiji 源码分析文章:https://github.com/yuanmabiji/Java-SourceCode-Blogs Sprin

[Java] HashMap源码分析

1.概述 Hashmap继承于AbstractMap,实现了Map.Cloneable.java.io.Serializable接口.它的key.value都可以为null,映射不是有序的. Hashmap不是同步的,如果想要线程安全的HashMap,可以通过Collections类的静态方法synchronizedMap获得线程安全的HashMap. Map map = Collections.synchronizedMap(new HashMap()); (除了不同步和允许使用 null 之

Java Reference 源码分析

Reference对象封装了其它对象的引用,可以和普通的对象一样操作,在一定的限制条件下,支持和垃圾收集器的交互.即可以使用Reference对象来引用其它对象,但是最后还是会被垃圾收集器回收.程序有时候也需要在对象回收后被通知,以告知对象的可达性发生变更.  Java提供了四种不同类型的引用,引用级别从高到低分别为FinalReference,SoftReference,WeakReference,PhantomReference.其中FinalReference不对外提供使用.每种类型对应着

java HashMap源码分析(JDK8)

这两天在复习JAVA的知识点,想更深层次的了解一下JAVA,所以就看了看JAVA的源码,把自己的分析写在这里,也当做是笔记吧,方便记忆.写的不对的地方也请大家多多指教. JDK1.6中HashMap采用的是位桶+链表的方式,即我们常说的散列链表的方式,而JDK1.8中采用的是位桶+链表/红黑树的方式,也是非线程安全的.当某个位桶的链表的长度达到某个阀值的时候,这个链表就将转换成红黑树. 基本的数据结构: 1 //链表节点 2 static class Node<K,V> implements

Java - LinkedList源码分析

java提高篇(二二)---LinkedList 一.概述 LinkedList与ArrayList一样实现List接口,只是ArrayList是List接口的大小可变数组的实现,LinkedList是List接口链表的实现.基于链表实现的方式使得LinkedList在插入和删除时更优于ArrayList,而随机访问则比ArrayList逊色些. LinkedList实现所有可选的列表操作,并允许所有的元素包括null. 除了实现 List 接口外,LinkedList 类还为在列表的开头及结尾

Java - ArrayList源码分析

java提高篇(二一)-----ArrayList 一.ArrayList概述 ArrayList是实现List接口的动态数组,所谓动态就是它的大小是可变的.实现了所有可选列表操作,并允许包括 null 在内的所有元素.除了实现 List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小. 每个ArrayList实例都有一个容量,该容量是指用来存储列表元素的数组的大小.默认初始容量为10.随着ArrayList中元素的增加,它的容量也会不断的自动增长.在每次添加新的元素时,Array