CodeGym /Java Blog /무작위의 /Java 개발자 직위에 대한 취업 면접의 질문과 답변을 살펴보세요. 10부
John Squirrels
레벨 41
San Francisco

Java 개발자 직위에 대한 취업 면접의 질문과 답변을 살펴보세요. 10부

무작위의 그룹에 게시되었습니다
안녕! 어떤 일에 능숙해지려면 몇 시간이 걸리나요? 나는 종종 다음과 같은 말을 들었습니다. "무엇이든 마스터하려면 10,000시간을 투자해야 합니다." 정말 위협적인 숫자죠? Java 개발자 직위에 대한 취업 면접의 질문과 답변을 살펴보세요.  파트 10 - 1그래도 그게 사실인지 궁금하네요. 그리고 나는 프로그래밍 기술을 익히는 데 이미 얼마나 많은 시간을 투자했는지 끊임없이 파악하려고 노력하고 있습니다. 그리고 그 1만시간이라는 특별한 선을 넘어 마스터가 되면 과연 변화를 느낄 수 있을까요? 아니면 이미 오래전에 나도 모르게 그 선을 넘은 걸까? 어느 쪽이든 프로그래머가 되기 위해 그렇게 많은 시간을 투자할 필요는 없습니다. 중요한 것은 시간을 현명하게 사용하는 것입니다. 귀하의 주요 목표는 인터뷰를 얻는 것입니다. 그리고 인터뷰에서 소프트웨어 개발자 지망생들은 먼저 이론에 대한 질문을 받기 때문에 그것이 강점이 되어야 합니다. 실제로 인터뷰를 준비할 때 귀하의 임무는 기본 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) 이며 삽입이 목록 끝에 가까울수록 속도가 빨라집니다. 요소 설정(세트) 이 작업은 목록의 지정된 위치에 요소를 쓰고 기존 요소를 덮어씁니다. LinkedList 에서 이 작업은 추가와 유사합니다. 여기서 가장 큰 과제는 요소의 위치를 ​​찾는 것이기 때문입니다. 기존 요소는 한 쌍의 참조를 업데이트하여 덮어쓰므로 목록의 끝이나 시작에서 원하는 위치의 거리에 따라 O(1) 에서 O(n/2) 까지 다양한 알고리즘 복잡도를 갖게 됩니다. 그러나 ArrayList 의 경우 이 작업은 인덱스로 원하는 셀을 찾고 거기에 새 요소를 씁니다. 집합 연산과 마찬가지로 인덱스로 검색하는 경우 알고리즘 복잡도는 O(1) 입니다 . 인덱스로 요소 가져오기(get) LinkedList 에서 요소 가져오기는 다른 작업에 사용되는 것과 동일한 검색 원칙을 따릅니다. 복잡성은 끝이나 시작으로부터의 거리에 따라 달라집니다. 즉, O(1) 에서 O(n/2) 까지 다양합니다 . 앞서 언급했듯이 ArrayList 의 경우 내부 배열에서 인덱스로 요소를 찾는 것은 O(1) 의 복잡성을 갖습니다 . 인덱스로 요소 제거(제거) LinkedList 의 경우 동일한 원칙이 다시 한 번 적용됩니다. 먼저 요소를 찾은 다음 참조를 다시 작성하면 삭제된 요소의 이웃이 이제 서로를 참조하여 삭제된 요소에 대한 참조가 제거되고 이후에 가비지 수집기에 의해 정리됩니다. 즉, 알고리즘의 복잡성은 여전히 ​​동일합니다. 즉, O(1) 에서 O(n/2) 까지 다양합니다 . ArrayList 의 경우 이 작업은 새 요소 추가(추가)와 비슷합니다. 먼저 원하는 요소( 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는 null 값을 얼마든지 허용하지만 HashSet에는 하나의 null 값만 추가할 수 있습니다 ( 결국 요소는 고유해야 합니다).

91. Java에는 왜 그렇게 다양한 동적 배열 구현이 있습니까?

이것은 철학적인 질문에 가깝습니다. 우리는 또한 그들이 왜 그렇게 많은 새롭고 다양한 기술을 생각해 내는지 물어볼 수도 있습니다. 편의상. 그리고 많은 수의 동적 배열 구현에 대해서도 마찬가지입니다. 그 중 어느 것도 최고 또는 이상적인 구현이라고 할 수 없습니다. 각각은 특정 상황에 따른 장점을 가지고 있습니다. 우리의 임무는 주어진 상황에 가장 적합한 컬렉션을 사용할 수 있도록 차이점과 강점/약점을 아는 것입니다.

92. Java에는 왜 그렇게 다양한 키-값 저장 구현이 있습니까?

여기서 상황은 동적 배열 구현과 동일합니다. 다른 것보다 보편적으로 더 나은 것은 확실히 없습니다. 각 것에는 강점과 약점이 있습니다. 물론 우리는 그들의 강점을 최대한 활용해야 합니다. 예: 다중 스레드 클래스가 많은 동시 패키지에는 자체 Concurrent 컬렉션이 있습니다. ConcurrentHashMap 클래스 는 다중 스레드 환경에서 데이터로 작업할 때 안전성 측면에서 표준 HashMap 에 비해 이점이 있지만 성능이 저하되는 단점이 있습니다. 그리고 어떤 상황에서도 최선의 선택이 아닌 구현은 점차 사용이 중단됩니다. 예를 들어 원래 스레드로부터 안전한 HashMap 으로 의도된 Hashtable 은 잊어버리고 사용하지 않게 되었습니다. 왜냐하면 ConcurrentHashMap 은 다중 스레드 환경에서 작업할 때 Hashtable 보다 훨씬 낫기 때문입니다 .

93. 요소 모음을 어떻게 정렬합니까?

가장 먼저 말해야 할 것은 컬렉션 요소를 나타내는 클래스는 CompareTo 메서드 로 구성된 Comparable 인터페이스를 구현해야 한다는 것입니다 . 또는 비교 메서드 를 포함하여 Comparator 인터페이스를 구현하는 클래스가 필요합니다 . 두 방법 모두 주어진 유형의 객체를 비교하는 방법을 나타냅니다. 이는 정렬 시 매우 중요합니다. 정렬 알고리즘은 요소를 비교하는 데 사용할 원칙을 이해해야 하기 때문입니다. 이는 주로 정렬하려는 클래스에서 직접 Comparable을 구현하여 수행됩니다. 비교기를 사용하는 것은 덜 일반적입니다. 일부 라이브러리의 클래스를 사용하고 있고 해당 클래스가 Comparable 을 구현하지 않지만 해당 개체 컬렉션을 정렬해야 한다고 가정해 보겠습니다. 이 클래스의 코드는 확장을 제외하고 변경할 수 없으므로 클래스의 개체를 비교하는 방법을 나타내는 Comparator 구현을 작성할 수 있습니다 . 그리고 또 하나의 예입니다. 동일한 유형의 객체를 다른 방식으로 정렬해야 하는 경우 다양한 상황에서 사용할 여러 Comparator 구현을 작성할 수 있습니다 . 일반적으로 String 과 같은 많은 기본 클래스는 이미 Comparable 인터페이스를 구현합니다. 즉, 이러한 클래스를 비교하는 방법에 대해 걱정할 필요가 없습니다. 그냥 가서 사용할 수 있습니다. 첫 번째 이자 가장 확실한 방법은 TreeSet 또는 TreeMap 클래스를 사용하는 것입니다. 이러한 클래스는 클래스 요소에 의해 구현된 비교기에 따라 정렬된 순서로 요소를 저장합니다. TreeMap은 값이 아닌 키를 정렬한다는 점을 잊지 마세요 . Comparable 대신 Comparator를 사용하는 경우 컬렉션을 생성할 때 컬렉션 생성자에 Comparator 개체를 전달해야 합니다 .
TreeSet treeSet = new TreeSet(customComparator);
하지만 다른 유형의 컬렉션이 있다면 어떨까요? 어떻게 정렬하나요? 이 경우 Collections 유틸리티 클래스의 두 번째 방법인 sort() 메서드가 적합합니다. 메서드는 정적이므로 클래스 이름을 앞에 붙인 다음 정렬할 목록을 전달하기만 하면 됩니다. 예를 들어:
Collections.sort(someList);
Comparable 대신 Comparator 구현을 사용하는 경우 이를 두 번째 인수로 전달해야 합니다.
Collections.sort(someList, customComparator);
이 작업은 전달된 목록에 있는 요소의 내부 순서를 변경합니다. 목록은 비교기를 사용하여 정렬됩니다. 전달된 목록은 변경 가능해야 합니다. 그렇지 않으면 메서드가 실패하고 UnsupportedOperationException이 발생 합니다 . 세 번째 옵션은 컬렉션의 요소를 정렬하는 Stream 클래스의 sorted 메서드를 사용하는 것입니다 . Comparable을 사용하는 경우 :
someList = someList.stream().sorted().collect(Collectors.toList());
비교기를 사용하는 경우 :
someList = someList.stream().sorted(customComparator).collect(Collectors.toList());
번째 방법은 버블 정렬 또는 병합 정렬과 같은 정렬 알고리즘을 수동으로 구현하는 것입니다 .

객체 클래스. 같음() 및 hashCode()

94. 자바의 Object 클래스에 대해 간략하게 설명해주세요.

검토의 두 번째 부분 에서는 이미 Object 클래스의 메서드에 대해 논의했습니다. 여기서는 Object 클래스가 Java의 모든 클래스의 조상이라는 점을 상기시켜 드리겠습니다 . 여기에는 11개의 메서드가 있으며 이는 모든 클래스에서 상속됩니다. Java 개발자 직위에 대한 취업 면접의 질문과 답변을 살펴보세요.  파트 10 - 3

95. Java에서 equals()와 hashCode()는 무엇을 위해 사용되나요?

hashCode() 는 모든 클래스에 상속되는 Object 클래스 의 메서드입니다 . 그 임무는 특정 개체를 나타내는 숫자를 생성하는 것입니다. 실행 중인 이 메소드의 예는 HashMap 에서 찾을 수 있습니다. 여기서 이 메소드는 키-값 쌍이 저장될 버킷(내부 배열의 셀)을 결정하는 로컬 해시코드를 얻기 위해 키 객체에 대해 호출됩니다. 또한, 이 메서드는 일반적으로 객체를 식별하는 주요 방법 중 하나로 equals() 메서드 에서 사용됩니다 . equals() 는 객체를 비교하고 동일한지 여부를 확인하는 작업을 수행하는 Object 클래스 의 메서드입니다 . 이 방법은 객체를 비교해야 하는 모든 곳에서 사용됩니다. 표준 == 비교 연산자는 객체 참조만 비교하기 때문에 객체에 적합하지 않기 때문입니다.

96. Java에서 equals()와 hashCode() 사이의 계약에 대해 알려주십시오.

먼저, equals()hashCode() 메서드가 올바르게 작동하려면 올바르게 재정의되어야 합니다. 새로운 구현은 다음 규칙을 따라야 합니다.
  • 같음이 true를 반환하는 동일한 개체는 동일한 해시 코드를 가져야 합니다 .
  • 동일한 해시 코드를 가진 객체가 반드시 동일하지는 않습니다.
이제 리뷰의 다음 부분까지 잠시 멈추기에 좋은 것 같습니다!
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION