
89. ArrayList는 LinkedList와 어떻게 다릅니까?
이것은 HashMap 내부 구조에 대한 질문과 함께 가장 인기 있는 질문 중 하나입니다 . 그것 없이는 인터뷰가 완료되지 않으므로 답변이 쉽게 혀에서 흘러 나올 것입니다. 명백한 것(이름이 다름) 외에도 내부 구조도 다릅니다. 앞서 ArrayList 와 LinkedList 의 내부 구조에 대해 논의했으므로 구현 세부 사항은 다루지 않겠습니다. ArrayList는 다음 공식에 따라 크기가 동적으로 증가하는 내부 배열을 사용하여 구현된다는 점을 상기시켜 드리겠습니다 .<size of the current array> * 3 / 2 + 1
또한 LinkedList 구현에서는 내부 이중 연결 목록을 사용합니다. 즉, 목록의 시작과 끝에 있는 요소를 제외하고 각 요소에는 이전 요소와 다음 요소에 대한 참조가 있습니다. 면접관들은 " ArrayList 와 LinkedList 중 어느 것이 더 낫습니까 ?" 와 같은 질문을 좋아합니다. 당신을 잡기를 바라고 있습니다. 결국 둘 중 하나가 더 낫다고 말하면 잘못된 대답을 한 것입니다. 
-
색인을 지정하지 않으면 두 종류의 목록 모두 끝에 새 항목이 자동으로 추가됩니다. LinkedList 에서 새 요소는 새 꼬리가 됩니다(한 쌍의 참조만 다시 작성되므로 알고리즘 복잡도는 O(1) 입니다 ).
add 메소드는 배열의 마지막 빈 셀( O(1) )에 요소를 추가합니다.
-
색인으로 항목을 추가한다는 것은 일반적으로 목록 중간에 항목을 삽입하는 것을 의미합니다. LinkedList 에서 메서드는 먼저 꼬리와 머리( O(n/2) ) 의 요소를 반복하여 원하는 위치를 검색한 다음 양쪽에 있는 요소의 참조를 덮어써서 값을 삽입합니다. 새 요소가 삽입됩니다( O(1) ). 이 연산의 전반적인 알고리즘 복잡성은 O(n/2) 입니다 .
동일한 상황(인덱스로 추가)에서 ArrayList는 원하는 위치( O(1) )를 찾은 다음 오른쪽에 있는 모든 요소(지정된 인덱스에 이미 저장된 요소 포함)를 오른쪽으로 하나씩 이동합니다. 새로운 내부 배열을 생성하고 여기에 요소를 복사해야 할 수도 있습니다( O(n/2) ). 전체 복잡도는 O(n/2) 입니다 .
-
LinkedList 의 시작 부분에 요소를 추가하는 것은 끝에 요소를 추가하는 것과 유사합니다. 새 요소가 새 헤드( O(1) )가 됩니다. 그러나 ArrayList의 경우 해당 작업을 수행하려면 모든 요소를 오른쪽으로 이동해야 합니다( O(n) ).
90. ArrayList는 HashSet과 어떻게 다릅니까?
ArrayList 와 LinkedList를 작업별로 비교하여 어느 것이 더 나은지 결정할 수 있다면 ArrayList 와 HashSet 은 완전히 다른 컬렉션이기 때문에 비교하기가 쉽지 않을 것입니다 . 하나의 디저트를 다른 디저트와 비교할 수는 있지만, 디저트와 맛있는 요리를 비교하는 것은 어려운 일입니다. 둘은 고통스러울 정도로 다릅니다. 그래도 나는 그들 사이의 몇 가지 차이점을 지적하려고 노력할 것입니다.-
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개의 메서드가 있으며 이는 모든 클래스에서 상속됩니다.
95. Java에서 equals()와 hashCode()는 무엇을 위해 사용되나요?
hashCode() 는 모든 클래스에 상속되는 Object 클래스 의 메서드입니다 . 그 임무는 특정 개체를 나타내는 숫자를 생성하는 것입니다. 실행 중인 이 메소드의 예는 HashMap 에서 찾을 수 있습니다. 여기서 이 메소드는 키-값 쌍이 저장될 버킷(내부 배열의 셀)을 결정하는 로컬 해시코드를 얻기 위해 키 객체에 대해 호출됩니다. 또한, 이 메서드는 일반적으로 객체를 식별하는 주요 방법 중 하나로 equals() 메서드 에서 사용됩니다 . equals() 는 객체를 비교하고 동일한지 여부를 확인하는 작업을 수행하는 Object 클래스 의 메서드입니다 . 이 방법은 객체를 비교해야 하는 모든 곳에서 사용됩니다. 표준 == 비교 연산자는 객체 참조만 비교하기 때문에 객체에 적합하지 않기 때문입니다.96. Java에서 equals()와 hashCode() 사이의 계약에 대해 알려주십시오.
먼저, equals() 및 hashCode() 메서드가 올바르게 작동하려면 올바르게 재정의되어야 합니다. 새로운 구현은 다음 규칙을 따라야 합니다.- 같음이 true를 반환하는 동일한 개체는 동일한 해시 코드를 가져야 합니다 .
- 동일한 해시 코드를 가진 객체가 반드시 동일하지는 않습니다.
GO TO FULL VERSION