728x90
반응형
Java List 복사와 참조의 차이
주어진 graph에서 start node에서 end node로 갈 수 있는 모든 path를 구하는 코딩테스트 문제를 푸는 와중에 논리 오류(Logical Error)를 맞닥뜨렸다.
List 복사 시 발생한 오류인데, 그에 관한 내용을 정리해 본다.
- 논리 오류가 발생한 코드
- start node 0에서 end node 4로 가기 위한 path를 구해보겠습니다.
- 첫 번째 path인 [0, 1, 4]를 구하여 answer.add(path); 해주었습니다.
- 두 번째 path인 [0, 3, 4]를 구하여 answer.add(path); 해주었습니다.
- answer을 출력해 보았습니다.
- 기대한 값은 [[0, 1, 4], [0, 3, 4]]이었으나,,,
- 실제로는 [[0, 3, 4], [0, 3, 4]]가 출력되었습니다.
- 어디가 문제일까요??
List<List<Integer>> answer = new ArrayList<>();
List<Integer> path = new ArrayList<>();
// path #1
path.add(0);
path.add(1);
path.add(4);
answer.add(path);
// path = [0, 1, 4]
System.out.println("path = " + path);
// answer = [[0, 1, 4]]
System.out.println("answer = " + answer);
// path #2
path.remove(2);
path.remove(1);
path.add(3);
path.add(4);
answer.add(path);
// path = [0, 3, 4]
System.out.println("path = " + path);
// 논리 오류 발생!!
// 기대 출력 값 : answer = [[0, 1, 4], [0, 3, 4]]
// 실제 출력 값 : answer = [[0, 3, 4], [0, 3, 4]]
System.out.println("answer = " + answer);
- 논리 오류를 해결한 코드
- answer.add(path) 대신 answer.add(new ArrayList<>(path)) 를 사용한다.
- 실제 answer 값이 [[0, 1, 4], [0, 3, 4]] 가 출력되는 것을 볼 수 있다!
List<List<Integer>> answer = new ArrayList<>();
List<Integer> path = new ArrayList<>();
// path #1
path.add(0);
path.add(1);
path.add(4);
answer.add(new ArrayList<>(path));
// path = [0, 1, 4]
System.out.println("path = " + path);
// answer = [[0, 1, 4]]
System.out.println("answer = " + answer);
// path #2
path.remove(2);
path.remove(1);
path.add(3);
path.add(4);
answer.add(new ArrayList<>(path));
// path = [0, 3, 4]
System.out.println("path = " + path);
// 의도한 Logic!!
// 기대 출력 값 : answer = [[0, 1, 4], [0, 3, 4]]
// 실제 출력 값 : answer = [[0, 1, 4], [0, 3, 4]]
System.out.println("answer = " + answer);
- List의 주소를 참조하는 answer.add(path)
- List의 주소를 참조한 path 객체를 추가하므로 answer에 add 한 모든 path는 같은 path 객체를 가리킨다.
- 모든 경로를 탐색할 동안 path는 계속 수정되기 때문에, answer에 추가한 모든 path는 최종적으로 같은 값을 가지게 된다.
- List의 값을 복사하는 answer.add(new ArrayList<>(path))
- List에 path의 현재 값을 복사하여 새로운 path 리스트 객체를 만든다.
- 다른 경로를 탐색할 동안 path가 수정되더라도 answer에 추가된 path는 영향을 받지 않는다.
- 즉, 각 path 객체는 독립적인 상태를 유지한다.
- 결론
- 위 두 방법 중 틀린 방법은 없다.
- answer.add(path)가 틀린 방법이 아니라 의도하지 않은 방법(Logical Error)이란 것이다.
- 중요한 것은 작성한 코드가 본인이 의도한 대로 동작하는가이다.
728x90
알게 된 점
- 주소 참조와 값 복사는 이론으로 배우긴 했으나, 실제로 처음 맞닥뜨린 사례이다.
- 앞으로 이론을 배우면 실습 코드를 무조건 작성해 봐야겠다.
다음에 학습할 것
- List 이외의 다른 객체들에서의 주소 참조와 값 복사에 대하여
반응형
Java 코딩 테스트에서 알고리즘은 잘 구현해 놓고 이런 실수가 있지 않도록 주의해야겠다.
728x90
반응형
'Club > 99클럽 코테 스터디 2기' 카테고리의 다른 글
99클럽 코테 스터디 16일차 TIL 문자열 join (0) | 2024.06.04 |
---|---|
99클럽 코테 스터디 15일차 TIL 포화이진트리 (1) | 2024.06.03 |
99클럽 코테 스터디 13일차 TIL List to Map (0) | 2024.06.01 |
99클럽 코테 스터디 12일차 TIL List 자료구조 (0) | 2024.05.31 |
99클럽 코테 스터디 11일차 TIL 배열과 리스트 (0) | 2024.05.30 |
댓글