본문 바로가기

Lucene

[lucene] TokenStream.next() 와 TokenStream.next(Token token)


루씬 앤 액션 1판의 내용을 보면 Analyzer 분석 Util 클래스를 만드는데
아래와 같은 내용의 코드가 나옵니다.

TokenStream stream =
analyzer.tokenStream("contents", new StringReader(text));
ArrayList tokenList = new ArrayList();

while (true) {
Token token = stream.next();
if (token == null) break;

tokenList.add(token);
}



이 바로 앞 포스트와도 조금 연관이 있는 내용일지 모르겠습니다.

루씬 2.4.0으로 넘어오면서 바로 저 TokenStream.next() 메서드가 deprecated 되었습니다.

일단 이전버전과 현재 버젼의 메서드 변경을 살펴보겠습니다.

2.4.0 이전
  public Token next() throws IOException {
    Token result = next(new Token());

    if (result != null) {
      Payload p = result.getPayload();
      if (p != null) {
        result.setPayload((Payload) p.clone());
      }
    }

    return result;
  }

  public Token next(Token result) throws IOException {
    return next();
  }



 

2.4.0
  public Token next() throws IOException {
    final Token reusableToken = new Token();
    Token nextToken = next(reusableToken);

    if (nextToken != null) {
      Payload p = nextToken.getPayload();
      if (p != null) {
        nextToken.setPayload((Payload) p.clone());
      }
    }

    return nextToken;
  }

  public Token next(final Token reusableToken) throws IOException {
    // We don't actually use inputToken, but still add this assert
    assert reusableToken != null;
    return next();
  }



눈에 띄게 변경된 부분이 bold 처리된 저부분인데요. 사실 루씬에서는 next(Token token) 메서드를 오버라이드해서 사용하도록 되어있습니다. next() 메서드는 다시 next(Token token) 메서드를 호출하고 있으니까요.

일단 deprecated된 메서드이기 때문에 쓰기도 찜찜하고 기존에 사용하던 부분에 대해서 변경을 해주어야 하는데 왜 deprecated되었는지가 궁금했습니다.

그리고 살펴보니..
Token result = next(new Token()); 와

final Token reusableToken = new Token();
Token nextToken = next(reusableToken);

입니다.

기존에는 next()메서드가 호출될때마다 새로운 Token 객체를 생성하여 next(Token token) 메서드를 호출하는 방식이었습니다. 이게 작동상의 큰 문제는 없지만 역시 속도가 문제가 되는 듯 합니다. 일단 Analyze해야 할 문서 혹은 웹페이지의 갯수가 수백만개 수천만개가 넘어 갈 수도 있는 상황에서 (문서가 수백만개라면 그 안에 단어들은 더 많겠죠) 매번 new를 통해 Token 객체를 생성하여 넘겨주는 것이 문제가 있다고 생각된 모양입니다.

또한 next(Token token) 메서드도 보면 정확하게는 TokenStream.next(final Token reusableToken) 입니다.
다른 값을 할당하지 못 하도록 final로 정해버렸습니다. 정확하게는 resuableToken이 가지고 있는 레퍼런스를 변경하지 못 하도록 (즉, 한놈만 바라보고 그놈만 사용하도록) 정해줘버렸다는 얘기겠지요.

한번 생성된 Token 객체를 이용해서 계속해서 Analyze 하는데 재사용하는 로직을 Tokenizer에서 볼 수 있습니다.