핵심 정리
이미 잘 만들어 놓은 라이브러리를 잘 활용하자.
표준 라이브러리 사용 예제
: Random
// 직접 구현
static Random rnd = new Random();
static int random(int n) {
return Math.abs(rnd.nextInt()) % n;
}
public static void main(String[] args){
int n = 2 * (Integer.MAX_VALUE / 3);
int low = 0;
for (int i = 0; i < 1000000; i++)
if (random(n) < n/2)
low++;
System.out.println(low);
}
- 위 코드는 세 가지 문제점을 지니고 있다.
- n이 그리 크지 않은 2의 제곱수라면 얼마 지나지 않아 같은 수열이 반복된다.
- n이 2의 제곱수가 아니라면 몇몇 숫자가 평균적으로 더 자주 반환된다.
- 지정한 범위 밖의 수가 나올 수 있다.
👇 자세한 이유(참고).
더보기
1. n이 그리 크지 않은 2의 제곱수라면 얼마 지나지 않아 같은 수열이 반복된다.
2의 제곱수인 n에 대한 nextInt() 함수의 내부 동작 방식 때문에 발생한다. nextInt()는 32비트 정수를 반환하는데, 이 정수의 비트 수는 2의 제곱수이다. 따라서 n이 2의 제곱수이고 그 크기가 작다면, 생성된 무작위 수열은 실제로 그리 길지 않을 수 있다. 즉, n이 2의 제곱수인 경우 nextInt() 함수가 반환하는 범위 내에서 n으로 나누었을 때 가능한 나머지 값들의 수가 제한적이므로, 동일한 패턴의 수열이 빠르게 반복될 수 있다.
2. n이 2의 제곱수가 아니라면 몇몇 숫자가 평균적으로 더 자주 반환된다.
nextInt()는 일정 범위의 정수를 반환하지만, 그 범위가 n의 값과 정확히 맞지 않는 경우, 일부 결과값이 다른 결과값보다 더 자주 발생할 수 있다. 이는 특히 n`이 2의 제곱수가 아닌 경우에 두드러진다.
3. 지정한 범위 바깥의 수가 종종 튀어나올 수 있다. rnd.nextInt()가 반환한 값을 Math.abs를 이용해 음수가 아닌 정수로 매핑하기 때문이다.
rnd.nextInt()는 음수를 포함한 모든 정수를 반환할 수 있다. 따라서, Math.abs() 함수를 사용해 음수를 양수로 변환하면, 이 변환 과정에서 반환된 값의 범위가 0에서 n - 1까지가 아닌 0에서 Integer.MAX_VALUE까지로 확대되는 문제가 발생한다. 이는 rnd.nextInt()가 음수를 반환할 때 발생하는데, 이 때 Math.abs()`함수를 통해 음수가 양수로 변환되면서 원래 범위를 벗어난 값이 생성될 수 있다.
- 이미 잘 만들어놓은 Random.nextInt()을 사용하면 직접 해결할 필요가 없다.
- 자바 7부터는 Random 대신 ThreadLocalRandom을 사용하자.
- 포크-조인 풀이나 병렬 스트림에서는 SplittableRandom을 사용하자.
표준 라이브러리 장점
- 핵심적인 일과 크게 관련 없는 문제를 해결하느라 시간을 허비하지 않아도 된다.
- 노력하지 않아도 성능이 지속해서 개선된다.
- 기능이 점점 많아진다.
- 다른 개발자들이 읽고 유지보수, 재활용하기 좋은 코드가 된다.
- 메이저 릴리스마다 수많은 기능이 추가된다.
예시
// transferTo 메소드를 이용해 URL의 내용 가져오기 - 자바 9부터 가능하다.
public static void main(String[] args) throws IOException {
try {InputStream in = new URL(args[0]).openStream()) {
in.transferTo(System.out);
}
}
기타 팁
- 적어도 java.lang, java.util, java.io와 그 하위 패키지들에는 익숙해지자.
- 컬렉션 프레임워크(item 45~48), java.util.concurrent의 동시성 기능 등도 알아두자.
- 표준 라이브러리에 없는 기능이라면 서드파티 라이브러리(ex. 구글의 구아바 라이브러리)를 고려하자.
'Language > Java' 카테고리의 다른 글
| [effective java] 아이템 61. 박싱된 기본 타입보다는 기본 타입을 사용하라. (0) | 2023.07.27 |
|---|---|
| [effective java] 아이템 60. 정확한 답이 필요하다면 float와 double은 피하라. (0) | 2023.07.17 |
| [effective java] 아이템 58. 전통적인 for 문보다는 for-each 문을 사용하라. (0) | 2023.07.17 |
| [effective java] 아이템 57. 지역변수의 범위를 최소화하라. (0) | 2023.07.17 |
| [effective java] 아이템 56. 공개된 API 요소에는 항상 문서화 주석을 작성하라. (0) | 2023.07.17 |