스케치 1. “간단해 보이는 방법”
숫자 a를 숫자 b로 나눈 결과를 반환하는 메서드를 구현하는 방법을 적습니다. 면접관은 종이에 씁니다.int divide(int a, int b) {
}
*나는 메소드 서명이 적힌 종이를 믿을 수 없다는 듯이 쳐다보았습니다. 문제는 무엇입니까?* 나는 다음과 같이 씁니다:
int divide(int a, int b) {
return a/b;
}
이 방법에 문제가 있나요? *정말 멍청한 멍청이를 잡았습니다* 분명히 그렇지 않습니다. 다음은 타당한 질문입니다. b=0이면 어떨까요? *아, 이대로 계속하다간 이 사무실에서 쫓겨날 뻔!* 아, 물론이죠. 여기에는 int 유형의 인수가 있으므로 산술 예외가 발생합니다. 인수가 float 또는 double 유형인 경우 결과는 Infinity입니다. 이에 대해 우리는 무엇을 할 것인가? try/catch를 쓰기 시작했습니다.
int divide(int a, int b) {
try {
return a/b;
} catch (Exception e) {
e.printStackTrace();
return ... // ??? what the hack?
}
}
*반품하고 멈춥니다. 오류가 발생하면 뭔가를 반납해야 합니다. 하지만 이 “무엇”이 계산 결과와 어떻게 구별될 수 있습니까?* 우리는 무엇을 반환할 것입니까? 흠... 반환 변수의 유형을 Integer로 변경하고 예외가 발생하면 null을 반환합니다. 유형을 변경할 수 없다고 상상해 봅시다. 우리 어떻게든 나갈 수 있을까? 어쩌면 예외를 제외하고 다른 일을 할 수 있을까요? *여기에 있습니다* 호출 메소드로 전달할 수도 있습니다! 오른쪽. 어떤 모습일까요?
int divide(int a, int b) throws ArithmeticException{
return a/b;
}
void callDivide(int a, int b) {
try {
divide(a, b);
} catch (ArithmeticException e) {
e.printStackTrace();
}
}
예외를 처리해야 합니까? 예, Divide 메서드에서 명시적으로 전달하기 때문입니다. (*제가 틀렸습니다! 정답에 도달하기 위한 면접관의 주요 질문은 다음과 같습니다*) 그리고 산술 예외(Arithmetic Exception) - 어떤 종류의 예외가 선택되었는지 또는 선택되지 않았습니까? 이는 런타임 예외이며 선택 취소됨을 의미합니다. *여기에 킬러 질문이 있습니다* 그래서 우리가 메소드 시그니처에 산술 예외 throw를 지정하면 확인된 예외가 된다는 것이 밝혀졌습니다. *으윽!* 아마도... 아뇨. 예, 사라졌습니다. 서명에 /unchecked 예외 발생/을 표시하면 메서드가 예외를 throw할 수 있다는 경고만 하지만 호출 메서드에서 이를 처리할 필요는 없습니다. 정리되었습니다. 실수를 피하기 위해 우리가 할 수 있는 다른 일이 있습니까? *생각해 본 후에* 예, (b==0)인지 확인할 수도 있습니다. 그리고 몇 가지 논리를 수행하십시오. 오른쪽. 따라서 우리는 3가지 방법으로 갈 수 있습니다:
- 시도/잡기
- throws - 호출 메서드로 전달
- 인수 검사
divide
어떤 방식이 더 바람직하다고 생각하시나요? 나는 예외를 호출 메서드에 전달하기로 선택합니다. 왜냐하면... int
나누기 메서드에서는 이 예외를 처리하는 방법과 오류 발생 시 반환할 결과 유형이 명확하지 않습니다 . 그리고 호출 메서드에서는 b 인수를 사용하여 0과 같은지 확인합니다. 이 답변이 인터뷰 대상자를 만족시킨 것 같지만, 솔직히 이 답변이 명확한지 잘 모르겠습니다.))
스케치 2. “누가 더 빠르나요?”
ArrayList와 LinkedList의 차이점에 대한 표준 질문 후에 다음과 같은 결과가 나왔습니다. 요소를 중간에 삽입하는 것,ArrayList
아니면 중간에 삽입하는 것 중 어떤 일이 더 빨리 일어날까요 LinkedList
? *여기서 나는 뛰어내렸고, " 목록 중간에 요소를 삽입하거나 제거하는 데 사용합니다."와 같은 내용을 어디에서나 읽었던 것을 기억했습니다 . LinkedList
집에서 JavaRush 강의를 다시 확인해도 다음과 같은 문구가 있습니다. “컬렉션 중간에 많은 요소를 삽입(또는 삭제)하려면 LinkedList
. 그 밖의 모든 경우에는 - ArrayList
.” 자동 응답* 을 사용하면 더 빨라집니다 LinkedList
. 명확히 해주세요
- 중간에 요소를 삽입하려면
ArrayList
일정한 시간에 목록에서 요소를 찾은 다음 삽입되는 요소의 오른쪽에 있는 요소의 인덱스를 선형 시간으로 다시 계산합니다. - .. 먼저
LinkedList
선형 시간의 중간에 도달한 다음 일정한 시간에 요소를 삽입하여 인접한 요소에 대한 링크를 변경합니다.
LinkedList
더 빨라지나요? 목록의 전반부에 삽입하면 결과가 나타납니다. 예를 들어 맨 처음에 삽입하면 ArrayList
맨 끝 부분까지 모든 인덱스를 다시 계산해야 하지만 LinkedList
첫 번째 요소의 참조만 변경하면 됩니다. 도덕적: JavaRush에서도 쓰여진 모든 것을 말 그대로 믿지 마십시오!)
스케치 3. "등호와 해시코드가 없다면 우리는 어디에 있을까요!"
같음과 해시코드에 대한 대화는 매우 길었습니다. 이를 재정의하는 방법, 에 구현이 무엇인지Object
, 내부적으로 어떤 일이 발생하는지, 요소가 에 삽입될 때 HashMap
등이 있었습니다. 제 생각에는 흥미로운 점 몇 가지만 말씀드리겠습니다. * 우리가 클래스를 만들었다고 상상해 보세요.
public class A {
int id;
public A(int id) {
this.id = id;
}
}
그리고 그들은 equals
및 hashcode
. 코드가 실행되면 어떤 일이 일어날지 설명하세요.
A a1 = new A(1);
A a2 = new A(1);
Map<A, String> hash = new HashMap<>();
hash.put(a1, "1");
hash.get(a2);
*인터뷰 전에 기본 알고리즘, 복잡성 및 데이터 구조를 이해하는 데 며칠을 투자한 것은 좋은 일입니다. 많은 도움이 되었습니다. CS50에게 감사드립니다!*
-
클래스 A의 두 인스턴스 만들기
-
기본적으로 16개의 바구니가 있는 빈 맵을 만듭니다.
equals
키는 및 메소드가 재정의되지 않은 클래스 A의 객체입니다hashcode
. -
a1
지도에 넣으세요 . 이를 위해 먼저 해시를 계산합니다a1
.해시는 무엇과 동일합니까?
메모리에 있는 셀의 주소는 클래스의 메소드 구현입니다.
Object
-
해시를 기반으로 바구니 지수를 계산합니다.
어떻게 계산할 수 있나요?
*아쉽게도 여기서는 명확한 답변을 드리지 못했습니다. 해시가 있고 버킷이 16개 있는 긴 숫자가 있습니다. 서로 다른 해시를 가진 객체가 버킷에 고르게 분산되도록 인덱스를 정의하는 방법은 무엇입니까? 인덱스가 다음과 같이 계산된다고 상상할 수 있습니다.
int index = hash % buckets.length
이미 집에서 소스 코드의 원래 구현이 약간 다르다는 것을 확인했습니다.
static int indexFor(int h, int length) { return h & (length - 1); }
-
충돌이 없는지 확인하고 a1을 삽입합니다.
-
방법으로 넘어 갑시다
get
. 인스턴스 a1과 a2는 서로 다른(메모리의 다른 주소) 것을 보장하므로hash
이 키에 대해 아무것도 찾을 수 없습니다.클래스 A 에서만 재정의하고
hashcode
먼저 키 a1과 키 a2를 사용하여 해시맵에 쌍을 삽입하려고 하면 어떻게 될까요?그런 다음 먼저 원하는 바구니를 찾습니다
hashcode
. 이 작업은 올바르게 수행됩니다.Entry
다음으로 카트에 연결된 LinkedList의 개체를 살펴보고 키를 비교해 보겠습니다equals
. 왜냐하면equals
재정의되지 않은 경우 기본 구현은 클래스에서 가져옵니다Object
(참조별 비교). a1과 a2는 서로 다른 링크를 가지도록 보장되므로 삽입된 요소 a1을 "누락"하고 a2는 LinkedList에 새 노드로 배치됩니다.결론은 무엇입니까?
HashMap
재정의되지 않은 객체 의 키로 사용할 수 있습니까equalshashcode
?아니 당신은 할 수 없습니다.
스케치 4. “일부러 부수자!”
오류 및 예외에 대한 질문 후에 다음 질문이 이어졌습니다. 함수가 StackOverflow를 발생시키는 간단한 예제를 작성하세요. *그런 다음 재귀 함수를 작성하려고 할 때 이 오류가 나를 얼마나 괴롭혔는지 기억했습니다.* 이는 재귀 호출의 경우 재귀 종료 조건이 잘못 지정되면 아마도 발생할 수 있습니다. *이후 나는 조금 영리해지기 시작했고 결국 면접관의 도움을 받아 모든 것이 간단하다는 것이 밝혀졌습니다*void sof() {
sof();
}
이 오류는 와 어떻게 다릅니까 OutOfMemory
? *여기서는 대답하지 않았습니다. 나중에 이것이 Java 메모리 Stack
에 대한 지식에 관한 질문이라는 것을 깨달았습니다 Heap
(객체에 대한 호출 및 참조는 스택에 저장되고 객체 자체는 힙 메모리에 저장됩니다). Stack
따라서 다음 메소드 호출을 위해 메모리 에 더 이상 공간이 없고 , 메모리 OutOfMemory
에서 객체를 위한 공간이 부족해지면 StackOverflow가 던져집니다 Heap
.*
제가 기억하는 인터뷰의 순간들입니다. 결국 인턴십에 합격했기 때문에 앞으로 2.5 개월의 교육을 받고 모든 것이 잘되면 회사에 취직하게됩니다.) 관심이 있으면 이번에는 더 작은 기사를 쓸 수 있습니다. 다른 회사에서 면접을 본 간단하지만 예시적인 문제에 대한 분석입니다. 저는 이것이 전부입니다. 이 기사가 누군가가 지식을 심화하거나 정리하는 데 도움이 되기를 바랍니다. 모두들 즐겁게 배우세요!
GO TO FULL VERSION