Skip to content

Latest commit

 

History

History
105 lines (73 loc) · 2.81 KB

라이브러리를_익히고_사용하라.md

File metadata and controls

105 lines (73 loc) · 2.81 KB

아이템59 | 라이브러리를 익히고 사용하라


흔하게 구현하는 Random 메서드

static Random rnd = new Random();

static int random(int n) {
    return Math.abs(rnd.nextInt()) % n;
}

문제점

1. n이 그리 크지 않은 2의 제곱수라면 얼마 지나지 않아 같은 수열이 반복된다.

  • Random이 사용하는 난수 생성기인 LCG의 특징

2. n이 2의 제곱수가 아니라면 몇몇 숫자가 평균적으로 더 자주 반환된다.

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);
}
  • random 메서드가 정상적으로 동작한다면 약 50만개가 출력되야 하지만, 실제로 돌려보면 666,666에 가까운 값을 얻는다.
  • 무작위로 생성된 수 중에서 2/3이 중간값보다 낮은 쪽으로 쏠린 것이다.

3. 지정한 범위 바깥의 수가 종종 튀어나올 수 있다.

nextInt()가 Integer.MIN_VALUE를 반환하면 Math.abs도 Integer.MIN_VALUE를 반환한다.

  • n이 2의 제곱수가 아닌 경우 %는 음수를 반환한다.
  • Integer.MIN_VALUE의 절대값이 정수 범위를 초과하기 때문이다.

해결 방법

1. Random.nextInt(int bound)를 사용하라

public int nextInt(int bound) {
    if (bound <= 0) {
        throw new IllegalArgumentException(BAD_BOUND);
    }
    int r = next(31);
    int m = bound - 1;
    if ((bound & m) == 0)
        r = (int)((bound * (long)r) >> 31);
    else {
        for (int u = r;
             u - (r = u % bound) + m < 0;
             u = next(31))
            ;  
    }
    return r;
}

2. ThreadLocalRandom으로 대체하라

  • 자바 7부터는 Random을 더 이상 사용하지 않는 것이 좋다.
  • Random보다 고품질의 무작위 수를 생성하고 속도도 더 빠르다.

표준 라이브러리를 쓰는 이점

  1. 그 코드를 작성한 전문가의 지식과 앞서 사용한 다른 프로그래머들의 경험을 활용할 수 있다.
  2. 핵심적인 일과 크게 관련 없는 문제를 해결하느라 시간을 허비하지 않아도 된다.
  3. 따로 노력하지 않아도 성능이 지속해서 개선된다.
  4. 기능이 점점 많아진다.
  5. 다른 개발자들이 더 읽기 쉽고, 유지보수하기 좋고, 재활용하기 쉬운 코드가 된다.

알아두면 도움이 될 만한 라이브러리

  • java.lang, java.util, java.io와 그 하위 패키지
  • 컬렉션 프레임워크와 스트림 라이브러리
  • java.util.concurrent의 동시성 기능

결론

  • 바퀴를 다시 발명하지 말자.
  • 나만의 특별한 기능이 아니라면 이미 누군가 구현해놓았을 가능성이 크다.