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

Java中如何使用?byte?數(shù)組作為?Map?的?key

 更新時(shí)間:2023年06月07日 11:12:03   作者:萬貓學(xué)社  
本文將討論在使用HashMap時(shí),當(dāng)byte數(shù)組作為key時(shí)所遇到的問題及其解決方案,介紹使用String和List這兩種數(shù)據(jù)結(jié)構(gòu)作為臨時(shí)解決方案的方法,感興趣的朋友跟隨小編一起看看吧

本文將引領(lǐng)我們探索:如何將byte數(shù)組作為HashMap中鍵。HashMap的機(jī)制使我們無法直接這樣做。讓我們研究一下,為何出現(xiàn)此狀況,以及針對這種情況,幾種可供選擇的解決方案。

HashMap的工作原理

HashMap是一種使用哈希機(jī)制來存儲(chǔ)和檢索值的數(shù)據(jù)結(jié)構(gòu)。使用哈希碼來存儲(chǔ)和檢索值可以大大提高HashMap的性能,因?yàn)樗梢允共檎益I值對的時(shí)間復(fù)雜度保持在 O ( 1 ) O(1) O(1)的級別。當(dāng)然,這也要求我們在實(shí)現(xiàn)hashCode()方法時(shí)盡可能地讓哈希碼分布均勻,以免造成哈希沖突,從而影響HashMap的效率。

當(dāng)我們調(diào)用put(key, value)方法時(shí),HashMap會(huì)通過鍵的hashCode()方法計(jì)算哈希碼。這個(gè)哈希碼用于確定最終存儲(chǔ)值的桶:

public V get(Object key) {
    Node<K,V> e;
    return (e = getNode(hash(key), key)) == null ? null : e.value;
}

在使用get(key)方法檢索值時(shí),需要經(jīng)過一系列處理步驟:首先,會(huì)通過鍵計(jì)算哈希碼,然后找到哈希桶。接下來,使用equals()方法檢查桶中的每個(gè)條目是否與鍵相等。最終,返回匹配條目的值:

public V put(K key, V value) {
    return putVal(hash(key), key, value, false, true);
}

equalshashCode方法

在Java編程中,equals方法和hashCode方法都有應(yīng)該遵守的規(guī)則。在HashMap這個(gè)數(shù)據(jù)結(jié)構(gòu)中,有一個(gè)方面尤其重要:具有相同equals方法比較結(jié)果的對象,必須返回相同的哈希值。然而,反之則不一定成立,也就是說,具有相同哈希值的對象,并不一定具有相同的equals方法比較結(jié)果。這也是為什么我們可以將多個(gè)對象存儲(chǔ)在HashMap的同一個(gè)桶中的原因。

在使用HashMap時(shí),建議不要更改key的哈希值。雖然這不是強(qiáng)制性規(guī)定,但強(qiáng)烈建議將鍵定義為不可變對象。如果對象是不可變的,無論hashCode方法的實(shí)現(xiàn)如何,它的哈希值都不會(huì)被更改。

在默認(rèn)情況下,哈希值是基于對象的所有字段進(jìn)行計(jì)算的。如果我們需要使用可變的鍵,我們需要重寫hashCode方法,以確保它的計(jì)算不涉及可變字段。為了維護(hù)這一個(gè)規(guī)則,我們還需要修改equals方法。

使用 byte 數(shù)組作為key

為了能夠從映射中成功地檢索值,相等性必須是有意義的。這就是使用byte數(shù)組并不是一個(gè)真正的選擇的主要原因。在Java中,數(shù)組使用對象標(biāo)識來確定相等性。如果我們使用byte數(shù)組作為key創(chuàng)建HashMap,那么只有使用完全相同的數(shù)組對象才能檢索值。

讓我們使用byte數(shù)組作為key創(chuàng)建一個(gè)簡單的例子:

byte[] key1 = {1, 2, 3};
byte[] key2 = {1, 2, 3};
Map<byte[], String> map = new HashMap<>();
map.put(key1, "value1");
map.put(key2, "value2");
System.out.println(map.get(key1));
System.out.println(map.get(key2));
System.out.println(map.get(new byte[]{1, 2, 3}));

我們雖然有兩個(gè)相同的鍵,但是我們無法使用具有相同值的新創(chuàng)建的數(shù)組檢索到任何內(nèi)容,運(yùn)行結(jié)果如下:

value1
value2
null

解決方法

使用String

String的相等性基于字符數(shù)組的內(nèi)容:

public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

字符串也是不可變的,并且基于byte數(shù)組創(chuàng)建一個(gè)字符串非常簡單。我們可以使用Base64輕松編碼和解碼字符串,然后創(chuàng)建一個(gè)使用字符串作為key而不是byte數(shù)組的HashMap:

String key1 = Base64.getEncoder().encodeToString(new byte[]{1, 2, 3});
String key2 = Base64.getEncoder().encodeToString(new byte[]{1, 2, 3});
Map<String, String> map = new HashMap<>();
map.put(key1, "value1");
map.put(key2, "value2");
System.out.println(map.get(key1));
System.out.println(map.get(key2));
System.out.println(map.get(Base64.getEncoder().encodeToString(new byte[]{1, 2, 3})));

運(yùn)行結(jié)果如下:

value2
value2
value2

注意: 在byte數(shù)組轉(zhuǎn)化為String時(shí)會(huì)有性能損耗。因此,在大多數(shù)情況下,該解決方案并不推薦。

使用List

String類似,List#equals方法將檢查其每個(gè)元素的相等性:

public boolean equals(Object o) {
    if (o == this)
        return true;
    if (!(o instanceof List))
        return false;
    ListIterator<E> e1 = listIterator();
    ListIterator<?> e2 = ((List<?>) o).listIterator();
    while (e1.hasNext() && e2.hasNext()) {
        E o1 = e1.next();
        Object o2 = e2.next();
        if (!(o1==null ? o2==null : o1.equals(o2)))
            return false;
    }
    return !(e1.hasNext() || e2.hasNext());
}

如果這些元素具有合理的equals()方法并且是不可變的,則List將作為HashMap鍵正確工作。我們只需要確保使用不可變的List實(shí)現(xiàn):

List<Byte> key1 = ImmutableList.of((byte) 1, (byte) 2, (byte) 3);
List<Byte> key2 = ImmutableList.of((byte) 1, (byte) 2, (byte) 3);
Map<List<Byte>, String> map = new HashMap<>();
map.put(key1, "value1");
map.put(key2, "value2");
System.out.println(map.get(key1));
System.out.println(map.get(key2));
System.out.println(map.get(ImmutableList.of((byte) 1, (byte) 2, (byte) 3)));

運(yùn)行結(jié)果如下:

value2
value2
value2

注意: Byte對象的列表將占用比byte數(shù)組更多的內(nèi)存。因此,在大多數(shù)情況下,該解決方案并不推薦

自定義類(推薦使用)

我們還可以自己的定義一個(gè)類,用來完全控制哈希碼計(jì)算和相等性。這樣,我們可以確保解決方案快速,并且沒有太大的內(nèi)存占用。

讓我們創(chuàng)建一個(gè)只有一個(gè)final私有byte數(shù)組字段的類。它將沒有setter方法,只用getter方法,用來確保完全不可變性。

然后在實(shí)現(xiàn)自己的equalshashCode方法。為了方法,我們可以使用Arrays類來完成這兩項(xiàng)任務(wù),最終代碼如下:

public class BytesKey {
    private final byte[] array;
    public BytesKey(byte[] array) {
        this.array = array;
    }
    public byte[] getArray() {
        return array.clone();
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()){
            return false;
        }
        BytesKey bytesKey = (BytesKey) o;
        return Arrays.equals(array, bytesKey.array);
    }
    @Override
    public int hashCode() {
        return Arrays.hashCode(array);
    }
}

最后,我們使用我們自定義的類作為HashMap的key:

BytesKey key1 = new BytesKey(new byte[]{1, 2, 3});
BytesKey key2 = new BytesKey(new byte[]{1, 2, 3});
Map<BytesKey, String> map = new HashMap<>();
map.put(key1, "value1");
map.put(key2, "value2");
System.out.println(map.get(key1));
System.out.println(map.get(key2));
System.out.println(map.get(new BytesKey(new byte[]{1, 2, 3})));

運(yùn)行結(jié)果如下:

value2
value2
value2

注意: 自定義的類既沒有轉(zhuǎn)化為String的性能損耗,也沒有Byte對象列表的內(nèi)存占用。因此,該解決方案推薦使用。

總結(jié)

本文將討論在使用HashMap時(shí),當(dāng)byte數(shù)組作為key時(shí)所遇到的問題及其解決方案。

首先,我們將研究為什么不能直接使用數(shù)組作為鍵。在使用HashMap時(shí),我們需要保證每個(gè)鍵的唯一性,而使用數(shù)組作為鍵可能會(huì)出現(xiàn)沖突。這是因?yàn)閿?shù)組的hashCode值是基于其在內(nèi)存中的地址計(jì)算得出的,因此即使兩個(gè)數(shù)組內(nèi)容完全相同,它們在內(nèi)存中的位置不同,它們的hashCode也會(huì)不同。因此,直接使用數(shù)組作為鍵可能會(huì)導(dǎo)致無法正確獲取值或者出現(xiàn)意外的覆蓋。

接著,我們會(huì)介紹使用String和List這兩種數(shù)據(jù)結(jié)構(gòu)作為臨時(shí)解決方案的方法。它們都是具有可比性和可哈希性的數(shù)據(jù)結(jié)構(gòu),能夠保證唯一性。但這種方法并不是完美的解決方案,因?yàn)槭褂肧tring或List作為鍵會(huì)帶來一些性能上的開銷,或者占用不必要的內(nèi)存空間。

最后,我們將通過自定義類的方式完美解決這個(gè)問題。這個(gè)自定義類包含了一個(gè)byte數(shù)組字段,并重寫hashCodeequals方法,以確保唯一性和正確性。通過這種方式,我們可以避免使用String或List時(shí)的性能和內(nèi)存占用問題,并且能夠在保證正確性的同時(shí)獲得更高的效率。

到此這篇關(guān)于在Java中使用 byte 數(shù)組作為 Map 的 key的文章就介紹到這了,更多相關(guān)Java使用 byte 數(shù)組作為 Map 的 key內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringMVC按Ctrl上傳多個(gè)文件的方法

    SpringMVC按Ctrl上傳多個(gè)文件的方法

    這篇文章主要為大家詳細(xì)介紹了SpringMVC按Ctrl上傳多個(gè)文件的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-09-09
  • Kotlin語法學(xué)習(xí)-變量定義、函數(shù)擴(kuò)展、Parcelable序列化等簡單總結(jié)

    Kotlin語法學(xué)習(xí)-變量定義、函數(shù)擴(kuò)展、Parcelable序列化等簡單總結(jié)

    這篇文章主要介紹了Kotlin語法學(xué)習(xí)-變量定義、函數(shù)擴(kuò)展、Parcelable序列化等簡單總結(jié)的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • Java利用DelayQueue實(shí)現(xiàn)延遲任務(wù)代碼實(shí)例

    Java利用DelayQueue實(shí)現(xiàn)延遲任務(wù)代碼實(shí)例

    這篇文章主要介紹了Java利用DelayQueue實(shí)現(xiàn)延遲任務(wù)代碼實(shí)例,DelayQueue?是一個(gè)支持延時(shí)獲取元素的阻塞隊(duì)列,?內(nèi)部采用優(yōu)先隊(duì)列?PriorityQueue?存儲(chǔ)元素,同時(shí)元素必須實(shí)現(xiàn)?Delayed?接口,需要的朋友可以參考下
    2023-12-12
  • java開發(fā)就業(yè)信息管理系統(tǒng)

    java開發(fā)就業(yè)信息管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了java開發(fā)就業(yè)信息管理平臺(tái),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-06-06
  • logback過濾部分日志輸出的操作

    logback過濾部分日志輸出的操作

    這篇文章主要介紹了logback過濾部分日志輸出的操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Springboot 接收POST、json、文本數(shù)據(jù)的方法 附示例

    Springboot 接收POST、json、文本數(shù)據(jù)的方法 附示例

    這篇文章主要介紹了Springboot 接收POST、json、文本數(shù)據(jù)實(shí)踐,如果把 json 作為參數(shù)傳遞,我們可以使用 @requestbody 接收參數(shù),將數(shù)據(jù)直接轉(zhuǎn)換成對象,本文通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-10-10
  • 一文帶你深入了解Java泛型

    一文帶你深入了解Java泛型

    Java?泛型(generics)是?Jdk?5?中引入的一個(gè)新特性,?泛型提供了編譯時(shí)類型安全檢測機(jī)制,?該機(jī)制允許程序員在編譯時(shí)檢測到非法的類型。本文將通過示例詳解Java泛型的定義與使用,需要的可以參考一下
    2022-08-08
  • IDEA使用入門小白操作教程

    IDEA使用入門小白操作教程

    IntelliJ IDEA,就是Java語言開發(fā)工具 (IDE) 功能與Eclipse同類!本文通過圖文并茂的形式給大家介紹IntelliJ IDEA使用入門教程,非常適合新手小白操作,感興趣的朋友一起看看吧
    2020-10-10
  • springboot?接收LocalDateTime方式

    springboot?接收LocalDateTime方式

    這篇文章主要介紹了springboot?接收LocalDateTime方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • 淺談Apache Maven ToolChains的使用

    淺談Apache Maven ToolChains的使用

    Maven是java中非常有用和常用的構(gòu)建工具,基本上現(xiàn)在大型的java項(xiàng)目都是Maven和gradle的天下了。本文將介紹Apache Maven ToolChains的使用。
    2021-06-06

最新評論