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

oyeon·2022년 3월 27일
0

Effective Java

목록 보기
5/8

예제

무작위 정수 하나를 생성하고 싶을 때, 프로그래머가 직접 메소드를 만들었다고 하는 경우가 있을 것이다.

[코드 59-1 흔하지만 문제가 심각한 코드!]

// 범위는 0부터 n사이의 값이다.
static Random rnd = new Random();

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

괜찮은 듯 보여도 문제를 세 가지나 내포하고 있다.

  1. n이 그리 크지않은 2의 제곱수라면 얼마 지나지 않아 같은 수열이 반복된다.
  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);
}

결과

  • 기대한 값은 약 50만 이지만, 실제로 돌려보면 666,666에 가까운 값을 얻는다. 실제로 돌려보면 666,6666에 가까운 값을 얻는다.
  • 즉, 무작위로 생성된 수 중에서 2/3 가량이 중간값보다 낮은 쪽으로 쏠린 것이다.
  1. 지정한 범위 '바깥'의 수가 종종 튀어 나올 수 있다.
  • rnd.nextInt() 가 반환한 값을 Math.abs를 이용해 음수가 아닌 정수로 매핑하기 때문이다.
  • nextInt()가 Integer.MIN_VALUE를 반환하면 Math.abs 가 Interger.MIN_VALUE를 반환하고 나머지 연산자가 음수를 반환해버린다.
// n이 2의 제곱수가 아닐 때 음수를 반환한다.
System.out.println(Math.abs(Integer.MIN_VALUE) % 11);

그럼 어떻게 해야할까?

  • 직접 해결하기 위해서는 의사난수 생성기, 정수론, 2의 보수 계산 등에 조예가 깊어야 한다.
  • 하지만 라이브러리를 사용하면 이를 몰라도 쉽게 해결할 수 있다.
  • 위의 예제에서는 Random.nextInt(int)를 사용하면 된다.

참고) 자바 7부터는 Random보다 성능이 좋은 ThreadLocalRandom을 사용하는 것이 좋다.

라이브러리를 사용하여 얻는 이점

  1. 표준 라이브러리를 사용하면 그 코드를 작성한 전문가의 지식과 여러분보다 앞서 사용한 다른 프로그래머들의 경험을 활용할 수 있다.
  2. 핵심적인 일과 크게 관련 없는 문제를 해결하느라 시간을 허비하지 않아도 된다.
  3. 따로 노력하지 않아도 성능이 지속해서 개선된다.
  4. 기능이 점점 많아진다. 라이브러리에 부족한 부분이 있다면 개발자 커뮤티니에서 이야기가 나오고 논의된 후 다음 릴리즈에 해당 기능이 추가되곤 한다.
  5. 우리가 작성한 코드가 많은 사람에게 낯익은 코드가 된다.

그 외

  • 자바는 메이저 릴리즈마다 주목할 만한 수많은 기능이 라이브러리에 추가된다. 이를 웹페이지에 공시하는데 한번 쯤 읽어볼 만하다.
  • 표준 라이브러리가 매우 방대하기 떄문에 모든 API들을 공부하기 어렵겠지만 적어도 java.lang, java.util, java.io 와 그 하위 패키지들에는 익숙해져야 한다.
  • 마지막으로 자바의 컬렉션 프레임워크와 스트림 라이브러리, java.util.concurrent의 동시성 기능도 익혀두면 도움이 될 것이다.
profile
Enjoy to study

0개의 댓글