浅读java.util.Map及其实现类(二)

时间:2021-08-27 16:21:39

Map已知实现类概述


本文概述以下Map实现类,其中ConcurrentHashMap请转步到  浅读java.util.Map及其实现类(三)
AbstractMap
Attributes
AuthProvider
ConcurrentHashMap
ConcurrentSkipListMap
EnumMap
HashMap
Hashtable
IdentityHashMap
LinkedHashMap
PrinterStateReasons
Properties

AbstractMap

标签:抽象Map
概述:一个实现map的抽象类,提供各类一些基础的实现
以下类都是他的子类
ConcurrentHashMap /  ConcurrentSkipListMap /  EnumMap /  HashMap /  IdentityHashMap /  TreeMap /  WeakHashMap 
从AbstractMap源码中可以看到put及AbstractMap.SimpleImmutableEntry中setValue(V value)是不支持的method我们需要自己来实现这部分功能
entrySet是需要自己实现的,其中TreeMap等都对他进行了实现

Attributes

标签:MANIFEST.MF读取 非线程安全
概述: 用来读取jar中MANIFEST.MF的文件,UTF-8输出编码
public static void main(String[] args) {
String s = "e:\\commons-dbcp-1.3.jar";
JarInputStream ji = null;
try {
//jarInputStream与attributes都是在java.util.jar包
ji = new JarInputStream(new FileInputStream(s));
Manifest mf = ji.getManifest();
mf.getMainAttributes().forEach((k, v) -> System.out.println("[ k:" + k + "/" + "v:" + v + " ]"));
} catch (Exception e) {
e.printStackTrace();
} finally {
if (ji != null)
try {
ji.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
[ k:Bundle-License/v:http://www.apache.org/licenses/LICENSE-2.0.txt ][ k:Bundle-SymbolicName/v:org.apache.commons.dbcp ][ k:Archiver-Version/v:Plexus Archiver ][ k:Built-By/v:philsteitz ][ k:Bnd-LastModified/v:1265564429985 ][ k:Implementation-Vendor-Id/v:org.apache ][ k:Specification-Title/v:Commons DBCP ][ k:Bundle-DocURL/v:http://commons.apache.org/dbcp/ ][ k:Import-Package/v:javax.naming,javax.naming.spi,javax.sql,javax.transaction,javax.transaction.xa,org.apache.commons.dbcp;version="1.3",org.apache.commons.dbcp.cpdsadapter;version="1.3",org.apache.commons.dbcp.datasources;version="1.3",org.apache.commons.dbcp.managed;version="1.3",org.apache.commons.jocl;version="1.3",org.apache.commons.pool,org.apache.commons.pool.impl,org.xml.sax,org.xml.sax.helpers ][ k:Export-Package/v:org.apache.commons.jocl;version="1.3",org.apache.commons.dbcp.datasources;version="1.3",org.apache.commons.dbcp.cpdsadapter;version="1.3",org.apache.commons.dbcp.managed;version="1.3",org.apache.commons.dbcp;version="1.3" ][ k:Bundle-Name/v:Commons DBCP ][ k:Implementation-Title/v:Commons DBCP ][ k:Bundle-Description/v:Commons Database Connection Pooling ][ k:Implementation-Version/v:1.3 ][ k:Specification-Vendor/v:The Apache Software Foundation ][ k:Bundle-ManifestVersion/v:2 ][ k:Bundle-Vendor/v:The Apache Software Foundation ][ k:Tool/v:Bnd-0.0.238 ][ k:Manifest-Version/v:1.0 ][ k:Implementation-Vendor/v:The Apache Software Foundation ][ k:Bundle-Version/v:1.3 ][ k:X-Compile-Target-JDK/v:1.4 ][ k:X-Compile-Source-JDK/v:1.4 ][ k:Created-By/v:1.5.0_19 (Apple Inc.) ][ k:Build-Jdk/v:1.5.0_19 ][ k:Specification-Version/v:1.3 ]

AuthProvider

标签:java.security.*

概述:JAAS相关内容,提供了3个抽象方法。login logout  setCallbackHandler


ConcurrentHashMap

标签:高并发 线程安全 CAS node
请参见浅读java.util.Map及其实现类(三)ConcurrentHashMap专题: http://blog.csdn.net/crazyzxljing0621/article/details/73733559

ConcurrentSkipListMap

标签:Tree 跳表 SkipList  线程安全 高并发
概述:跳表机制提供了更高效的有序列表查询
SkipList:给予有序列表下高效的操作
例:
         3,4,5,6,78,9,10
想要查询5,9需要 3+7 ,一共10次比较操作
SkipList建立了Index Level
L3 3------------------>7----------->10
L2  3------->5------->7----------->10
L1  3-> 4-> 5-> 6-> 7-> 8-> 9-> 10
=============================
0.L3
1.3<5,3记录下一个是7,7>5
2.L2
3.3记录下一个是5,5==5,找到5了 
find : 以此类推跳表的方式查询更加迅速当然表越大效果越明显可以有若干个Level
add:每一个rand levelN 在level 1 ~ levelN中插入自己,如果新值超过最大值,则在levelMax+1中插入自己
del:找到目标,然后依次按层删除

EnumMap

标签:枚举map 非线程安全
概述:处理EnumKey的性能更高,内部使用数组存储
例:
public static void main(String[] args) {

EnumMap<State,String> e = new EnumMap<State,String>(State.class);
System.out.println(e.put(State.NPE, "11"));
System.out.println(e.put(State.NPE, "22"));
for (Map.Entry<State, String> entry : e.entrySet()) {
System.out.println(entry.getValue() + " " + entry.getKey().str());
}
System.out.println();
}

public enum State {

NOTFOUND("404", "404"), SERVERERROR("500", "500"),
SUCCESS("100", "成功"), NPE("101", "空指针"),
EXCEPTION("102","异常"), IPPERMISSIONS("103", "IP访问权限不足"),
VERSIONERROR("104", "版本错误"),
DOMAINNOTFOUND("105", "域不存在"), ;

private String value;
private String str;

private State(String value, String str) {
this.value = value;
this.str = str;
}

public String value() {
return this.value;
}

public String str() {
return this.str;
}
}
源码
  public EnumMap(Class<K> keyType) {
this.keyType = keyType;
keyUniverse = getKeyUniverse(keyType);//将枚举Key返回为key[]
vals = new Object[keyUniverse.length]; //初始化一个vals
}
 public V put(K key, V value) {
        typeCheck(key); //key类型要匹配Class<K>
        int index = key.ordinal(); //得到Key的下标 Enum.ordinal();其实就是在你的Enum中的定义顺序
        Object oldValue = vals[index];
        vals[index] = maskNull(value);
//如果值不存在则返回一个EnumMapObject // hasCode return 0 // toString return "java.util.EnumMap.NULL"
        if (oldValue == null)
            size++; //oldValue不存在计数器+1,代表是新增而不是覆盖
        return unmaskNull(oldValue);//新增返回null 覆盖返回 旧值
    }
  public V get(Object key) {
        return (isValidKey(key) ?
                unmaskNull(vals[((Enum<?>)key).ordinal()]) : null);
//key类型正确则以key下标去vals取值,空则返回
    }


HashMap

标签:非线程安全 
概述:hashMap是最长用的Map实现类之一,他是哈希分布
源码:
 public HashMap(int initialCapacity, float loadFactor) {  
//容量和加载因子,容量不说了,因子越小map利用率越高,冲突概率就高,反之越稀松,冲突概率越低
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal initial capacity: " +
initialCapacity);
if (initialCapacity > MAXIMUM_CAPACITY) //初始容量不能超过最大支持容量,最大容量1<<30
initialCapacity = MAXIMUM_CAPACITY;
if (loadFactor <= 0 || Float.isNaN(loadFactor)) //因子判断
throw new IllegalArgumentException("Illegal load factor:"+ loadFactor);
this.loadFactor = loadFactor; this.threshold = tableSizeFor(initialCapacity); //下一次调整大小的值
}

static class Node<K,V> implements Map.Entry<K,V> {        final int hash;        final K key;        V value;        Node<K,V> next;        Node(int hash, K key, V value, Node<K,V> next) {            this.hash = hash;            this.key = key;            this.value = value;            this.next = next;        }        public final K getKey()        { return key; }        public final V getValue()      { return value; }        public final String toString() { return key + "=" + value; }        public final int hashCode() {            return Objects.hashCode(key) ^ Objects.hashCode(value);        }        public final V setValue(V newValue) {            V oldValue = value;            value = newValue;            return oldValue;        }        public final boolean equals(Object o) {            if (o == this)                return true;            if (o instanceof Map.Entry) {                Map.Entry<?,?> e = (Map.Entry<?,?>)o;                if (Objects.equals(key, e.getKey()) &&                    Objects.equals(value, e.getValue()))                    return true;            }            return false;        }    }
链表散列存储: 一种数组+链表的存储结构,通过hash值计算,在合适的空间下平均分布数据存储,每一条数据都是一个Entry
Hash数据结构
----------------------------------------------------------------------------------------------------------------
数组->  位置1  位置2  位置3  位置4  位置5   位置6  位置7  位置8  位置9  位置10

数据->   "小明"    null    null    "小华"   "小龙"   null     null      null     null       null
               "小黑"
                    ↑
                 链表(产生哈希冲突,链表存储)
-----------------------------------------------------------------------------------------------------------------
当数据put进hashmap时,会先计算其hash值
    static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
哈希冲突:
找到指定的hash数组位置,如果位置上没有其他数据则直接插入,如果有其他数据则以链表方式并插到首位
这就是遇到了哈希冲突的链表法,还有一种开放地址法通过算法继续寻找可用位置

Hashtable

标签:线程安全 稳定 
概述:线程安全不允许空值,几乎所有方法都是synchronized修饰
扩展:Hashtable ConcurrentHashMap相比下后者支持高并发更高效
    Hashtable Collections.synchronizedMap(Map<K,V>)后者是在参数Map的所有方法上加了个sync并返回,个人建议还是尽可能用Hashtable

IdentityHashMap

标签:没有equals Key可以重复
概述:此Map没有equals,只有k1==k2所以我们可以做出2个相等的key
例:
	public static void main(String[] args) { 

IdentityHashMap<String, Integer> map=new IdentityHashMap<String, Integer>();
String a=new String("天");
map.put(a, 1);
map.put(new String("天"), 2);
map.put(new String("天"), 3);
map.put(new String("王"), 4);
System.out.println(map.toString());
System.out.println(map.get(a));
}

LinkedHashMap

标签:有序 非线程安全
概述:有序的HashMap,允许null key,null value。双向循环链表包含头结点
源码
 static class Entry<K,V> extends HashMap.Node<K,V> {
Entry<K,V> before, after; //继承HashMap.Node并定义了before after来完成双向循环链表
Entry(int hash, K key, V value, Node<K,V> next) {
super(hash, key, value, next);
}
}
其他地方与HashMap基本一致,只是增加了before,after并对相关函数重写已遍生效有序

PrinterStateReasons

标签: 打印机 非线程安全 HashMap派生类
概述:获取打印机相关信息数据
public static void main(String[] args) {
PrintService myPrint = PrintServiceLookup.lookupDefaultPrintService();
PrinterStateReasons printerStateReasons = myPrint.getAttribute(PrinterStateReasons.class);
System.out.println( printerStateReasons);
}

Properties

标签:属性 线程安全 Hashtable派生类
概述:读取java常用的*.properties格式文件
public static void main(String[] args) throws Exception {
Properties pro = new Properties();
try {
pro.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("conf-test.properties"));
System.out.println(pro.get("username"));
} catch (IOException e) {
}
}

总结

浅读第二章就到这里,下期继续