무작위 정수를 생성할 때 많은 개발자들이 다음과 같이 개발합니다.
얼핏 보면 문제가 없어 보이지만 세 가지의 문제점을 내포하고 있는 코드입니다.
- n이 크지 않은 2의 제곱수라면 얼마 지나지 않아 같은 수열이 반복됨
- n이 2의 제곱수가 아니라면 몇몇 숫자가 평균적으로 더 자주 반환됨
- rnd.nextInt()가 반환한 값을 Math.abs를 이용해 음수가 아닌 정수로 매핑하기 때문에 지정한 범위 바깥의 수가 종종 튀어나갈 수 있음
- 혹여나 결과로 Integer.MIN_VALUE가 나왔고 이를 절댓값 씌웠을 때 오버플로우 발생 가능
1. n이 크지 않은 2의 제곱수라면 얼마 지나지 않아 같은 수열이 반복됨
코드 부연 설명
- n을 2^10, 즉 1024로 설정하고 1024번의 반복을 통해 랜덤값을 생성했음에도 불구하고, 생성된 랜덤값이 균일하지 않음을 확인할 수 있음
- 만약 랜덤값이 균일했다면 1부터 1024까지의 각 값이 1번씩 나왔을 것
2. n이 2의 제곱수가 아니라면 몇몇 숫자가 평균적으로 더 자주 반환됨
부연 설명
- 이상적으로 동작한다면 약 50만개가 출력돼야 하지만
- 실제로 돌려보면 2/3인 666,666에 가까운 값을 얻음
- 무작위로 생성된 수 중에서 2/3 가량이 중간값보다 낮은 쪽으로 쏠린 것
3. 해결책
앞서 발생한 문제는 자바 7 버전부터 도입된 표준 라이브러리인 ThreadLocalRandom으로 대체하면 대부분 잘 작동합니다.
- Random보다 더 고품질의 무작위 수를 생성할 뿐 아니라 속도도 더 빠름
- 포크-조인 풀이나 병렬 스트림에서는 SplittableRandom을 사용
표준 라이브러리를 적극 활용하자
표준 라이브러리를 사용하면 다음과 같은 장점이 있습니다.
- 표준 라이브러리를 사용하면 다른 개발자들의 경험을 활용 가능
- 핵심적인 일과 크게 관련 없는 문제를 해결하느라 시간을 허비하지 않아도 됨
- 별도로 노력하지 않아도 성능이 지속해서 개선됨
- 기능이 점점 많아짐
- 라이브러리를 사용하면 많은 사람들에게 낯익은 코드가 됨
1. 표준 라이브러리를 사용하면 다른 개발자들의 경험을 활용 가능
- Random의 결함을 해결하려면 의사난수 생성기, 정수론, 2의 보수 계산 등에 조예가 깊어야 하지만 자바에서 제공한 표준 라이브러리인 ThreadLocalRandom에서 이미 해결했으므로 메서드의 동작 방식을 몰라도 해결 가능
- 알고리즘에 능통한 개발자가 설계와 구현과 검증에 시간을 들여 개발했고, 이 분야의 여러 전문가가 잘 동작함을 대신 검증해 줬기 때문에 안심하고 사용해도 됨
- 혹시 버그가 발생하더라도 다음 릴리즈에서 수정될 것이라고 기대할 수 있음
2. 핵심적인 일과 크게 관련 없는 문제를 해결하느라 시간을 허비하지 않아도 됨
- 표준 라이브러리는 사용자가 많고 사용자가 많을수록 레퍼런스가 풍부하기 때문에 문제 발생 시 해결 속도가 빠름
3. 별도로 노력하지 않아도 성능이 지속해서 개선됨
- 사용자가 많고, 업계 표준 벤치마크를 사용해 성능을 확인하기 때문에 표준 라이브러리 제작자들은 더 나은 방법을 꾸준히 모색함
- ex) 자바 플랫폼 라이브러리의 많은 부분이 수 년에 걸쳐 지속해서 재작성되었기 때문에 때로는 성능이 드라마틱하게 개선되기도 함
4. 기능이 점점 많아짐
- 라이브러리에 부족한 부분이 있다면 stackoverflow 혹은 github issues에서 이야기가 나오고 논의된 후 다음 리리즈에 해당 기능이 추가되기도 함
5. 라이브러리를 사용하면 많은 사람들에게 낯익은 코드가 됨
- 표준 라이브러리를 사용하는 개발자들이 많기 때문에 활용할수록 자연스럽게 다른 개발자들 입장에서 가독성과 유지보수 측면에서 좋은 코드가 됨
메이저 릴리즈를 주목하자
메이저 릴리즈마다 주목할만한 수많은 기능이 라이브러리에 추가되며 자바는 이를 웹페이지에 공시합니다.
- 자바 개발자라면 한 번쯤 읽어보는 것을 추천
- 너무 많아서 읽기 힘들더라도 java.lang.*, java.util.*, java.io.* 패키지들은 반드시 확인하는 것을 추천
- 특히 java.util의 컬렉션 프레임워크와 java.util.concurrent 패키지는 알아두면 큰 도움이 됨
정리
- 전문적인 기능을 요구할수록 라이브러리가 필요한 기능을 충분히 제공하지 못할 수도 있고 있지만 우선은 라이브러리를 사용하려 시도하는 것을 권장
- 어떤 영역의 기능을 제공하는지 살펴보고, 원하는 기능이 아니라 판단될 경우 대안을 사용하는 것을 권장
- 일반적으로 라이브러리의 코드는 개발자가 작성한 것보다 품질이 좋고 개선의 여지가 있음
- 라이브러리 코드는 주목을 많이 받고 개발자 커뮤니티에서 문제점이 많이 거론되므로 코드 품질이 점차 좋아질 확률이 높음
- 자바 표준 라이브러리에서 원하는 기능을 찾지 못하면, 그다음 선택지는 Guava와 같은 고품질의 서드파티 라이브러리 사용하는 것을 권장
- 특별한 기능이 아니라면 누군가 라이브러리로 만들어 두었을 가능성이 높음
참고
이펙티브 자바
반응형
'JAVA > Effective Java' 카테고리의 다른 글
[아이템 61] 박싱된 기본 타입보다는 기본 타입을 사용하라 (0) | 2024.03.17 |
---|---|
[아이템 60] 정확한 답이 필요하다면 float와 double은 피하라 (0) | 2024.03.17 |
[아이템 58] 전통적인 for 문보다는 for-each 문을 사용하라 (0) | 2024.03.16 |
[아이템 57] 지역변수의 범위를 최소화하라 (0) | 2024.03.16 |
[아이템 56] 공개된 API 요소에는 항상 문서화 주석을 작성하라 (0) | 2024.03.13 |