우테코 6기 프리코스를진행하며 contains 메소드를 공부한 경험을 공유해보고자 한다.
요구사항에 따르면 랜덤으로 생성한 숫자 3개가 중복이 되면 안된다.
처음에 나는 반복문을 돌며 이전에 생성한 수를 모두 탐색
하는 방법을 생각했다. 하지만 숫자 3개가 아닌 더 커지게 된다면 탐색 시간이 증가한다. 그래서 좋은 코드가 아니라 생각해 변경했다.
내가 짠 코드는 다른 방식으로 중복을 확인했다.
//중복을 확인할 배열 생성
boolean[] isNumberUsed = new boolean[9];
//수 생성하기
while (targetNumbers.size() < 3) {
int generatedNumber = Randoms.pickNumberInRange(1, 9);
//만약 중복되면 다시 생성
if (isNumberUsed[generatedNumber - 1]) {
continue;
}
targetNumbers.add(generatedNumber);
isNumberUsed[generatedNumber - 1] = true;
먼저 크기 9의 배열을 생성한다. 이후 수를 생성하면 배열의 해당 인덱스를 true로 바꾼다. 만약 이미 true라면 중복이라는 뜻이므로 while문을 다시 돌며 수를 재생성한다.
이 코드는 수 생성시 배열을 처리하는 과정이 있지만 중복 확인 과정에서의 시간을 단축시킬 수 있다.
이후 다음 기능 구현을 위해 Read.md를 읽던 나는 빠뜨린 부분을 발견했다.
우테코에서 친절히 라이브러리 사용방법을 알려주며 코드를 제공해주었던 것이다.
List<Integer> computer = new ArrayList<>();
while (computer.size() < 3) {
int randomNumber = Randoms.pickNumberInRange(1, 9);
if (!computer.contains(randomNumber)) {
computer.add(randomNumber);
}
}
Randoms 사용방법만 확인한 나는 contain
을 늦게 확인했다…🥲
코드가 훨씬 가독성있고 간결해보인다.
하지만 그냥 넘어가기에는 contain
메소드의 경우에는 또 어떤 방식으로 해당 요소를 찾는지 궁금해져 알아봤다.
contains()
는 리스트 안 어떤 객체가 있는지 확인하는데 사용하는 메소드이다.
만약 리스트에 그 객체가 존재하면 boolean true
값을 반환한다.
이제 속을 들여다보자
위 주석을 보면 equals
를 사용해 최소 하나 이상 있다면 true를 반환하는 것을 알 수 있다.
더 자세히 보기 위해 indexOf
도 살펴보자
indexOf
의 주석을 보면 리스트의 첫번째 출현 인덱스를 반환한다. 리스트를 순회하다 o.equals(es[i])
가 true
가 되면 바로 return을 하는 것이다.
따라서 찾게 되면 적어도 인덱스가 0보다 크게 되기 때문에 contains
함수에서 이를 이용할 수 있는 것이다.
중복 확인 배열
의 경우 O(1)이 걸리지만 contains
의 경우 O(n)의 시간이 걸린다.
하지만…!
글을 작성하며 정답 수는 최대 9자리라는 걸 깨달았다.
따라서 요구사항의 변경을 고려한 코딩을 하더라도 성능에는 큰 차이가 없다.
(모두 탐색해도 배열의 크기가 최대 9이기 때문)
가독성이 있는 contains
를 사용하는 것이 더 좋을 것 같다.
그동안 메소드가 어떻게 돌아가는지 크게 생각안하고 사용을 했었다.
앞으로는 무조건 쓰는 것이 아닌 메소드의 내부 동작을 알고 다른 방법도 고려하며 사용해야 할 것 같다.
(+ readme를 잘읽고 최대 범위도 미리 잘 생각하자…ㅎ)