JavaRush /Java Blog /Random-TW /Java 開發者訪談問答分析。第10部分

Java 開發者訪談問答分析。第10部分

在 Random-TW 群組發布
你好!成為某件事的大師需要多少小時?我經常聽到這樣的話:“要成為任何事情的大師,你需要花費一萬個小時。” 一個可怕的數字,不是嗎? Java 開發者訪談問答分析。 第 10 - 1 部分不過,我想知道這是真的嗎?我不斷地試著弄清楚我已經投入了多少時間來掌握程式設計藝術。而當我跨過那珍貴的一萬小時,成為大師時,我會感受到這種差異嗎?還是我早已在不知不覺中跨過了它們?無論如何,要成為一名程式設計師,你不需要投入如此大量的時間。最重要的是明智地使用它。您的首要目標是通過面試。而且新人面試的時候,首先問的就是理論,所以你一定要很強。實際上,在準備面試時,你的任務就是發現自己在 Java 開發人員基礎理論方面的所有差距,並用知識來彌補它們。今天我將在這件事上幫助你,因為我在這裡繼續分析最熱門的問題。那麼就讓我們繼續吧!

89.ArrayList與LinkedList有何不同?

這是與HashMap內部結構問題一樣最常見的問題之一。如果沒有它,任何一次採訪都是不完整的,因此它的答案應該是「從你的牙齒上彈下來」。除了明顯的名稱不同之外,它們的內部結構也有所不同。前面我們已經研究了ArrayListLinkedList的內部結構,因此我不會詳細介紹它們的實作細節。順便提醒一下,ArrayList是基於內部數組實現的,根據需要根據公式增加:
<размерТекущегоМассива> * 3 / 2  + 1
同時,LinkedList是基於內部雙向鍊錶實現的,即每個元素都有一個到上一個和下一個的鏈接,不包括作為列表開頭/結尾的值。人們喜歡以這樣的形式問這個問題:“ ArrayListLinkedList哪個更好?”,希望能抓住你。畢竟,如果你指出其中一個作為答案,那將是錯誤的答案。 Java 開發者訪談問答分析。 第 10 - 2 部分相反,您應該澄清您所討論的具體情況 - 索引訪問或插入列表中間。根據答案,您將能夠解釋您的選擇。我之前已經描述過ArrayListLinkedList在某種情況下如何運作。讓我們透過將它們放在同一頁上進行比較來總結這一點: 添加元素(添加)
  1. Добавление нового element без указания индекса How местоположения будет происходить автоматически в конец обоих списков. В LinkedList новый элемент станет новым хвостом (происходит только перезаписывание пары ссылок — алгоритмическая сложность O(1)).

    В ArrayList будет добавлен новый элемент в последнюю пустую ячейку массива — O(1).

  2. Добавление element по индексу How правило подразумевает вставку примерно в середину списка. В LinkedList сперва будет вестись поиск нужного места с помощью перебора элементов с “хвоста” и “головы” — O(n/2), а после — вставка значения путем переопределения ссылок элементов, между которыми вставляется новый — O(1). Суммарная алгоритмическая сложность данного действия будет O(n/2).

    ArrayList в данной ситуации по индексу находит элемент — O(1), и все элементы справа (включая элемент, который уже хранится по данному индексу) двигаются на одну единицу вправо (при этом возможно понадобится создание нового списка и копирование элементов в него) — O(n/2). Суммарная сложность — O(n/2).

  3. Добавление element в начало списка в 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中,透過元素索引來存取:取得操作的演算法複雜度為O(1),而在HashSet中,需要透過暴力破解來取得所需元素,這是從O(1)O(n) ;

  • ArrayList允許重複元素。在HashSet 中,所有元素都是唯一的:在集合中已存在類似元素的HashSet新增元素將無法運作(使用雜湊碼檢查重複項,因此該集合的名稱);

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

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

  • ArrayList允許任意數量的空值(null),在一個HashSet中只能插入一個空值(畢竟元素的唯一性)。

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

Java 開發者訪談問答分析。 第 10 - 3 部分嗯,這更像是哲學問題。那麼,為什麼他們會想出這麼多不同的新技術呢?為了舒適。實際上,大量動態數組的實作也是如此。他們都不能被稱為最好或理想的。每個人在某些特定情況下都有優勢。我們的任務是了解它們的差異、優點/缺點:以便能夠在正確的情況下使用最合適的。

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

這裡的情況與動態數組實現相同。沒有最好的人:每個人都有優點和缺點。當然,我們必須充分利用我們的優勢。 範例: concurrent包,包含了很多多執行緒技術,有自己的Concurrent集合。與常規HashMap相比,相同的ConcurrentHashMap在多執行緒處理資料的安全性方面具有優勢,但在非多執行緒環境中它會損失速度。好吧,在任何情況下都不是最強的實現逐漸被停止使用。 範例:Hashtable最初旨在成為線程安全的HashMap,但ConcurrentHashMap在多線程環境中優於它,Hashtable最終被遺忘並不再使用。

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

首先要說的是集合元素類別必須實作Comparable介面及其compareTo方法。或者您需要一個使用其比較器方法實作Comaprator 的類別。您可以在這篇文章中閱讀有關它們的更多資訊。兩種方法都指定應如何比較給定類型的物件。排序時,這一點至關重要,因為您需要了解比較元素的原理。主要方法是實作Comparable,直接在要排序的類別中實作。同時,Comparator的使用也較不常見。假設您正在使用某個庫中的類,該類沒有Comparable實現,但您需要以某種方式對其進行排序。在無法更改此類程式碼(除非擴展它)的情況下,您可以編寫Comparator的實現,在其中指示您想要根據什麼的原則來比較此類的物件。還有一個例子。假設您需要不同的原則來對同一類型的物件進行排序,因此您編寫了多個在不同情況下使用的比較器。通常,許多開箱即用的類別已經實作了Comparable介面- 相同的String。其實,在使用它們的時候,你不必擔心如何比較它們。你只需拿起它們並使用它們。 第一種也是最明顯的方法是使用像TreeSetTreeMap這樣的集合,它根據元素類別比較器以已經排序的順序儲存元素。請記住,TreeMap會對鍵進行排序,但不會對值進行排序。如果您使用Comparator實作而不是Comparable,則需要在建立時將其物件傳遞給集合建構子:
TreeSet treeSet = new TreeSet(customComparator);
但是如果您有不同類型的集合怎麼辦?怎麼排序呢?在這種情況下,Collections實用程式類別的第二種方法是適當的- sort()方法。它是靜態的,因此您所需要的只是類別的名稱和向其傳遞所需清單的方法。例如:
Collections.sort(someList);
如果您不使用Comparable ,而是使用Comparator 的實現,則需要將其作為第二個參數傳遞:
Collections.sort(someList, customComparator);
結果,傳遞的列表元素的內部順序將發生變化:它將根據元素比較器進行排序。我注意到傳輸的元素列表必須是可變的,即 可變的,否則該方法將無法運作並會拋出UnsupportedOperationException。作為第三種方法,您可以使用Stream排序操作,如果使用Comparable實現,它會對集合的元素進行排序:
someList = someList.stream().sorted().collect(Collectors.toList());
如果比較器
someList = someList.stream().sorted(customComparator).collect(Collectors.toList());
您可以在本文中閱讀有關Stream 的更多資訊。 第四種方法是手動實現排序,例如冒泡排序歸併排序

類別對象。等於和哈希碼

94.簡述Java中的類別對象

在第二部分的分析中,我們已經講了Object類別的方法,這裡我要提醒大家,Object類別是Java中所有類別的鼻祖。它有 11 個方法,相應地,所有類別都繼承這些方法。 有關所有 11 種方法的資訊可以在討論的 第二部分中Java 開發者訪談問答分析。 第 10 - 4 部分找到。

95. Java 中 Equals 和 HashCode 的用途是什麼?

hashCode()是Object類別的一個方法,被所有類別繼承。它的任務是產生一些代表特定物件的數字。使用此方法的範例是在鍵物件上的HashMap中使用它來進一步確定本地雜湊碼,這將確定儲存該對的內部數組(桶)的單元格。我們在分析的第 9 部分中詳細討論了HashMap的工作,因此我們不再過多贅述。 此外,通常,此方法在equals()方法中使用,作為確定物件身分的主要工具之一。 equals()是Object類別的一個方法,其作用是比較物件並確定它們是否相等。凡是我們需要比較對象的地方都會用到這個方法,因為通常使用==的比較並不適合對象,因為 僅比較它們的連結。 Java 開發者訪談問答分析。 第 10 - 5 部分

96.請告訴我們Java中Equals和HashCode之間的約定?

我要說的第一件事是,為了讓equals()hashCode()方法正常運作,需要正確重寫它們。此後他們必須遵守規則:
  • 透過equals比較傳回true 的相同物件必須具有相同的雜湊碼;
  • 具有相同哈希碼的物件可能並不總是相等。
到這裡我們就暫停一下,等待下一部分的分析!Java 開發者訪談問答分析。 第 10 - 6 部分
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION