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

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

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

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

HashMap的工作原理

HashMap是一種使用哈希機制來存儲和檢索值的數(shù)據結構。使用哈希碼來存儲和檢索值可以大大提高HashMap的性能,因為它可以使查找鍵值對的時間復雜度保持在 O ( 1 ) O(1) O(1)的級別。當然,這也要求我們在實現(xiàn)hashCode()方法時盡可能地讓哈希碼分布均勻,以免造成哈希沖突,從而影響HashMap的效率。

當我們調用put(key, value)方法時,HashMap會通過鍵的hashCode()方法計算哈希碼。這個哈希碼用于確定最終存儲值的桶:

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

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

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

equalshashCode方法

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

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

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

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

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

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

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}));

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

value1
value2
null

解決方法

使用String

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

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)建一個字符串非常簡單。我們可以使用Base64輕松編碼和解碼字符串,然后創(chuàng)建一個使用字符串作為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})));

運行結果如下:

value2
value2
value2

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

使用List

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

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實現(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)));

運行結果如下:

value2
value2
value2

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

自定義類(推薦使用)

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

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

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

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})));

運行結果如下:

value2
value2
value2

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

總結

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

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

接著,我們會介紹使用String和List這兩種數(shù)據結構作為臨時解決方案的方法。它們都是具有可比性和可哈希性的數(shù)據結構,能夠保證唯一性。但這種方法并不是完美的解決方案,因為使用String或List作為鍵會帶來一些性能上的開銷,或者占用不必要的內存空間。

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

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

相關文章

  • SpringMVC按Ctrl上傳多個文件的方法

    SpringMVC按Ctrl上傳多個文件的方法

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

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

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

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

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

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

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

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

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

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

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

    一文帶你深入了解Java泛型

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

    IDEA使用入門小白操作教程

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

    springboot?接收LocalDateTime方式

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

    淺談Apache Maven ToolChains的使用

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

最新評論