你不得不知道的HashMap面試連環炮

来源:https://www.cnblogs.com/wuneng/archive/2019/09/10/11503709.html
-Advertisement-
Play Games

1. 為什麼用HashMap? 1. 簡述一下Map類繼承關係? 1. 解決哈希衝突的方法? 1. 為什麼HashMap線程不安全? 1. resize機制? 1. HashMap的工作原理是什麼? 1. 有什麼方法可以減少碰撞? 1. HashMap中hash函數怎麼是是實現的? 1. 拉鏈法導致 ...


  1. 為什麼用HashMap?
  2. 簡述一下Map類繼承關係?
  3. 解決哈希衝突的方法?
  4. 為什麼HashMap線程不安全?
  5. resize機制?
  6. HashMap的工作原理是什麼?
  7. 有什麼方法可以減少碰撞?
  8. HashMap中hash函數怎麼是是實現的?
  9. 拉鏈法導致的鏈表過深問題為什麼不用二叉查找樹代替,而選擇紅黑樹?為什麼不一直使用紅黑樹?
  10. 說說你對紅黑樹的見解?
  11. 解決hash 碰撞還有那些辦法?
  12. 如果HashMap的大小超過了負載因數(load factor)定義的容量,怎麼辦?
  13. 重新調整HashMap大小存在什麼問題嗎?
  14. HashTable
  15. HashMap ,HashTable 區別
  16. ConcurrentHashMap 原理
  17. 我們可以使用CocurrentHashMap來代替Hashtable嗎?

    現在是晚上11點了,學校屠豬館的自習室因為太晚要關閉了,勤奮且疲憊的小魯班也從屠豬館出來了,正準備回宿舍洗洗睡,由於自習室位置比較偏僻所以是接收不到手機網路信號的,因此小魯班從兜里掏出手機的時候,信息可真是炸了呀,小魯班心想,微信群平時都沒什麼人聊天,今晚肯定是發生了什麼大事,仔細一看,才發現原來是小魯班的室友達摩(光頭)拿到了阿裡巴巴JAVA開發實習生的offer,此時小魯班真替他室友感到高興的同時,心裡也難免會產生一絲絲的失落感,那是因為自己投了很多份簡歷,別說拿不拿得到offer,就連給面試邀的公司也都寥寥無幾,小魯班這會可真是受到了一萬點真實暴擊,不過小魯班還是很樂觀的,很快調整了心態,帶上耳機,慢慢的走回了宿舍,正打算準備向他那神室友達摩取取經。
    片刻後~
  • 小魯班:666,聽說你拿到了阿裡的offer,能透露一下麵試內容和技巧嗎
    達摩:嘿嘿嘿,沒問題鴨,叫聲爸爸我就告訴你
  • 小魯班:baba(錶面笑嘻嘻,心裡MMP)
  • 達摩:JAVA的基礎知識:數據結構(Map,List,Set等),設計模式,演算法,線程相關,IO/NIO,序列化等等。其次是高級特征:反射機制,併發與鎖,JVM(GC策略,類載入機制,記憶體模型)等等
  • 小魯班:問這麼多內容,那豈不是一個人都面試很久嗎?
  • 達摩:不是的,面試官一般都會用連環炮的方式提問的。
  • 小魯班:你說的連環炮是什麼意思鴨?
  • 達摩:那我舉個例子
    就比如問你HashMap是不是有序的?
    你回答不是有序的。那面試官就會可能繼續問你,有沒有有序的Map實現類呢?
    你如果這個時候說不知道的話,那這塊問題就到此結束了。
    如果你說有TreeMap和LinkedHashMap。那麼面試官接下來就可能會問你,TreeMap和LinkedHashMap是如何保證它的順序的?如果你回答不上來,那麼到此為止。如果你說TreeMap是通過實現SortMap介面,能夠把它保存的鍵值對根據key排序,基於紅黑樹,從而保證TreeMap中所有鍵值對處於有序狀態。LinkedHashMap則是通過插入排序(就是你put的時候的順序是什麼,取出來的時候就是什麼樣子)和訪問排序(改變排序把訪問過的放到底部)讓鍵值有序。
    那麼面試官還會繼續問你,你覺得它們兩個哪個的有序實現比較好?
    如果你依然可以回答的話,那麼面試官會繼續問你,你覺得還有沒有比它更好或者更高效的實現方式。。無窮無盡深入,直到你回答不出來或者面試官認為問題到底了
    小魯班捏了一把汗,我去。。。這是魔鬼吧,那我們來試試唄(因為小魯班剛剛在自習室才看了這章的知識,想趁機裝一波逼,畢竟剛剛叫了聲爸爸~~)於是達摩and小魯班就開始了對決:

1.為什麼用HashMap?

HashMap是一個散列桶(數組和鏈表),它存儲的內容是鍵值對(key-value)映射
HashMap採用了數組和鏈表的數據結構,能在查詢和修改方便繼承了數組的線性查找和鏈表的定址修改
HashMap是非synchronized,所以HashMap很快
HashMap可以接受null鍵和值,而Hashtable則不能(原因就是equlas()方法需要對象,因為HashMap是後出的API經過處理才可以)

2.簡述一下Map類繼承關係


上面展示了java中Map的繼承圖,Map是一個介面,我們常用的實現類有HashMap、LinkedHashMap、TreeMap,HashTable。HashMap根據key的hashCode值來保存value,需要註意的是,HashMap不保證遍歷的順序和插入的順序是一致的。HashMap允許有一條記錄的key為null,但是對值是否為null不做要求。HashTable類是線程安全的,它使用synchronize來做線程安全,全局只有一把鎖,線上程競爭比較激烈的情況下hashtable的效率是比較低下的。因為當一個線程訪問hashtable的同步方法時,其他線程再次嘗試訪問的時候,會進入阻塞或者輪詢狀態,比如當線程1使用put進行元素添加的時候,線程2不但不能使用put來添加元素,而且不能使用get獲取元素。所以,競爭會越來越激烈。相比之下,ConcurrentHashMap使用了分段鎖技術來提高了併發度,不在同一段的數據互相不影響,多個線程對多個不同的段的操作是不會相互影響的。每個段使用一把鎖。所以在需要線程安全的業務場景下,推薦使用ConcurrentHashMap,而HashTable不建議在新的代碼中使用,如果需要線程安全,則使用ConcurrentHashMap,否則使用HashMap就足夠了。
LinkedHashMap屬於HashMap的子類,與HashMap的區別在於LinkedHashMap保存了記錄插入的順序。TreeMap實現了SortedMap介面,TreeMap有能力對插入的記錄根據key排序,預設按照升序排序,也可以自定義比較強,在使用TreeMap的時候,key應當實現Comparable。

3. HashMap的工作原理是什麼?

java7和java8在實現HashMap上有所區別,當然java8的效率要更好一些,主要是java8的HashMap在java7的基礎上增加了紅黑樹這種數據結構,使得在桶裡面查找數據的複雜度從O(n)降到O(logn),當然還有一些其他的優化,比如resize的優化等。

HashMap是基於hashing的原理,我們使用put(key, value)存儲對象到HashMap中,使用get(key)從HashMap中獲取對象。當我們給put()方法傳遞鍵和值時,我們先對鍵調用hashCode()方法,計算並返回的hashCode是用於找到Map數組的bucket位置來儲存Node 對象。這裡關鍵點在於指出,HashMap是在bucket中儲存鍵對象和值對象,作為Map.Node 。

Node<K,V>就是實際保存我們的key-value對的數據結構,下麵是這個數據結構的主要內容:

final int hash;
final K key;
V value;
Node<K,V> next;

以下是HashMap初始化 ,簡單模擬數據結構

以下是具體的put過程(JDK1.8版)

  • 對Key求Hash值,然後再計算下標
  • 如果沒有碰撞,直接放入桶中(碰撞的意思是計算得到的Hash值相同,需要放到同一個bucket中)
  • 如果碰撞了,以鏈表的方式鏈接到後面
  • 如果鏈表長度超過閥值( TREEIFY THRESHOLD==8),就把鏈表轉成紅黑樹,鏈表長度低於6,就把紅黑樹轉回鏈表

  • 如果節點已經存在就替換舊值
  • 如果桶滿了(容量16*載入因數0.75),就需要 resize(擴容2倍後重排),直到設定的最大值之後就無法再resize了
    以下是具體get過程(考慮特殊情況如果兩個鍵的hashcode相同,你如何獲取值對象?)
    當我們調用get()方法,HashMap會使用鍵對象的hashcode找到bucket位置,找到bucket位置之後,會調用keys.equals()方法去找到鏈表中正確的節點,最終找到要找的值對象。
      

4.解決哈希衝突的方法?

  • 有開放地址方法
  • 以及鏈地址方法

5.resize機制

HashMap的擴容機制就是重新申請一個容量是當前的2倍的桶數組,然後將原先的記錄逐個重新映射到新的桶裡面,然後將原先的桶逐個置為null使得引用失效。後面會講到,HashMap之所以線程不安全,就是resize這裡出的問題。

6.為什麼HashMap線程不安全

上面說到,HashMap會進行resize操作,在resize操作的時候會造成線程不安全。下麵將舉兩個可能出現線程不安全的地方。

  • put的時候導致的多線程數據不一致。
    這個問題比較好想象,比如有兩個線程A和B,首先A希望插入一個key-value對到HashMap中,首先計算記錄所要落到的桶的索引坐標,然後獲取到該桶裡面的鏈表頭結點,此時線程A的時間片用完了,而此時線程B被調度得以執行,和線程A一樣執行,只不過線程B成功將記錄插到了桶裡面,假設線程A插入的記錄計算出來的桶索引和線程B要插入的記錄計算出來的桶索引是一樣的,那麼當線程B成功插入之後,線程A再次被調度運行時,它依然持有過期的鏈表頭但是它對此一無所知,以至於它認為它應該這樣做,如此一來就覆蓋了線程B插入的記錄,這樣線程B插入的記錄就憑空消失了,造成了數據不一致的行為。
  • 另外一個比較明顯的線程不安全的問題是HashMap的get操作可能因為resize而引起死迴圈(cpu100%),具體分析如下:

下麵的代碼是resize的核心內容:

void transfer(Entry[] newTable, boolean rehash) {
int newCapacity = newTable.length;
for (Entry<K,V> e : table) {
while(null != e) {
Entry<K,V> next = e.next;
if (rehash) {
e.hash = null == e.key ? 0 : hash(e.key);
}
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
}
}
}

這個方法的功能是將原來的記錄重新計算在新桶的位置,然後遷移過去。

我們假設有兩個線程同時需要執行resize操作,我們原來的桶數量為2,記錄數為3,需要resize桶到4,原來的記錄分別為:[3,A],[7,B],[5,C],在原來的map裡面,我們發現這三個entry都落到了第二個桶裡面。
假設線程thread1執行到了transfer方法的Entry next = e.next這一句,然後時間片用完了,此時的e = [3,A], next = [7,B]。線程thread2被調度執行並且順利完成了resize操作,需要註意的是,此時的[7,B]的next為[3,A]。此時線程thread1重新被調度運行,此時的thread1持有的引用是已經被thread2 resize之後的結果。線程thread1首先將[3,A]遷移到新的數組上,然後再處理[7,B],而[7,B]被鏈接到了[3,A]的後面,處理完[7,B]之後,就需要處理[7,B]的next了啊,而通過thread2的resize之後,[7,B]的next變為了[3,A],此時,[3,A]和[7,B]形成了環形鏈表,在get的時候,如果get的key的桶索引和[3,A]和[7,B]一樣,那麼就會陷入死迴圈。
如果在取鏈表的時候從頭開始取(現在是從尾部開始取)的話,則可以保證節點之間的順序,那樣就不存在這樣的問題了。
綜合上面兩點,可以說明HashMap是線程不安全的。

7. 有什麼方法可以減少碰撞?

  • 擾動函數可以減少碰撞,原理是如果兩個不相等的對象返回不同的hashcode的話,那麼碰撞的幾率就會小些,這就意味著存鏈表結構減小,這樣取值的話就不會頻繁調用equal方法,這樣就能提高HashMap的性能。(擾動即Hash方法內部的演算法實現,目的是讓不同對象返回不同hashcode。)
  • 使用不可變的、聲明作final的對象,並且採用合適的equals()和hashCode()方法的話,將會減少碰撞的發生。不可變性使得能夠緩存不同鍵的hashcode,這將提高整個獲取對象的速度,使用String,Interger這樣的wrapper類作為鍵是非常好的選擇。為什麼String, Interger這樣的wrapper類適合作為鍵?因為String是final的,而且已經重寫了equals()和hashCode()方法了。不可變性是必要的,因為為了要計算hashCode(),就要防止鍵值改變,如果鍵值在放入時和獲取時返回不同的hashcode的話,那麼就不能從HashMap中找到你想要的對象。

8. HashMap中hash函數怎麼是是實現的?

  • 我們可以看到在hashmap中要找到某個元素,需要根據key的hash值來求得對應數組中的位置。如何計算這個位置就是hash演算法。前面說過hashmap的數據結構是數組和鏈表的結合,所以我們當然希望這個hashmap裡面的元素位置儘量的分佈均勻些,儘量使得每個位置上的元素數量只有一個,那麼當我們用hash演算法求得這個位置的時候,馬上就可以知道對應位置的元素就是我們要的,而不用再去遍歷鏈表。 所以我們首先想到的就是把hashcode對數組長度取模運算,這樣一來,元素的分佈相對來說是比較均勻的。但是,“模”運算的消耗還是比較大的,能不能找一種更快速,消耗更小的方式,我們來看看JDK1.8的源碼是怎麼做的(被樓主修飾了一下)
簡單來說就是
  1. 高16bt不變,低16bit和高16bit做了一個異或(得到的HASHCODE轉化為32位的二進位,前16位和後16位低16bit和高16bit做了一個異或)
  2. (n·1)&hash=->得到下標
  3. 拉鏈法導致的鏈表過深問題為什麼不用二叉查找樹代替,而選擇紅黑樹?為什麼不一直使用紅黑樹?
    之所以選擇紅黑樹是為瞭解決二叉查找樹的缺陷,二叉查找樹在特殊情況下會變成一條線性結構(這就跟原來使用鏈表結構一樣了,造成很深的問題),遍歷查找會非常慢。而紅黑樹在插入新數據後可能需要通過左旋,右旋、變色這些操作來保持平衡,引入紅黑樹就是為了查找數據快,解決鏈表查詢深度的問題,我們知道紅黑樹屬於平衡二叉樹,但是為了保持“平衡”是需要付出代價的,但是該代價所損耗的資源要比遍歷線性鏈表要少,所以當長度大於8的時候,會使用紅黑樹,如果鏈表長度很短的話,根本不需要引入紅黑樹,引入反而會慢。

9. 說說你對紅黑樹的見解?

  • 每個節點非紅即黑
  • 根節點總是黑色的
  • 如果節點是紅色的,則它的子節點必須是黑色的(反之不一定)
  • 每個葉子節點都是黑色的空節點(NIL節點)
  • 從根節點到葉節點或空子節點的每條路徑,必須包含相同數目的黑色節點(即相同的黑色高度)

10. 解決hash 碰撞還有那些辦法?

開放定址法。
當衝突發生時,使用某種探查技術在散列表中形成一個探查(測)序列。沿此序列逐個單元地查找,直到找到給定的地址。
按照形成探查序列的方法不同,可將開放定址法區分為線性探查法、二次探查法、雙重散列法等。

下麵給一個線性探查法的例子  

問題:已知一組關鍵字為(26,36,41,38,44,15,68,12,06,51),用除餘法構造散列函數,用線性探查法解決衝突構造這組關鍵字的散列表。

前5個關鍵字插入時,其相應的地址均為開放地址,故將它們直接插入T[0],T[10),T[2],T[12]和T[5]中。
當插入第6個關鍵字15時,其散列地址2(即h(15)=15%13=2)已被關鍵字41(15和41互為同義詞)占用。故探查h1=(2+1)%13=3,此地址開放,所以將15放入T[3]中。
當插入第7個關鍵字68時,其散列地址3已被非同義詞15先占用,故將其插入到T[4]中。
當插入第8個關鍵字12時,散列地址12已被同義詞38占用,故探查hl=(12+1)%13=0,而T[0]亦被26占用,再探查h2=(12+2)%13=1,此地址開放,可將12插入其中。
類似地,第9個關鍵字06直接插入T[6]中;而最後一個關鍵字51插人時,因探查的地址12,0,1,…,6均非空,故51插入T[7]中。

11. 如果HashMap的大小超過了負載因數(load factor)定義的容量,怎麼辦?

預設的負載因數大小為0.75,也就是說,當一個map填滿了75%的bucket時候,和其它集合類(如ArrayList等)一樣,將會創建原來HashMap大小的兩倍的bucket數組,來重新調整map的大小,並將原來的對象放入新的bucket數組中。這個過程叫作rehashing,因為它調用hash方法找到新的bucket位置。這個值只可能在兩個地方,一個是原下標的位置,另一種是在下標為<原下標+原容量>的位置

12. 重新調整HashMap大小存在什麼問題嗎?

當重新調整HashMap大小的時候,確實存在條件競爭,因為如果兩個線程都發現HashMap需要重新調整大小了,它們會同時試著調整大小。在調整大小的過程中,存儲在鏈表中的元素的次序會反過來,因為移動到新的bucket位置的時候,HashMap並不會將元素放在鏈表的尾部,而是放在頭部,這是為了避免尾部遍歷(tail traversing)。如果條件競爭發生了,那麼就死迴圈了。(多線程的環境下不使用HashMap)

HashMap的容量是有限的。當經過多次元素插入,使得HashMap達到一定飽和度時,Key映射位置發生衝突的幾率會逐漸提高。這時候,HashMap需要擴展它的長度,也就是進行Resize。

  1. 擴容:創建一個新的Entry空數組,長度是原數組的2倍。

  2. ReHash:遍歷原Entry數組,把所有的Entry重新Hash到新數組。
  • 達摩:哎呦,小老弟不錯嘛~~意料之外呀
  • 小魯班:嘿嘿,優秀吧,中場休息一波,我先喝口水
  • 達摩:不僅僅是這些哦,面試官還會問你相關的集合類對比,比如:

13. HashTable

數組 + 鏈表方式存儲
預設容量: 11(質數 為宜)
put:

  • 索引計算 : (key.hashCode() & 0x7FFFFFFF)% table.length
    若在鏈表中找到了,則替換舊值,若未找到則繼續
    當總元素個數超過容量*載入因數時,擴容為原來 2 倍並重新散列。
    將新元素加到鏈表頭部
    對修改 Hashtable 內部共用數據的方法添加了 synchronized,保證線程安全。

14. HashMap ,HashTable 區別

預設容量不同。擴容不同
線程安全性,HashTable 安全
效率不同 HashTable 要慢因為加鎖

15. ConcurrentHashMap 原理

1、最大特點是引入了 CAS(藉助 Unsafe 來實現【native code】)

CAS有3個操作數:

  • 記憶體值V
  • 舊的預期值A
  • 要修改的新值B。

當且僅當預期值A和記憶體值V相同時,將記憶體值V修改為B,否則什麼都不做。
Unsafe 藉助 CPU 指令 cmpxchg 來實現

使用實例:

  • 對 sizeCtl 的控制都是用 CAS 來實現的
  • sizeCtl :預設為0,用來控制 table 的初始化和擴容操作。

-1 代表table正在初始化

N 表示有 -N-1 個線程正在進行擴容操作

如果table未初始化,表示table需要初始化的大小。

如果table初始化完成,表示table的容量,預設是table大小的0.75倍,居然用這個公式算0.75(n - (n >>> 2))。

CAS 會出現的問題:ABA

對變數增加一個版本號,每次修改,版本號加 1,比較的時候比較版本號。

16. 我們可以使用CocurrentHashMap來代替Hashtable嗎?

我們知道Hashtable是synchronized的,但是ConcurrentHashMap同步性能更好,因為它僅僅根據同步級別對map的一部分進行上鎖。ConcurrentHashMap當然可以代替HashTable,但是HashTable提供更強的線程安全性。它們都可以用於多線程的環境,但是當Hashtable的大小增加到一定的時候,性能會急劇下降,因為迭代時需要被鎖定很長的時間。因為ConcurrentHashMap引入了分割(segmentation),不論它變得多麼大,僅僅需要鎖定map的某個部分,而其它的線程不需要等到迭代完成才能訪問map。簡而言之,在迭代的過程中,ConcurrentHashMap僅僅鎖定map的某個部分,而Hashtable則會鎖定整個map。

  • 此時躺著床上的張飛哄了一聲:睡覺了睡覺了~
  • 見此不太妙:小魯班立馬回到床上(泉水),把被子蓋過頭,心裡有一絲絲愉悅感,不對。好像還沒洗澡。。。

    by the way

CocurrentHashMap在JAVA8中存在一個bug,會進入死迴圈,原因是遞歸創建ConcurrentHashMap 對象,但是在1.9已經修複了,場景重現如下:

想瞭解更多面經和開發小技能,歡迎掃描下方的二維碼,持續關註!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 第十章 分層架構(面向流程拆分) 保證各層的差異足夠清晰,邊界足夠明顯 隔離關註點 層層傳遞 例如:MVC:分離數據處理,視圖顯示,業務邏輯 第十一章 SOA架構(面向服務拆分) 背景: 企業內部的IT系統重覆建設且效率低下。 企業各部門都有獨立的IT系統,人力資源部門,財務部門,銷售部門....當 ...
  • 前言:引擎組件的基本職責是負責流程流轉,但是在流轉過程中,除了對內部控制邏輯進行實現外,也不可避免的要去調用或者響應外部事件。本文主要描述外部事件的類型,以及調用方法過程。 1. 外部事件的類型 外部事件的類型是隨著引擎功能的需要而不斷增加,開發人員也可以在此基礎上進行擴展,目前主要常用的事件類型如 ...
  • day-4作業 1.簡述Python的五大數據類型的作用、定義方式、使用方法: 1.數字類型 不知道 2.字元串類型 不知道 3.列表 作用:儲存多個(任意數據類型)元素 定義方式:[]用逗號‘’隔開多個元素[任意數據類型] 使用方法:索[搜索]引[引路]取值,以0為開始,也可以倒數為-1開始。 3 ...
  • python入門,print ,運算符, 變數,input,解決問題。 ...
  • 為了更好的管理應用的配置,也為了不用每次更改配置文件都重啟,我們可以使用配置中心 關於eureka的服務註冊和rabbitMQ的安裝使用(自動更新配置需要用到rabbitMQ)這裡不贅述,只關註配置中心的內容 我們需要引入關鍵的包是這三個 需要在啟動類加上@EnableConfigServer註解, ...
  • 這裡建議先去看看路徑的問題,看看application.xml的裡面的導入的相應的配置文件的路徑有沒有問題,如下: 再者看看相應的註解有沒有加上,service和controller等的註解 如果再不行,在pon.xml文件加上下麵的: <build><resources> <!--編譯之後包含xm ...
  • 面試題 如何保證消息隊列的高可用? 面試官心理分析 如果有人問到你 MQ 的知識, 高可用是必問的 。 "上一講" 提到,MQ 會導致 系統可用性降低 。所以只要你用了 MQ,接下來問的一些要點肯定就是圍繞著 MQ 的那些缺點怎麼來解決了。 要是你傻乎乎的就乾用了一個 MQ,各種問題從來沒考慮過,那 ...
  • 安裝方法: 註:python環境一定要配置好。 1.第一步:下載 官方網站:http://www.pyinstaller.org/downloads.html 此處下載版本為穩定版。 2.第二步:下載完成後解壓,打開cmd。 例如:我的在F盤根目錄下。可更換目錄,建議不要有目錄不要帶有中文。 上圖: ...
一周排行
    -Advertisement-
    Play Games
  • GoF之工廠模式 @目錄GoF之工廠模式每博一文案1. 簡單說明“23種設計模式”1.2 介紹工廠模式的三種形態1.3 簡單工廠模式(靜態工廠模式)1.3.1 簡單工廠模式的優缺點:1.4 工廠方法模式1.4.1 工廠方法模式的優缺點:1.5 抽象工廠模式1.6 抽象工廠模式的優缺點:2. 總結:3 ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 本章將和大家分享ES的數據同步方案和ES集群相關知識。廢話不多說,下麵我們直接進入主題。 一、ES數據同步 1、數據同步問題 Elasticsearch中的酒店數據來自於mysql資料庫,因此mysql數據發生改變時,Elasticsearch也必須跟著改變,這個就是Elasticsearch與my ...
  • 引言 在我們之前的文章中介紹過使用Bogus生成模擬測試數據,今天來講解一下功能更加強大自動生成測試數據的工具的庫"AutoFixture"。 什麼是AutoFixture? AutoFixture 是一個針對 .NET 的開源庫,旨在最大程度地減少單元測試中的“安排(Arrange)”階段,以提高 ...
  • 經過前面幾個部分學習,相信學過的同學已經能夠掌握 .NET Emit 這種中間語言,並能使得它來編寫一些應用,以提高程式的性能。隨著 IL 指令篇的結束,本系列也已經接近尾聲,在這接近結束的最後,會提供幾個可供直接使用的示例,以供大伙分析或使用在項目中。 ...
  • 當從不同來源導入Excel數據時,可能存在重覆的記錄。為了確保數據的準確性,通常需要刪除這些重覆的行。手動查找並刪除可能會非常耗費時間,而通過編程腳本則可以實現在短時間內處理大量數據。本文將提供一個使用C# 快速查找並刪除Excel重覆項的免費解決方案。 以下是實現步驟: 1. 首先安裝免費.NET ...
  • C++ 異常處理 C++ 異常處理機制允許程式在運行時處理錯誤或意外情況。它提供了捕獲和處理錯誤的一種結構化方式,使程式更加健壯和可靠。 異常處理的基本概念: 異常: 程式在運行時發生的錯誤或意外情況。 拋出異常: 使用 throw 關鍵字將異常傳遞給調用堆棧。 捕獲異常: 使用 try-catch ...
  • 優秀且經驗豐富的Java開發人員的特征之一是對API的廣泛瞭解,包括JDK和第三方庫。 我花了很多時間來學習API,尤其是在閱讀了Effective Java 3rd Edition之後 ,Joshua Bloch建議在Java 3rd Edition中使用現有的API進行開發,而不是為常見的東西編 ...
  • 框架 · 使用laravel框架,原因:tp的框架路由和orm沒有laravel好用 · 使用強制路由,方便介面多時,分多版本,分文件夾等操作 介面 · 介面開發註意欄位類型,欄位是int,查詢成功失敗都要返回int(對接java等強類型語言方便) · 查詢介面用GET、其他用POST 代碼 · 所 ...
  • 正文 下午找企業的人去鎮上做貸後。 車上聽同事跟那個司機對罵,火星子都快出來了。司機跟那同事更熟一些,連我在內一共就三個人,同事那一手指桑罵槐給我都聽愣了。司機也是老社會人了,馬上聽出來了,為那個無辜的企業經辦人辯護,實際上是為自己辯護。 “這個事情你不能怪企業。”“但他們總不能讓銀行的人全權負責, ...