欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java之HashMap案例詳解

 更新時(shí)間:2021年08月10日 16:44:04   作者:Real_man  
這篇文章主要介紹了Java之HashMap案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下

概述

這篇文章,我們打算探索一下Java集合(Collections)框架中Map接口中HashMap的實(shí)現(xiàn)。Map雖然是Collctions框架的一部分,但是Map并沒(méi)有實(shí)現(xiàn)Collection接口,而Set和List是實(shí)現(xiàn)Collection接口的。

簡(jiǎn)單來(lái)說(shuō),HashMap主要通過(guò)key存儲(chǔ)value值,并且提供了添加,獲取和操作存儲(chǔ)value的方法。HashMap的實(shí)現(xiàn)基于HashTable。


HashMap內(nèi)部呈現(xiàn)

Key-value對(duì)在內(nèi)部是以buckets的方式存儲(chǔ)在一起,最終成為一個(gè)表。存儲(chǔ)和檢索操作的時(shí)間是固定的,也就是時(shí)間復(fù)雜度為O(1)。

這篇文章暫時(shí)不過(guò)于涉及HashMap的底層,我們先對(duì)HashMap有個(gè)整體認(rèn)知。

put方法

Map中通過(guò)put方法來(lái)存儲(chǔ)一個(gè)value。

    /**
     * 建立鍵值對(duì)應(yīng)關(guān)系,如果之前已經(jīng)存在對(duì)應(yīng)的key,
     * 返回之前存儲(chǔ)的value,之前如果不存在對(duì)應(yīng)的key,返回null
     */
    public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }

知識(shí)點(diǎn)一: 當(dāng)Map的調(diào)用put方法的時(shí)候,key對(duì)象被調(diào)用hashCode()方法,獲得一個(gè)hash值供hashmap使用。
我們創(chuàng)建一個(gè)對(duì)象來(lái)證實(shí)一下。

public class MyKey {
    private int id;
    
    @Override
    public int hashCode() {
        System.out.println("調(diào)用 hashCode()");
        return id;
    }

    // constructor, setters and getters 
}

   @Test
    public void mapKeyTest(){
        HashMap<MyKey,String> map = new HashMap<MyKey, String>();
        String retV = map.put(new MyKey(1),"value1");
    }

可以看到控制臺(tái)的輸出信息

調(diào)用 hashCode()

知識(shí)點(diǎn)二: hash()方法計(jì)算出的hash值可以標(biāo)識(shí)它在buckets數(shù)組中的索引位置。

HashMap的hash()方法如下:可以與put方法進(jìn)行關(guān)聯(lián)。

static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

HashMap有一個(gè)特點(diǎn),它可以存儲(chǔ)null的key和null的value。當(dāng)key時(shí)null的時(shí)候,執(zhí)行put方法,它會(huì)自動(dòng)分配hash為0. 這也意味著key為null的時(shí)候沒(méi)有hash操作,這樣就避免了空指針異常。

get() 方法

為了獲取存儲(chǔ)在hashMap中的對(duì)象,我們需要知道與它對(duì)應(yīng)的key。然后通過(guò)get方法把對(duì)應(yīng)的key傳到參數(shù)里。調(diào)用HashMap的get方法的時(shí)候,也會(huì)調(diào)用key對(duì)象的hashCode方法。

    @Test
    public void mapKeyTest(){
        HashMap<MyKey,String> map = new HashMap<MyKey, String>();
        MyKey key1 = new MyKey(1);
        map.put(key1,"value1");
        String retV =  map.get(key1);
    }

控制臺(tái)上可以看到兩行輸出

調(diào)用 hashCode()
調(diào)用 hashCode()

HashMap中的集合視圖

HashMap提供了三種方式,讓我們可以把key和value作為其它集合來(lái)使用。

Set<K> keys = map.keySet()
Collection<V> values = map.values()
Set<Entry<K, V>> entries = map.entrySet();

注意: 在iteators創(chuàng)建完畢后,對(duì)map的任何結(jié)構(gòu)修改,都會(huì)拋出一個(gè)異常。

@Test
public void givenIterator_whenFailsFastOnModification_thenCorrect() {
    Map<String, String> map = new HashMap<>();
    map.put("name", "baeldung");
    map.put("type", "blog");
 
    Set<String> keys = map.keySet();
    Iterator<String> it = keys.iterator();
    map.remove("type");
    while (it.hasNext()) {
        String key = it.next();
    }
}

// 會(huì)拋出java.util.ConcurrentModificationException異常

HashMap中唯一允許的修改是在iterator中移除元素。

public void givenIterator_whenRemoveWorks_thenCorrect() {
    Map<String, String> map = new HashMap<>();
    map.put("name", "baeldung");
    map.put("type", "blog");
 
    Set<String> keys = map.keySet();
    Iterator<String> it = keys.iterator();
 
    while (it.hasNext()) {
        it.next();
        it.remove();
    }
 
    assertEquals(0, map.size());
}

HashMap在iterator上的性能相比于LinkedHashMap和treeMap,性能非常糟糕。最差情況下為O(n),n為hashmap中條目的個(gè)數(shù)。

HashMap性能

HashMap的性能主要有兩個(gè)參數(shù)影響,初始容量和負(fù)載因子。初始容量為Map底層桶數(shù)組的長(zhǎng)度,負(fù)載因子為當(dāng)桶容量的長(zhǎng)度為多大的時(shí)候,重新開(kāi)辟新的空間。

    int threshold;
    final float loadFactor;

默認(rèn)的初始容量為16,默認(rèn)的負(fù)載因子為0.75. 我們也可以自定義它們的值。

Map<String,String> hashMapWithCapacity=new HashMap<>(32);
Map<String,String> hashMapWithCapacityAndLF=new HashMap<>(32, 0.5f);

初始容量:

大的初始容量用于條目數(shù)較多,但是少量迭代(iteration)
小的初始容量用于條目數(shù)較少,但是多次迭代(iteration)

負(fù)載因子:
0.75是一個(gè)很折衷的方案了。在我們初始化HashMap的時(shí)候,初始容量和負(fù)載因子都應(yīng)該考慮在內(nèi),比如為了減少重新hash的操作,初始容量乘以負(fù)載因子應(yīng)該大于能存儲(chǔ)的最大條目數(shù),這樣就不會(huì)發(fā)生重新hash的操作。

最后

HashMap內(nèi)部有很多東西值得探索,這篇僅僅對(duì)HashMap做了一層表面的分析。接下來(lái)會(huì)深入分析。

到此這篇關(guān)于Java之HashMap案例詳解的文章就介紹到這了,更多相關(guān)Java之HashMap內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java編程用棧來(lái)求解漢諾塔問(wèn)題的代碼實(shí)例(非遞歸)

    Java編程用棧來(lái)求解漢諾塔問(wèn)題的代碼實(shí)例(非遞歸)

    這篇文章主要介紹了Java編程用棧來(lái)求解漢諾塔問(wèn)題的代碼實(shí)例(非遞歸),具有一定參考價(jià)值,這里給大家分享下,供朋友們參考。
    2017-10-10
  • Mybatis映射文件實(shí)例詳解

    Mybatis映射文件實(shí)例詳解

    這篇文章主要介紹了 Mybatis映射文件實(shí)例詳解,需要的朋友可以參考下
    2017-02-02
  • 詳解java動(dòng)態(tài)代理的2種實(shí)現(xiàn)方式

    詳解java動(dòng)態(tài)代理的2種實(shí)現(xiàn)方式

    目前Java開(kāi)發(fā)包中包含了對(duì)動(dòng)態(tài)代理的支持,但是其實(shí)現(xiàn)只支持對(duì)接口的的實(shí)現(xiàn)。這篇文章主要介紹了詳解java動(dòng)態(tài)代理的2種實(shí)現(xiàn)方式 ,有興趣的可以了解一下。
    2016-11-11
  • Mybatis通過(guò)攔截器實(shí)現(xiàn)單數(shù)據(jù)源內(nèi)多數(shù)據(jù)庫(kù)切換

    Mybatis通過(guò)攔截器實(shí)現(xiàn)單數(shù)據(jù)源內(nèi)多數(shù)據(jù)庫(kù)切換

    這篇文章主要為大家詳細(xì)介紹了Mybatis如何通過(guò)攔截器實(shí)現(xiàn)單數(shù)據(jù)源內(nèi)多數(shù)據(jù)庫(kù)切換,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-12-12
  • Java如何跳過(guò)https的ssl證書驗(yàn)證詳解

    Java如何跳過(guò)https的ssl證書驗(yàn)證詳解

    這篇文章主要介紹了Java跳過(guò)https的ssl證書驗(yàn)證的解決思路,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,下面我們來(lái)深入學(xué)習(xí)下吧
    2019-06-06
  • 新手初學(xué)Java網(wǎng)絡(luò)編程

    新手初學(xué)Java網(wǎng)絡(luò)編程

    網(wǎng)絡(luò)編程是指編寫運(yùn)行在多個(gè)設(shè)備(計(jì)算機(jī))的程序,這些設(shè)備都通過(guò)網(wǎng)絡(luò)連接起來(lái)。本文介紹了一些網(wǎng)絡(luò)編程基礎(chǔ)的概念,并用Java來(lái)實(shí)現(xiàn)TCP和UDP的Socket的編程,來(lái)讓讀者更好的了解其原理
    2021-07-07
  • Java 將PPT幻燈片轉(zhuǎn)為HTML文件的實(shí)現(xiàn)思路

    Java 將PPT幻燈片轉(zhuǎn)為HTML文件的實(shí)現(xiàn)思路

    本文以Java程序代碼為例展示如何通過(guò)格式轉(zhuǎn)換的方式將PPT幻燈片文檔轉(zhuǎn)為HTML文件,本文通過(guò)實(shí)例代碼圖文相結(jié)合給大家分享實(shí)現(xiàn)思路,需要的朋友參考下吧
    2021-06-06
  • java如何創(chuàng)建一個(gè)jdbc程序詳解

    java如何創(chuàng)建一個(gè)jdbc程序詳解

    使用Java程序來(lái)操作數(shù)據(jù)庫(kù),后者更加直接的話就是使用Java程序來(lái)發(fā)送SQL語(yǔ)句的技術(shù)稱之為:JDBC。下面這篇文章主要給大家介紹了關(guān)于利用java如何創(chuàng)建一個(gè)jdbc程序的相關(guān)資料,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。
    2017-11-11
  • 詳解Spring簡(jiǎn)單容器中的Bean基本加載過(guò)程

    詳解Spring簡(jiǎn)單容器中的Bean基本加載過(guò)程

    本篇將對(duì)定義在 XMl 文件中的 bean,從靜態(tài)的的定義到變成可以使用的對(duì)象的過(guò)程,即 bean 的加載和獲取的過(guò)程進(jìn)行一個(gè)整體的了解
    2017-05-05
  • Java使用抽象工廠模式實(shí)現(xiàn)的肯德基消費(fèi)案例詳解

    Java使用抽象工廠模式實(shí)現(xiàn)的肯德基消費(fèi)案例詳解

    這篇文章主要介紹了Java使用抽象工廠模式實(shí)現(xiàn)的肯德基消費(fèi)案例,較為詳細(xì)的分析了抽象工廠模式的定義、原理并結(jié)合實(shí)例形式分析了Java使用抽象工廠模式實(shí)現(xiàn)肯德基消費(fèi)案例的步驟與相關(guān)操作技巧,需要的朋友可以參考下
    2018-05-05

最新評(píng)論