프로그래머가 되는 것은 쉽지 않습니다. 항상 새로운 것을 배울 수 있습니다. 그리고 다른 노력과 마찬가지로 가장 어려운 일은 시작하고 목표를 향한 첫 걸음을 내딛는 것입니다. 하지만 당신은 이미 여기 와서 이 글을 읽고 있으므로 첫 번째 단계를 완료한 것입니다. 이는 이제 속도를 늦추거나 옆으로 방향을 바꾸지 않고 의도적으로 목표를 향해 움직여야 함을 의미합니다. 나는 당신의 목표가 Java 개발자가 되는 것이라고 생각합니다. 이미 개발자라면 지식을 강화하는 것입니다. 그렇다면 계속해서 광범위한 Java 개발자 인터뷰 질문 목록을 살펴보겠습니다. Java 개발자 직위에 대한 취업 면접의 질문과 답변을 살펴보세요.  파트 9 - 1계속하자!

컬렉션

84. 반복자와 그것이 어떻게 사용되는지 알려주세요

컬렉션은 Java 개발자 인터뷰에서 가장 좋아하는 주제입니다. 컬렉션 계층 구조에 대한 질문에 답할 때 지원자는 컬렉션 인터페이스로 시작한다고 말하는 경우가 많습니다. 그러나 이것은 그렇지 않습니다. 한 수준 위에 또 다른 인터페이스가 있습니다: Iterable . 이 인터페이스는 현재 컬렉션의 Iterator 객체 에 액세스할 수 있는 iterator() 메서드로 구성됩니다. 그리고 이 Iterator 객체는 정확히 무엇입니까 ? Iterator 객체는 컬렉션을 통해 이동하고 해당 요소 반복하는 기능을 제공하며 사용자는 컬렉션의 특정 구현 세부 사항을 알 필요가 없습니다. 즉, 컬렉션의 요소 중 하나를 들여다보는 것처럼 컬렉션의 요소에 대한 일종의 포인터입니다. 반복자에는 다음과 같은 메서드가 있습니다.
  • hasNext() — 반복에 다른 요소가 있으면 true를 반환합니다. 이 메서드를 사용하면 컬렉션의 끝에 도달했음을 알 수 있습니다.

  • next() — 반복의 다음 항목을 반환합니다. 없는 경우 NoSuchElementException 이 발생합니다. 즉, 이 메서드를 사용하기 전에 hasNext() 메서드를 사용하여 다음 요소가 있는지 확인하는 것이 가장 좋습니다 .

  • 제거() — next() 메서드를 사용하여 받은 마지막 요소를 컬렉션에서 제거합니다 . next()가 호출된 적이 없는 경우 , 제거()를 호출하면 IllegalStateException 이 발생합니다 .

  • forEachRemaining(<Consumer>) — 컬렉션의 각 요소에 대해 전달된 작업을 실행합니다(이 메서드는 Java 8에 나타남).

다음은 우리가 살펴본 다양한 반복기 메서드를 사용하여 목록을 반복하고 해당 요소를 모두 제거하는 작은 예입니다.
List<String> list = new ArrayList<>();
list.add("Hello ");
list.add("World, ");
list.add("It's ");
list.add("Amigo!");
Iterator iterator = list.iterator();

while(iterator.hasNext()) {
   iterator.next();
   iterator.remove();
}
System.out.println(list.size());
콘솔에 다음이 표시됩니다.
0
이는 요소가 성공적으로 제거되었음을 의미합니다. 반복자를 얻은 후에는 화면에 모든 요소를 ​​표시하는 메서드를 사용할 수 있습니다.
iterator.forEachRemaining(x -> System.out.print(x));
그러나 일단 이렇게 하면 반복자는 더 이상 사용하기에 적합하지 않게 됩니다. 전체 목록을 순회했으며 일반 반복자에는 뒤로 반복할 수 있는 방법이 없습니다. 그리고 이는 LinkedList , 특히 향상된 유형의 반복자인 ListIterator 를 반환하는 listIterator() 메서드 대한 논의로 이어지는 멋진 부분입니다 . 일반(표준) 반복자의 메서드 외에도 이 종류에는 다음이 있습니다.
  • add(<Element>) — 목록에 새 요소를 추가합니다.

  • hasPrevious() — 다음 요소 앞에 요소가 있는 경우(이전 요소가 있는 경우) true를 반환합니다.

  • nextIndex() — 다음 요소의 인덱스를 반환합니다.

  • 이전() — 이전 요소(다음 요소 이전의 요소)를 반환합니다.

  • PreviousIndex는 이전 요소의 인덱스를 반환합니다.

  • set(<Element>) — next() 또는 이전() 이 반환한 마지막 요소를 대체합니다 .

보시다시피 이 반복자는 훨씬 더 흥미로운 기능을 가지고 있습니다. 즉, 양방향으로 이동할 수 있고 요소 작업 시 상당한 자유로움을 제공합니다. 사람들이 반복자에 관해 이야기할 때 때로는 디자인 패턴 자체를 의미한다는 점도 알아야 합니다. Java 개발자 직위에 대한 취업 면접의 질문과 답변을 살펴보세요.  파트 9 - 2

85. Java Collection Framework에는 어떤 컬렉션 계층이 존재합니까?

Java에는 두 가지 컬렉션 계층이 있습니다. 첫 번째 계층은 다음과 같은 구조를 갖는 컬렉션 계층입니다. Java 개발자 직위에 대한 취업 면접의 질문과 답변을 살펴보세요.  파트 9 - 3이는 다음과 같은 하위 컬렉션으로 나뉩니다.
  • Set은 순서가 지정되지 않은 고유한(반복되지 않는) 요소를 포함하는 데이터 구조인 집합을 설명하는 인터페이스입니다. 이 인터페이스에는 TreeSet , HashSetLinkedHashSet 과 같은 몇 가지 표준 구현이 있습니다 .

  • List 는 순서가 지정된 개체 시퀀스를 저장하는 데이터 구조를 설명하는 인터페이스입니다. 목록 의 개체는 목록의 인덱스에 따라 삽입 및 제거될 수 있습니다(배열과 유사하지만 동적 크기 조정이 가능함). 이 인터페이스에는 ArrayList , Vector ( 더 이상 사용되지 않으며 실제로 사용되지 않음 ) 및 LinkedList 와 같은 일부 표준 구현도 있습니다 .

  • 큐는 FIFO(선입선출) 큐 에 항목을 저장하는 데이터 구조를 설명하는 인터페이스입니다 . 이 인터페이스에는 LinkedList (맞습니다. Queue 도 구현함 ) 및 PriotityQueue 라는 표준 구현이 있습니다 .

두 번째 컬렉션 계층은 다음과 같은 구조를 갖는 Map 계층입니다. Java 개발자 직위에 대한 취업 면접의 질문과 답변을 살펴보세요.  파트 9 - 4이 컬렉션 계층은 하위 컬렉션으로 구분되지 않습니다( Map 계층 자체는 그 자체로 구별되는 하위 컬렉션이기 때문입니다). 표준 Map 구현은 Hashtable (더 이상 사용되지 않음), LinkedHashMapTreeMap 입니다 . 실제로 사람들이 Collections 에 대해 묻는 경우 일반적으로 두 계층을 모두 의미합니다. Java 개발자 직위에 대한 취업 면접의 질문과 답변을 살펴보세요.  파트 9 - 5

86. ArrayList의 내부 구조는 무엇입니까?

ArrayList 배열과 비슷하지만 동적으로 확장할 수 있습니다. 그게 무슨 뜻이에요? 내부적으로 ArrayList는 일반 배열을 사용합니다. 즉, 기본 크기가 10개 셀인 내부 배열에 해당 요소를 저장합니다. 내부 배열이 가득 차면 새 배열이 생성됩니다. 새 배열의 크기는 다음 공식으로 결정됩니다.
<size of the current array> * 3 / 2 + 1
따라서 배열의 크기가 10이면 새 배열의 크기는 10 * 3 / 2 + 1 = 16이 됩니다. 그러면 원래(이전) 배열의 모든 값이 내장된 배열을 사용하여 복사됩니다. System.arraycopy() 메서드를 사용하고 원래 배열은 삭제됩니다. 간단히 말해서 이것이 ArrayList가 동적 크기 조정을 구현하는 방식입니다. 가장 널리 사용되는 ArrayList 메서드를 고려해 보겠습니다 . 1. add(<Element>) — 먼저 배열에 사용 가능한 셀이 있는지 확인한 후 배열 끝(마지막 빈 셀)에 요소를 추가합니다. 그렇지 않은 경우 새 배열이 생성되고 해당 배열에 요소가 복사됩니다. 이 연산의 시간 복잡도는 O(1)입니다. 비슷한 add(<Index>, <Elelement>) 메서드가 있습니다 . 목록(배열)의 끝부분이 아닌 인자로 들어온 인덱스가 가리키는 특정 셀에 요소를 추가합니다. 이 경우 시간 복잡도는 추가하는 위치에 따라 달라집니다.
  • 추가가 목록의 시작 부분에 가까우면 시간 복잡도는 O(N)에 가까울 것입니다. 왜냐하면 새 요소의 오른쪽에 있는 모든 요소가 한 셀 오른쪽으로 이동해야 하기 때문입니다.
  • 요소가 중간에 삽입되면 목록 항목의 절반만 오른쪽으로 한 셀 이동하면 되므로 O(N/2)가 됩니다.
즉, 이 방법의 시간 복잡도는 요소가 삽입되는 위치에 따라 O(1)에서 O(N)까지 다양합니다. 2. set(<Index>, <Element>) — 목록의 지정된 위치에 요소를 씁니다. 요소가 해당 위치에 이미 있으면 메서드가 해당 요소를 덮어씁니다. 이 작업의 시간 복잡도는 O(1)입니다. 이는 시프트 작업이 포함되지 않기 때문입니다. 인덱스를 사용하여 복잡도가 O(1)인 배열의 셀 주소를 계산한 다음 새 요소를 씁니다. . 3. 제거(<index>) — 내부 배열의 인덱스를 기준으로 요소를 제거합니다. 목록 끝에 없는 항목을 제거하는 경우 삭제로 인해 발생하는 간격을 줄이기 위해 삭제된 항목 오른쪽에 있는 모든 항목을 한 셀 왼쪽으로 이동해야 합니다. 따라서 중간에 요소를 추가하면 시간 복잡도는 add(<Index>, <Element>) 와 동일해 O(N/2)가 됩니다 . 결국 요소의 절반을 한 셀 왼쪽으로 이동해야 합니다. 그리고 시작에 대해 이야기한다면 O(N)입니다. 또는 마지막에 있다면 아무 것도 이동할 필요가 없으므로 O(1)입니다.

87. LinkedList의 내부 구조는 무엇입니까?

ArrayList 에는 내부 배열의 요소가 포함되어 있지만 LinkedList는 해당 요소 를 이중 연결 목록에 저장합니다. 즉, 각 요소에는 이전 요소와 다음 요소에 대한 링크가 포함되어 있습니다. 첫 번째 요소는 이전 요소에 연결되지 않습니다(결국 첫 번째 요소임). 이는 또한 목록의 헤드로 간주되며 LinkedList 개체는 이를 직접 참조합니다. 마찬가지로 마지막 요소는 목록의 꼬리이므로 다음 요소를 갖지 않습니다. LinkedList 개체 이를 직접 참조합니다. 이는 목록의 헤드 또는 테일에 액세스하는 시간 복잡도가 O(1)임을 의미합니다. ArrayList 에서 목록이 커지면 내부 배열도 커집니다. 여기에서는 모든 것이 더 쉽습니다. 참조를 추가하는 것은 링크 몇 개를 변경하는 것만큼 간단합니다. 가장 많이 사용되는 LinkedList 메소드 중 일부를 살펴보겠습니다 . 1. add(<Element>) — 목록 끝에 요소를 추가합니다. 즉, 마지막 요소(5) 뒤에 새 요소에 대한 링크가 다음으로 추가됩니다. . 새 요소의 이전 참조는 이제 목록에서 앞에 있는 요소(5)를 가리킵니다. 이 작업의 시간 복잡도는 O(1)입니다. 왜냐하면 마지막 요소에 대한 링크만 필요하고, 기억하시겠지만 LinkedList 개체는 꼬리에 대한 직접 참조를 가지며 이에 액세스하는 데 최소한의 일정한 시간 복잡도가 있습니다. 2. add(<Index>, <Element>) — 인덱스별로 요소를 추가합니다. 예를 들어 목록 중간에 요소를 추가할 때 이 메서드는 먼저 원하는 위치를 찾을 때까지 머리와 꼬리(양방향)에서 요소를 반복합니다. 위 그림에서 세 번째 요소와 네 번째 요소 사이에 요소를 추가하면 세 번째 요소의 다음 링크가 새 요소를 가리킵니다. 그리고 새로 추가된 요소 중 이전 요소는 세 번째 요소를 가리킵니다. 결과적으로 이전 네 번째 요소의 이전 링크는 이제 새 요소를 가리키고 새 요소의 다음 링크는 새로운 네 번째 요소를 가리킵니다. 이 메서드의 시간 복잡도는 새 요소의 인덱스에 따라 달라집니다.Java 개발자 직위에 대한 취업 면접의 질문과 답변을 살펴보세요.  파트 9 - 6Java 개발자 직위에 대한 취업 면접의 질문과 답변을 살펴보세요.  파트 9 - 7
  • 머리나 꼬리에 가까우면 실제로 요소를 반복할 필요가 없기 때문에 작업은 O(1)에 접근합니다.
  • 중간에 가까우면 O(N/2)가 됩니다. 왜냐하면 이 메서드는 원하는 요소를 찾을 때까지 머리와 꼬리에서 동시에 검색하기 때문입니다.
3. set(<Index>, <Element>) — 목록의 지정된 위치에 요소를 씁니다. 이 작업의 시간 복잡도는 O(1)에서 O(N/2)까지이며, 새 요소가 머리, 꼬리 또는 중앙에 얼마나 가까운지에 따라 달라집니다. 4. 제거(<index>) — 삭제된 요소 앞의 요소( previous )가 삭제된 요소 뒤의 요소( next )를 참조하도록 하여 목록에서 요소를 제거합니다. 그 반대도 마찬가지입니다. 즉, 삭제된 요소 뒤의 요소는 이제 삭제된 요소 이전의 요소를 참조합니다. Java 개발자 직위에 대한 취업 면접의 질문과 답변을 살펴보세요.  파트 9 - 8이 프로세스는 인덱스로 추가하는 것과 반대입니다( add(<Index>, <Element>) ).

88. HashMap의 내부 구조는 무엇입니까?

이는 Java 개발자 지원자에게 묻는 가장 인기 있는 인터뷰 질문 중 하나일 수 있습니다. HashMap키-값 쌍 으로 작동합니다 . HashMap 자체 에는 어떻게 저장되나요 ? HashMap 에는 내부 노드 배열이 있습니다.
Node<K,V>[] table
기본적으로 배열의 크기는 16이고 요소로 채워질 때마다 두 배로 늘어납니다(즉, LOAD_FACTOR에 도달 하면 배열이 얼마나 가득 찰 수 있는지에 대한 임계값을 지정합니다. 기본적으로 0.75 입니다 ). . 각 노드는 키의 해시, 키, 값 및 다음 요소에 대한 참조를 저장합니다. Java 개발자 직위에 대한 취업 면접의 질문과 답변을 살펴보세요.  파트 9 - 9이 경우 "다음 요소에 대한 참조"는 단일 연결 목록을 처리한다는 의미입니다. 각 요소에는 다음 요소에 대한 링크가 포함되어 있습니다. 즉, HashMap은 단일 연결 목록 배열에 데이터를 저장합니다. 그러나 테이블 배열의 셀에 둘 이상의 요소로 구성된 단일 연결 목록이 있는 경우에는 좋지 않다는 점을 바로 말씀드리겠습니다 . 이 현상을 충돌 이라고 합니다 . 하지만 가장 먼저 해야 할 일이 있습니다. put 메소드를 사용하여 새 쌍이 어떻게 저장되는지 살펴보겠습니다 . 먼저 이 메서드는 키의 hashCode() 를 가져옵니다 . 이는 HashMap 이 올바르게 작동하려면 사용하는 키가 이 메서드를 재정의하는 클래스여야 함을 의미합니다. 그런 다음 이 해시 코드는 내부 hash() 메서드에서 사용되어 테이블 배열 내 일부 셀의 인덱스를 결정합니다. 결과 인덱스를 사용하면 테이블 배열의 특정 셀에 액세스할 수 있습니다. 여기에는 두 가지 경우가 있습니다.
  1. 셀은 비어 있습니다. 이 경우 새 Node 값이 셀에 저장됩니다.
  2. 셀이 비어 있지 않습니다. 이 경우 키 값이 비교됩니다. 동일하면 새 Node 값이 이전 값을 덮어씁니다. 같지 않으면 다음 항목에 액세스 하고 해당 키를 비교합니다. 새 값이 이전 값을 덮어쓰거나 단일 연결 목록의 끝에 도달한 다음 새 값을 거기에 저장합니다. 마지막 요소.
키로 요소를 검색하는 경우( get(<key>) 메서드 사용) 키의 hashCode()가 계산된 다음 hash() 를 사용하여 배열 내의 해당 인덱스가 계산됩니다 . 결과 숫자는 테이블 배열 에 있는 셀의 인덱스이며 , 그런 다음 노드를 반복하고 원하는 노드의 키를 현재 노드의 키와 비교하여 검색합니다. 이상적으로 Map 연산은 배열에 액세스하기 때문에 O(1)의 알고리즘 복잡도를 가지며, 기억하시겠지만 배열에 포함된 요소 수에 관계없이 O(1)입니다. 그러나 우리는 이상적인 경우를 다루고 있지 않습니다. 셀이 비어 있지 않고(2) 이미 일부 노드를 저장한 경우 알고리즘 복잡성은 O(N)(선형)이 됩니다. 이제 올바른 위치를 찾기 전에 요소를 반복해야 하기 때문입니다. Java 8부터 단일 연결 목록 형태의 노드에 8개 이상의 요소(충돌)가 있는 경우 이진 트리로 변환된다는 점을 언급하지 않을 수 없습니다. 이 경우 알고리즘의 복잡성은 더 이상 O(N)이 아니라 O(log(N))입니다. 그리고 그것은 완전히 다른 문제입니다. 그렇지 않습니까? Java 개발자 직위에 대한 취업 면접의 질문과 답변을 살펴보세요.  파트 9 - 10HashMap 은 큰 주제이며 사람들은 취업 면접에서 이에 대해 질문하는 것을 좋아합니다. 그러니 손등처럼 알아두시길 권합니다. 개인적으로 저는 HashMap 에 질문이 포함되지 않은 인터뷰를 본 적이 없습니다 . 오늘은 그게 다야. 계속하려면 ...