CodeGym /Java Blog /Toto sisi /探索 Java 開發人員職位面試中的問題和答案。第10部分
John Squirrels
等級 41
San Francisco

探索 Java 開發人員職位面試中的問題和答案。第10部分

在 Toto sisi 群組發布
你好!成為某件事的大師需要多少小時?我經常聽到這樣的話:“要成為某件事的大師,你需要花一萬個小時。” 這是一個令人恐懼的數字,不是嗎? 探索 Java 開發人員職位面試中的問題和答案。 第 10 - 1 部分不過,我想知道這是否屬實。我不斷地試著弄清楚我已經投入了多少時間來掌握程式設計藝術。當我跨過那條10000小時的特殊線並成為大師時,我會感受到不同嗎?還是說我很久以前就已經跨過了那條線而沒有意識到?不管怎樣,你不必投入如此大量的時間來成為一名程式設計師。重要的是明智地利用你的時間。您的首要目標是獲得面試機會。在面試中,未來的軟體開發人員首先會被問及理論,因此這需要成為一種優勢。事實上,當你準備面試時,你的工作就是發現基礎 Java 理論知識中的所有空白,然後填補它們。今天我來這裡就是為了幫助您做到這一點,因為今天我們將繼續回顧最受歡迎的面試問題。好吧,我們繼續吧!

89. ArrayList 與 LinkedList 有何不同?

這是最常見的問題之一,還有關於 HashMap 內部結構的問題。沒有它,面試就不完整,所以你的答案應該很容易脫口而出。除了明顯的差異(它們有不同的名稱)之外,它們的內部結構也有所不同。之前,我們討論了ArrayListLinkedList的內部結構,因此我不會深入討論它們的實作細節。我只是提醒您,ArrayList是使用內部數組實現的,其大小根據以下公式動態增加:

<size of the current array> * 3 / 2 + 1
此外, LinkedList 的實作使用內部雙向鍊錶,即每個元素都有對前一個和下一個元素的引用,但列表開頭和結尾的元素除外。面試官喜歡問這樣的問題:“ ArrayListLinkedList哪個更好?” 希望能抓住你。畢竟,如果你說其中一個更好,那麼你就給了錯誤的答案。 探索 Java 開發人員職位面試中的問題和答案。 第 10 - 2 部分相反,您應該澄清您所討論的具體情況:透過索引存取元素或插入清單中間。然後,根據他們的回答,您可以解釋哪一個更好。我之前描述了ArrayListLinkedList在每種情況下如何運作。讓我們透過將它們放在一行中進行比較來總結這一點: 添加元素(添加)
  1. 如果未指定索引,則新項目將自動新增至兩種清單的末端。在LinkedList中,新元素將成為新尾部(只會重寫一對引用,因此演算法複雜度為O(1))。

    add 方法將一個元素加入到陣列中的最後一個空單元格 ( O(1) )。

  2. 透過索引添加項目通常意味著將其插入清單中間的某個位置。在LinkedList中,該方法將首先透過迭代尾部和頭部的元素來搜尋所需的位置 ( O(n/2) ),然後透過覆蓋兩側元素的參考來插入值插入新元素 ( O(1) )。此操作的總體演算法複雜度將為O(n/2)

    在相同的情況下(按索引新增),ArrayList找到所需的位置(O(1)),然後將位於右側的所有元素(包括已儲存在指定索引處的元素)向右移動一位(這可能需要建立一個新的內部陣列並將元素複製到其中)(O(n/2))。總體複雜度為O(n/2)

  3. 將元素添加到LinkedList的開頭類似於將元素添加到末尾:新元素成為新頭 ( O(1) )。但對於 ArrayList,該操作需要將所有元素移到右側 ( O(n) )。

最重要的是,對於 LinkedList,演算法複雜度範圍從O(1)O(n/2)。另一個觀察結果是,插入越接近列表的末尾或開頭,插入速度就越快。對於ArrayList,演算法複雜度從O(1)O(n)不等,插入越接近列表末尾,速度越快。 設定元素 (set) 此操作將元素寫入清單中的指定位置,覆寫任何現有元素。在LinkedList中,此操作類似於添加,因為這裡最大的挑戰是找到元素的位置。透過更新一對引用來覆蓋現有元素,因此我們的演算法複雜度從O(1)O(n/2)不等,取決於所需位置與列表末尾或開頭的距離。但對於ArrayList,此操作透過索引找到所需的儲存格並將新元素寫入其中。與集合運算一樣,依索引搜尋的演算法複雜度為O(1)透過索引取得元素 (get)從LinkedList 取得元素遵循與其他運算中使用的相同搜尋原則。複雜度取決於距離終點或起點的距離,即從O(1)O(n/2)不等。如前所述,對於ArrayList,透過索引在內部陣列中尋找元素的複雜度為O(1)透過索引刪除元素(remove) 對於LinkedList,同樣的原理再次適用。首先,定位該元素,然後重寫引用,已刪除元素的鄰居現在互相引用,消除了對已刪除元素的引用,該元素隨後將被垃圾收集器清理。換句話說,演算法複雜度仍然相同——從O(1)O(n/2)不等。對ArrayList來說,這個操作更像是增加一個新元素(add)。首先,該方法找到所需的元素 ( O(1) ),將其刪除,然後將位於右側的所有元素向左移動一步,以彌補刪除所產生的間隙。刪除元素與新增操作具有相同的演算法複雜度 — 從O(1)O(n)。被刪除的元素越接近列表的末尾,該操作的演算法複雜度越低。現在我們已經介紹了所有主要操作。需要提醒大家的是,在比較這兩種清單的時候,一定要弄清楚它們的具體使用場景,這樣才能明確回答面試官的問題。

90. ArrayList 與 HashSet 有何不同?

如果我們可以逐一比較ArrayListLinkedList以確定哪一個比較好,那麼我們會發現在ArrayListHashSet之間進行這樣的比較就沒那麼容易了,因為它們是完全不同的集合。你可以將一種甜點與另一種甜點進行比較,但比較甜點和鹹味菜餚是一項挑戰——它們截然不同。儘管如此,我還是會試著指出它們之間的一些差異:
  • ArrayList實作了List接口,而HashSet實作了Set接口。

  • ArrayList允許您透過索引存取元素:get操作的演算法複雜度為O(1),但HashSet只允許您透過迭代存取所需的元素,這會產生從O(1)O(n) 的演算法複雜度。

  • ArrayList允許重複元素。在HashSet中,所有元素都是唯一的:任何已添加 HashSet 中已存在的元素的嘗試都會失敗(透過雜湊碼檢查重複項,因此該集合的名稱也由此而來)。

  • ArrayList是使用內部陣列實現的,而HashSet是使用內部HashMap實現的。

  • ArrayList維護元素的插入順序,但HashSet是無序集合,不維護元素的順序。

  • ArrayList允許任意數量的空值,但你只能在HashSet中加入一個空值(畢竟元素必須是唯一的)。

91. 為什麼Java有這麼多不同的動態陣列實作?

這更多的是一個哲學問題。我們也可以問為什麼他們會想出這麼多新奇的技術?為了方便。對於大量動態數組實作也是如此。它們都不能被稱為最好或理想的實現。每種情況都有其優點。我們的工作是了解它們的差異以及它們的優點/缺點,以便能夠使用最適合任何特定情況的集合。

92. 為什麼Java有這麼多不同的鍵值儲存實作?

這裡的情況與動態數組實現相同。絕對沒有一個是普遍優於其他的:每個都有優點和缺點。當然,我們必須充分利用他們的優勢。 範例: concurrent 套件有很多多線程類,有自己的Concurrent集合。在多執行緒環境中處理資料時,ConcurrentHashMap 類別在安全性方面比標準 HashMap 具有優勢,但這是以效能較慢為代價。在任何情況下都不是最佳選擇的實現將逐漸停止使用。 例如: Hashtable原本是打算成為線程安全的HashMap,但現在已經被遺忘並不再使用了,因為ConcurrentHashMap在多線程環境中工作時 甚至比Hashtable更好。

93. 如何對元素集合進行排序?

首先要說的是,表示集合元素的類別必須實作Comparable接口,該接口由compareTo方法組成。或者您需要一個實作Comparator介面的類,包括其比較方法。這兩種方法都指示如何比較給定類型的物件。這在排序時至關重要,因為排序演算法需要了解使用什麼原理來比較元素。這主要是透過直接在要排序的類別中實作Comparable來完成的。使用比較器不太常見。假設您正在使用某個庫中的類,並且它沒有實作Comparable,但您需要對其物件的集合進行排序。由於您無法更改此類的程式碼(除非擴展它),因此您可以編寫Comparator的實作來指示如何比較該類別的物件。還有一個例子。如果您需要以不同的方式對相同類型的物件進行排序,那麼您可以編寫多個Comparator實作以在不同的情況下使用。通常,許多開箱即用的類別(例如String)已經實作了Comparable介面。這意味著您無需擔心如何比較這些類別。您可以繼續使用它們。 第一個也是最明顯的方法是使用TreeSetTreeMap類別。這些類別根據類別元素實現的比較器按排序順序儲存元素。不要忘記TreeMap對鍵進行排序,而不是對值進行排序。如果您使用Comparator而不是Comparable,那麼您需要在建立集合時 將Comparator物件傳遞給集合的建構子:

TreeSet treeSet = new TreeSet(customComparator);
但是如果您有不同類型的集合怎麼辦?你如何排序?在這種情況下,Collections實用程式類別的第二種方法 — sort()方法 — 是適當的。此方法是靜態的,因此您所需要做的就是在前面新增類別的名稱,然後傳入要排序的清單。例如:

Collections.sort(someList);
如果您使用Comparator而不是Comparable 的實現,那麼您需要將其作為第二個參數傳遞:

Collections.sort(someList, customComparator);
此操作將變更傳遞清單中元素的內部順序:將使用比較器對清單進行排序。請注意,傳遞的清單必須是可變的,否則該方法將失敗並拋出UnsupportedOperationException。第三種選擇是使用Stream類別的排序方法,該方法集合的元素進行排序。如果我們使用Comparable

someList = someList.stream().sorted().collect(Collectors.toList());
如果我們使用比較器

someList = someList.stream().sorted(customComparator).collect(Collectors.toList());
第四種方式是手動實作排序演算法,例如冒泡排序 歸併排序

對象類別。equals() 和 hashCode()

94. 簡要描述Java中的Object類別。

在回顧的第二部分中,我們已經討論了 Object類別的方法。這裡我要提醒大家,Object類別是Java中每個類別的祖先。它有 11 個方法,依序被所有類別繼承。 探索 Java 開發人員職位面試中的問題和答案。 第 10 - 3 部分

95. Java中equals()和hashCode()的用途是什麼?

hashCode()是Object類別的一個方法,被所有類別繼承。它的工作是產生一個代表特定物件的數字。可以在HashMap中找到此方法的實際範例,其中對鍵物件調用該方法以獲取本地哈希碼,這將確定鍵值對將儲存在哪個儲存桶(內部數組的單元格)中。此外,該方法一般用在equals()方法中,作為其辨識物件的主要方式之一。 equals()是Object類別的一個方法,其作用是比較物件並確定它們是否相等。這個方法用在我們需要比較物件的任何地方,因為標準的==比較運算子不適合對象,因為它只比較物件參考。

96. 請告訴我們 Java 中 equals() 和 hashCode() 之間的約定?

首先,我要說的是,為了讓equals()hashCode()方法正常運作,必須正確重寫它們。他們的新實現必須遵循以下規則:
  • equals傳回true 的相同物件必須具有相同的雜湊碼。
  • 具有相同哈希碼的物件不一定相等。
現在似乎是一個暫停的好地方,直到評論的下一部分!
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION