CodeGym /Java Blog /ランダム /Java 開発者の職の面接での質問と回答を調査します。パート 10
John Squirrels
レベル 41
San Francisco

Java 開発者の職の面接での質問と回答を調査します。パート 10

ランダム グループに公開済み
こんにちは!何かをマスターするのに何時間かかりますか? 「何かの達人になるには、それに10,000時間を費やす必要がある」というようなことをよく聞いたことがあります。それは恐ろしい数字ですね。 Java 開発者の職の面接での質問と回答を調査します。 パート10-1それでも、それが本当なのかどうかは疑問です。そして、私はプログラミングの技術を習得するためにすでに何時間を費やしたかを常に把握しようとしています。そして、10,000時間という特別なラインを超えてマスターになったとき、違いを感じるでしょうか?それとも、私はずっと前に、気づかないうちにすでにその一線を超えていたのでしょうか?いずれにせよ、プログラマーになるためにそれほど膨大な時間を投資する必要はありません。重要なことは時間を賢く使うことです。あなたの主な目標は面接を受けることです。そして、ソフトウェア開発者志望者は面接で最初に理論について尋ねられるため、それを強みにする必要があります。実際、面接の準備をする際の仕事は、Java の基本理論に関する知識のギャップをすべて発見し、それを埋めることです。今日私は、面接で最もよく聞かれる質問のレビューを続けるので、まさにそれをお手伝いするためにここにいます。さて、続けましょう!

89. ArrayList は LinkedList とどう違うのですか?

これは、 HashMapの内部構造に関する質問と並んで、最も人気のある質問の 1 つです。これなしでは面接は完了しません。そのため、あなたの答えはすぐに口からこぼれてしまうはずです。明らかなことに加えて(名前が異なります)、内部構造も異なります。前にArrayListLinkedListの両方の内部構造について説明したため、実装の詳細については説明しません。ArrayList は、次の式に従ってサイズが動的に増加する内部配列を使用して実装されていること を思い出してください。
<size of the current array> * 3 / 2 + 1
さらに、 LinkedList の実装では内部二重リンク リストが使用されます。つまり、リストの先頭と末尾の要素を除き、各要素は前後の要素への参照を持ちます。面接官は「 ArrayListLinkedListのどちらが優れていますか?」というような質問をするのが好きです。あなたを捕まえることを願っています。結局のところ、どちらか一方が優れていると言うなら、それは間違った答えを出したことになります。 Java 開発者の職の面接での質問と回答を調査します。 パート10-2代わりに、あなたが話している特定の状況、つまりインデックスによる要素へのアクセス、またはリストの途中への挿入を明確にする必要があります。そして、彼らの答えに応じて、どちらが優れているかを説明できます。それぞれの状況でArrayListLinkedList がどのように機能するかを以前に説明しました。比較のために並べてまとめてみましょう: 要素の追加 (add)
  1. インデックスが指定されていない場合、両方の種類のリストの末尾に新しい項目が自動的に追加されます。LinkedListでは、新しい要素が新しい末尾になります (参照のペアのみが書き換えられるため、アルゴリズムの複雑さはO(1)です)。

    add メソッドは、配列内の最後の空のセル ( O(1) )に要素を追加します。

  2. インデックスによって項目を追加するということは、通常、リストの中央のどこかに項目を挿入することを意味します。LinkedListでは、メソッドはまず末尾と先頭 ( O(n/2) )から要素を反復処理して目的の場所を検索し、次に、その両側の要素の参照を上書きして値を挿入します。新しい要素が挿入されます ( O(1) )。この操作の全体的なアルゴリズムの複雑さはO(n/2)になります。

    同じ状況 (インデックスによる追加) では、ArrayList は目的の位置 ( O(1) ) を見つけて、右にあるすべての要素 (指定されたインデックスに既に格納されている要素を含む) を 1 つだけ右にシフトします (これは、新しい内部配列の作成とそこへの要素のコピーが必要になる場合があります) ( O(n/2) )。全体的な複雑さはO(n/2)です。

  3. LinkedListの先頭に要素を追加することは、末尾に要素を追加することと似ており、新しい要素が新しい先頭 ( O(1) ) になります。ただし、ArrayList の場合、その操作ではすべての要素を右に移動する必要があります ( O(n) )。

結論としては、LinkedListのアルゴリズムの複雑さの範囲はO(1)からO(n/2)であるということです。もう 1 つの観察結果は、挿入がリストの末尾または先頭に近づくほど、挿入が高速になるということです。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) ) を見つけて削除し、次に、削除によって生じたギャップを埋めるために、右側にあるすべての要素を 1 ステップ左にシフトします。要素の削除には、O(1)からO(n)まで、追加操作と同じアルゴリズムの複雑さが伴います。。削除された要素がリストの最後に近づくほど、この操作のアルゴリズムの複雑さは低くなります。これで、主要な操作をすべてカバーできました。これら 2 種類のリストを比較するときは、それらが使用される具体的な状況を明確にする必要があることを思い出してください。そうして初めて、面接官の質問に明確に答えることができます。

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 では任意の数の null 値を許可しますが、 HashSetに追加できるのは 1 つの null 値のみです(結局、要素は一意である必要があります)。

91. Java にはなぜこれほど多くの異なる動的配列実装があるのですか?

これはむしろ哲学的な質問です。また、なぜ彼らはこれほど多くの新しくて多様なテクノロジーを思いつくのかと尋ねることもできます。便宜上。そして、同じことが多数の動的配列実装にも当てはまります。どれも最良または理想的な実装とは言えません。それぞれに特定の状況に応じた利点があります。私たちの仕事は、それぞれの違いと長所/短所を理解し、特定の状況に最適なコレクションを使用できるようにすることです。

92. Java にはなぜこれほど多くの異なるキーと値のストレージ実装があるのですか?

ここでの状況は、動的配列実装の場合と同じです。他より普遍的に優れているものは絶対にありません。それぞれに長所と短所があります。そしてもちろん、私たちは彼らの強みを最大限に活用しなければなりません。 例:多数のマルチスレッド クラスを含む並行パッケージには、独自の並行コレクションがあります。ConcurrentHashMapクラスは、マルチスレッド環境でデータを操作する場合の安全性の点で標準の HashMap よりも優れていますが、その代償としてパフォーマンスが低下ます。そして、どのような状況においても最善の選択ではない実装は、徐々に使用されなくなります。 例: Hashtableは、もともとスレッドセーフなHashMapであることを意図していましたが、マルチスレッド環境で作業する場合には ConcurrentHashMap の方がHashtableよりも優れているため、忘れられ、使用されなくなりました。

93. 要素のコレクションを並べ替えるにはどうすればよいですか?

まず最初に言っておきたいのは、コレクション要素を表すクラスは、compareToメソッドで構成されるComparableインターフェイスを実装する必要があるということです。または、 Comparatorインターフェイス ( compareメソッドを含む)を実装するクラスが必要です。どちらのメソッドも、特定のタイプのオブジェクトを比較する方法を示します。並べ替えアルゴリズムは要素を比較するためにどのような原理を使用するかを理解する必要があるため、これは並べ替えの際に重要です。これは主に、並べ替えるクラスにComparable を直接実装することによって行われます。Comparator を使用することはあまり一般的ではありません。あるライブラリのクラスを使用していて、そのクラスがComparableを実装していないが、そのオブジェクトのコレクションをソートする必要があるとします。このクラスのコードは (拡張する場合を除いて) 変更できないため、クラスのオブジェクトを比較する方法を示すComparatorの実装を作成できます。そしてもう一つの例。同じ型のオブジェクトをさまざまな方法で並べ替える必要がある場合は、さまざまな状況で使用する複数のComparator実装を作成できます。原則として、多くのすぐに使用できるクラス ( Stringなど) はすでにComparableインターフェースを実装しています。つまり、これらのクラスを比較する方法について心配する必要はありません。そのまま使用してください。 最初の最も明白な方法は、 TreeSet クラスまたはTreeMapクラスを使用することです。これらのクラスは、クラス要素によって実装されたコンパレータに基づいて並べ替えられた順序で要素を格納します。TreeMap は値ではなくキーを並べ替えることを忘れないでください。Comparableの代わりにComparator を使用する場合は、コレクションの作成時に Comparatorオブジェクトをコレクションのコンストラクターに渡す必要があります。
TreeSet treeSet = new TreeSet(customComparator);
しかし、別の種類のコレクションがある場合はどうなるでしょうか? どうやって並べ替えるのですか?この場合、Collectionsユーティリティ クラスの2 番目の方法であるsort()メソッドが適しています。このメソッドは静的であるため、クラスの名前を先頭に追加し、並べ替えるリストを渡すだけで済みます。例えば:
Collections.sort(someList);
ComparableではなくComparator の実装を使用している場合は、それを 2 番目の引数として渡す必要があります。
Collections.sort(someList, customComparator);
この操作により、渡されたリスト内の要素の内部順序が変更されます。リストはコンパレータを使用して並べ替えられます。渡されるリストは変更可能である必要があることに注意してください。変更可能でない場合、メソッドは失敗し、 UnsupportedOperationException をスローします。3番目のオプションは、コレクションの要素を並べ替えるStreamクラスのsortedメソッドを使用することです。Comparable を使用している場合:
someList = someList.stream().sorted().collect(Collectors.toList());
Comparator を 使用している場合:
someList = someList.stream().sorted(customComparator).collect(Collectors.toList());
4番目の方法は、バブル ソートマージ ソートなど のソート アルゴリズムを手動で実装することです。

オブジェクトクラス。equals() と hashCode()

94. Java の Object クラスについて簡単に説明してください。

レビューの2 番目の部分 では、 Objectクラスのメソッドについてすでに説明しました。ここで、 Objectクラスが Java のすべてのクラスの祖先であることを思い出してください。これには 11 のメソッドがあり、それらはすべてのクラスによって継承されます。 Java 開発者の職の面接での質問と回答を調査します。 パート10-3

95. Java では、equals() と hashCode() は何に使用されますか?

hashCode() は、すべてのクラスに継承されるObjectクラスのメソッドです。その仕事は、特定のオブジェクトを表す数値を生成することです。このメソッドの動作例はHashMapにあります。このメソッドはキー オブジェクトに対して呼び出され、ローカル ハッシュコードを取得します。これにより、キーと値のペアがどのバケット (内部配列のセル) に格納されるかが決まります。このメソッドは通常、オブジェクトを識別する主な方法の 1 つとして、 equals()メソッドで使用されます。equals()は、オブジェクトを比較し、それらが等しいかどうかを判断するObjectクラスのメソッドです。標準の==比較演算子はオブジェクト参照のみを比較するため、オブジェクトには適していないため、 このメソッドはオブジェクトを比較する必要があるあらゆる場所で使用されます。

96. Javaにおけるequals()とhashCode()の間の契約について教えてください。

まず、 equals()メソッドとhashCode()メソッドが正しく動作するには、それらを正しくオーバーライドする必要があると言わせてください。新しい実装は次のルールに従う必要があります。
  • 等号がtrue を返す同一のオブジェクトは、同じハッシュ コードを持つ必要があります。
  • 同じハッシュ コードを持つオブジェクトは必ずしも等しいとは限りません
ここで、レビューの次の部分まで一時停止するのが良いようです。
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION