主頁 >  其他 > (Java)筆記篇---HashMap底層原理決議及HashMap常考面試題

(Java)筆記篇---HashMap底層原理決議及HashMap常考面試題

2021-12-27 07:21:11 其他

目錄

一. 實作的介面

二. 默認初始值

1. 默認初始容量

2. 默認最大容量

3. 默認負載因子

三. 鏈表與紅黑樹的相互轉換

四. 哈希桶中鏈表的結構

五. 哈希函式

六. 擴容

七. HashMap中常用的方法

1. 構造方法

2. 查找,根據key獲取value

3. 檢測key是否存在

4. 插入

5. 洗掉

八. HashMap常考問題


一. 實作的介面

底層實作了Map,克隆,序列化介面

二. 默認初始值

1. 默認初始容量

2^4 = 16,當不給初始容量時,容量默認為16

2. 默認最大容量

默認最大容量為 2^30

3. 默認負載因子

默認的負載因子為0.75,有效元素個數 / 表容量 = 負載因子

三. 鏈表與紅黑樹的相互轉換

哈希桶中存放的是鏈表節點,但是在一定條件下,鏈表會和紅黑樹相互轉化

每個桶的鏈表節點個數超過8,鏈表會轉化為紅黑樹

當紅黑樹中的節點個數小于6時,紅黑樹會退化為鏈表

如果哈希桶中某條鏈表中節點超過8,并且桶的個數超過64,鏈表才會轉化為紅黑樹,否則直接擴容

四. 哈希桶中鏈表的結構

//HashMap將其底層鏈表中的節點封裝為靜態內部類
//節點中帶有key,value鍵值對以及key所對應的哈希值
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; }
        
        //重寫Object類中hashcode()方法
        public final int hashCode() {
            return Objects.hashCode(key) ^ Objects.hashCode(value);
        }

        public final V setValue(V newValue) {
            V oldValue = value;
            value = newValue;
            return oldValue;
        }
        
        //重寫Object類中equals方法
        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;
        }
    }

五. 哈希函式

將key轉化為一個整型數字,再用這個數字進行除留余數法計算桶的位置

決議:

1. 如果key為null,回傳0號桶,

2. 如果key不為null,回傳key所對應的哈希碼,如果key為自定義型別,必須重寫Object類中的hashcode()方法,

3. ( h = key . hashCode() ) ^ ( h >>> 16 ),是為了讓高16bit不變,低16bit與高16bit進行異或,主要用于當hashmap陣列比較小的時候所有bit都參與運算,目的是減小碰撞,

4. 獲取到哈希地址后,計算桶號的方式為:index = (table.length - 1) & hash,

5. 通過除留余數法方式獲得桶號,因為hash表的大小始終為2的n次冪因此可以將取模轉為位運算,提高效率,這也是為什么要按照2倍方式擴容的一個原因,

這里畫圖來說明一下原因:

總結:通過上述方式可知,實際上hashcode的很多位是用不上的,因此在hashMap的hash函式中,才使用了移位運算,只取了前16位來做映射,另一方面&運算比取模效率更高,

六. 擴容

每次都是將cap擴大到與cap最近的2的n次冪,int n = cap - 1;是為了防止cap已經是2的冪次方,如果cap已經是2的冪次方,則執行完后面的幾條無符號右移操作之后,回傳的capacity將是這個cap的2倍,

假設現在cap的初始值為10,具體方式如下:

七. HashMap中常用的方法

1. 構造方法

 // 構造方法一:帶有初始容量的構造,負載因子使用默認值0.75
    public HashMap(int initialCapacity) {
        this(initialCapacity, DEFAULT_LOAD_FACTOR);
    }
    // 構造方法二:
    public HashMap() {
        this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
    }
    // 構造方法一:帶有初始容量和初始負載因子的構造
    public HashMap(int initialCapacity, float loadFactor) {
        // 如果容量小于0,拋出非法引數例外
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +
                    initialCapacity);
        // 如果初始容量大于最大值,用2^30代替
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;

        // 檢測負載因子是否非法,如果負載因子小于0,或者負載因子不是浮點數,拋出非法引數例外
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal load factor: " +
                    loadFactor);
        // 給負載因子和容量賦值,并將容量提升到2的整數次冪
        // 注意:建構式中并沒有給
        this.loadFactor = loadFactor;
        this.threshold = tableSizeFor(initialCapacity);
    }
/*
注意:
不同于Java7中的構造方法,Java8對于陣列table的初始化,并沒有直接放在構造器中完成,而是將table陣列的構
造延遲到了resize中完成
*/

2. 查找,根據key獲取value

/*
     1. 通過key計算出其哈希地址,然后借助哈希地址在哈希桶中找到與key對應的節點
     2. 如果節點為null,回傳null,說明HashMap中節點是可以為空的
     3. 如果節點不為空,回傳該節點中的value
    */
    public V get(Object key) {
        Node<K,V> e;
        return (e = getNode(hash(key), key)) == null ? null : e.value;
    }
    final Node<K,V> getNode(int hash, Object key) {
        Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
        // 1. 先檢測哈希桶是否為空
        // 2. 檢測哈希桶的個數是否大于零,如果桶不空,桶的個數肯定不為0
        // 3. n-1&hash-->計算桶號
        // 4. 當前桶是否為空桶
        // 如果1 2 3 4均不成立,說明當前桶中有節點,拿到當前桶中第一個節點
        if ((tab = table) != null && (n = tab.length) > 0 &&
                (first = tab[(n - 1) & hash]) != null) {

            // 如果節點的哈希值與key的哈希值相等,然后再檢測key是否相等
            // 如果相等,則回傳該節點
            // 此處也進一步證明了:HashMap必須要重寫hashCode和equals方法
            if (first.hash == hash && // always check first node
                    ((k = first.key) == key || (key != null && key.equals(k))))
                return first;
            // 如果第一個節點后還有節點,檢測first是否為treeNode型別的
            // 因為如果哈希桶中某條鏈節點大于8個,為了提高性能,HashMap會將鏈表替換為紅黑樹
            // 此時再紅黑樹中找與key對應的節點
            if ((e = first.next) != null) {
                if (first instanceof TreeNode) // 通過檢測節點的型別知道是鏈表還是紅黑樹
                    return ((TreeNode<K,V>)first).getTreeNode(hash, key);
                // 當前桶中掛接的是一個鏈表
                // 順著鏈表的節點一個一個往下找,找到之后回傳
                do {
                    if (e.hash == hash &&
                            ((k = e.key) == key || (key != null && key.equals(k))))
                        return e;
                } while ((e = e.next) != null);
            }
        }
        return null;
    }

3. 檢測key是否存在

    /*
1. 先通過getNode()獲取與key對應的節點
2. 如果節點不為空,說明存在回傳true,否則回傳false
3. 時間復雜度:平均為O(1),如果當天key所對應的桶中掛接的鏈表則順序查找,掛接的是紅黑樹按照紅黑樹性質找
*/
    public boolean containsKey(Object key) {
        return getNode(hash(key), key) != null;
    }

4. 插入

    /*
1. 先使用key借助hash函式計算key的哈希地址
2. 將key-value鍵值對,結合計算出的hash地址插入到哈希桶中
3. 從以下代碼中可以看到,HashMap在插入時,并沒有處理執行緒安全問題,因此HashMap不是執行緒安全的
4. 紅黑樹優化鏈表過長是java8新引進,是基于性能的考慮,在沖突大時,紅黑樹演算法會比鏈表綜合表現更好
*/
    public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }
    final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i;

        // 1. 桶如果是空的,則進行擴容
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;

        // 2. (n-1)&hash-->計算桶號,如果當前桶中沒有節點,直接插入
        // p來記錄桶中的第一個節點
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
        else {
            Node<K,V> e; K k;

            // 3. 如果key已經是和桶中第一個節點相等,不進行插入
            if (p.hash == hash &&
                    ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;
            else if (p instanceof TreeNode) // 4. 如果該桶中掛接的是紅黑樹,向紅黑樹中插入
                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
            else {
                // 5. key不同,也不是紅黑樹,說明當前桶中掛的是一個鏈表
                // a. 在當前鏈表中找key
                // b. 如果找到,則不插入
                // c. 如果沒有找到,先構建新節點,然后將該節點尾插到鏈表中
                // d. 檢測bitCount的計數,binCount記錄的是在未插入新節點前原鏈表的節點個數
                // e. 新節點插入后,鏈表長度是否超過TREEIFY_THRESHOLD,如果超過將鏈表轉換為紅黑樹
                for (int binCount = 0; ; ++binCount) {
                    if ((e = p.next) == null) {
                        // p已經是最后一個節點,說明在鏈表中未找到key對應的節點
                       // 進行尾插
                        p.next = newNode(hash, key, value, null);
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash); // 將鏈表轉化為紅黑樹
                        break;
                    }

                    // 如果key已經存在,跳出回圈
                    if (e.hash == hash &&
                            ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
                }
            }

            // 如果key已經存在,將key所對節點中的value替換為引數指定value,回傳舊value
            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }
        }
        ++modCount;
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);
        return null;
    }
    /*
注意:afterNodeAccess和afterNodeInsertion主要是LinkedHashMap實作的,HashMap中給出了該方法,但是
并沒有實作
*/
    // Callbacks to allow LinkedHashMap post-actions
    // 訪問、插入、洗掉節點之后進行一些處理,
    // LinkedHashMap正是通過重寫這三個方法來保證鏈表的插入、洗掉的有序性
    void afterNodeAccess(Node<K,V> p) { }
    void afterNodeInsertion(boolean evict) { }
    void afterNodeRemoval(Node<K,V> p) { }
/*
LinkedHashMap: 繼承了HashMap,在LinkedHashMap中會對以上方法進行重寫,以保證存入到LinkedHashMap中
的key是有序的,注意這里的有序是不自然序列,指的是插入元素的先后次序
LinkedHashMap底層的哈希桶使用的是雙向鏈表
*/

5. 洗掉

public V remove(Object key) {
        Node<K,V> e;
        return (e = removeNode(hash(key), key, null, false, true)) == null ?
                null : e.value;
    }
    final Node<K,V> removeNode(int hash, Object key, Object value,
                               boolean matchValue, boolean movable) {
        Node<K,V>[] tab; Node<K,V> p; int n, index;

        // 1. 檢測哈希表是否存在
        // 2. index = (n - 1) & hash: 獲取桶號
        // 3. p記錄當前桶中第一個節點,如果桶中沒有節點,直接回傳null
        if ((tab = table) != null && (n = tab.length) > 0 &&
                (p = tab[index = (n - 1) & hash]) != null) {
            Node<K,V> node = null, e; K k; V v;

            // 如果第一個節點就是key,用node記錄
            if (p.hash == hash &&
                    ((k = p.key) == key || (key != null && key.equals(k))))
                node = p;
            else if ((e = p.next) != null) {
                // 如果當前桶下是紅黑樹,在紅黑樹中查找,結果用node記錄
                if (p instanceof TreeNode)
                    node = ((TreeNode<K,V>)p).getTreeNode(hash, key);
                else {
                    // 當前桶下是鏈表,遍歷鏈表,在鏈表中檢測是否存在為key的節點
                    do {
                        if (e.hash == hash &&
                                ((k = e.key) == key ||
                                        (key != null && key.equals(k)))) {
                            node = e;
                            break;
                        }
                        p = e;
                    } while ((e = e.next) != null);
                }
            }
            // node不為空,在HashMap中找到了
            if (node != null && (!matchValue || (v = node.value) == value ||
                    (value != null && value.equals(v)))) {
                // 如果節點在紅黑樹中,將其洗掉
                if (node instanceof TreeNode)
                    ((TreeNode<K,V>)node).removeTreeNode(this, tab, movable);
                    // 如果節點是鏈表中第一個節點,將當前鏈表中下一個節點地址放在桶中
                else if (node == p)
                    tab[index] = node.next;
                else
                    p.next = node.next; // 非第一個節點
                ++modCount;
                --size;

                // LinkedHashMap使用
                afterNodeRemoval(node);

                // 洗掉成功,回傳原節點
                return node;
            }
        }

        // 洗掉失敗回傳空
        return null;
    }

八. HashMap常考問題

1. 如果new HashMap(19),bucket陣列多大?

在Java1.8中,new的時候并沒有給陣列開辟空間,而是在第一次插入的時候才開辟空間,開辟的空間為比19大且最接近19的冪次方,2^4=16,2^5=32,故bucket陣列的大小為32

2. HashMap什么時候開辟bucket陣列占用記憶體?

這個問題上面答案中已經回答過了,在第一次插入的時候才開辟空間記憶體

3. hashMap何時擴容?

當表中有效元素的個數 >= 負載因子 * 表格容量的時候需要擴容,擴容也是按照2的冪次方來進行擴容的

4. 當兩個物件的hashcode相同會發生什么?

在get()時:如果hashcode相同,先通過equal方法比較key是否一樣,如果key也相同將value直接回傳,否則回傳空

在插入時:如果hashcode相同,再判斷key是否存在,如果key已經存在,將key對應的value進行替換,如果key不存在則插入

在洗掉時:如果hashcode相同,則key可能是我們要洗掉的,通過equals對比,如果是則洗掉,如果不是則回傳

5. 如果兩個鍵的hashcode相同,你如何獲取值物件?

遍歷與hashCode值相等時相連的鏈表,直到相等或者 null

6. 你了解重新調整HashMap大小存在什么問題嗎?

如果將HashMap的容量進行改變,就必須將原來表中的節點重新哈希,擴容的目的就是將節點重新哈希,將鏈表變短

7. 為什么要重寫hashcode()與equals()方法?

重寫hashcode:底層原理是通過key來計算hashcode,通過hashcode來計算hash,hash回傳的是一個整型數字,再通過這個數來進行除留余數,計算的結果為桶的位置,但是對于自定義型別,key不能轉化為整型數字,必須重寫hashcode方法來使自定義型別的key轉化為整型數字以此來得到桶的位置,

重寫equals:當發生哈希沖突時,得比較key是否相同,而比較需要用到equals方法,對于自定義型別比較key的時候得重寫equals方法來比較key的內容是否相同,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/393922.html

標籤:其他

上一篇:嵌入式實時作業系統8——等待表

下一篇:Manacher(馬拉車演算法)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more