JAVA Pair 자료구조

Kevin·2025년 2월 1일
1

JAVA

목록 보기
16/16
post-thumbnail

서론

이 글은 저번 작성 글인 랜덤 닉네임 기능 생성기 중 생겼던 고민 중 하나를 바탕으로 설명 하는 글이다.

나는 랜덤 닉네임 생성간 아래와 같은 고민을 가지게 되었다.

N만건의 닉네임 생성 요청이 들어왔다면, 중복 되지 않은 N만개의 닉네임을 생성 해주어야 한다.

그러나 이 때 N만개의 닉네임을 생성 하면서, 만약 같은 형용사 + 명사 조합으로 인해서 같은 닉네임이 생성되면 어떻게 할까?

방법은 여러가지가 있을 것 같다.

같은 형용사 + 명사 조합의 닉네임이 있다면 그 뒤에 숫자를 붙이는 방법이 있을 것이다.

또 다른 방법으로는 아예 같은 형용사와 명사 조합을 피하는 방법도 존재 할 것이다.

먼저 나는 같은 형용사와 명사 조합을 피하는 방법을 선택 하였다.

그 이유로는 첫번째 방법인 그 뒤에 숫자를 붙이는 방법의 경우에는 매번 문자열 연산을 반복하는데 있어 많은 리소스가 사용 될 것이라 판단 하였기 때문이다.

먼저 위의 판단 근거는 옳지 못했다고 현재는 생각한다.

우선은 문자열간 “+” 연산이 아니라 StringBuilderStringBuffer 객체를 사용하면 이러한 부담은 훨씬 줄어드며, 후술한 방식은 문자열을 연산하는 방식이 아니었기 때문이다.

셀프 피드백은 이쯤하고, 본론에 대해서 작성해보겠다.


본론

아래 코드는 현재 랜덤 닉네임을 생성하는 코드 중 일부 코드이다.

List<NicknameAdjective> adjectives = nicknameAdjectiveRepository.findAll();
List<NicknameNoun> nouns = nicknameNounRepository.findAll();
nickname += adjectives.get(randomIdx);
nickname += nouns.get(randomIdx);

코드를 보면 알겠지만, 인덱스를 통해 List에 접근하여 형용사와 명사를 가지고 있다.

현재 해당 방식에서 같은 형용사와 명사 조합을 피하는 방법 을 구현하기 위해서는 해당 인덱스 이 중복되지 않게 구현을 하면 될 것이다.

이를 문자열로 풀어낼지 또는 객체로 풀어낼지, 자료구조로 풀어낼지 고민이 많았다.

이 때 자료구조로 풀어내는 것이 코드의 가독성과 생산성이 가장 높을 것이라 판단 하였다.

자바 자료구조들에 대해서 먼저 살펴보자.

자바의 MAP 자료 구조는 아래와 같은 구조를 가진다.

Map<String, String> map = new HashMap<String, String>();
map.put("name", "kevin");
map.put("hobby", "야구");

이 때 name과 hobby는 key이다.

그리고 kevin과 야구는 value이다.

즉 MAP은 하나의 key와 하나의 value가 매핑된 자료구조이다.

그러나 현재 나에게 필요한 것은 형용사와 명사를 동시에 비교 하기 위해서 형용사와 명사가 한 쌍의 value로 존재하는 자료구조가 필요했다.

이는 바로 Apache Commons Lang3 라이브러리의 Pair 자료구조이다.

Apache Commons Lang3 라이브러리는 Java의 기본 라이브러리를 보완하는 유틸리티 라이브러리이며, Pair는 두 개의 값을 하나의 객체로 묶어서 저장할 수 있는 자료구조이다.

Pair<K, V>는 두 개의 값을 하나의 객체로 묶어서 저장할 수 있다.

그리고 이를 통해 형용사와 명사를 하나의 Pair 객체로 묶어서 사용하고자 하였다.

Pair는 정적 메서드를 통해 Pair 객체를 생성할 수 있다.

import org.apache.commons.lang3.tuple.Pair;

public class PairExample {
    public static void main(String[] args) {
        Pair<String, Integer> pair = Pair.of("Apple", 100)
    }
}

또한 getLeft()getRight()로 MAP으로 치면, key와 value를 가지고 올 수 있다.

System.out.println("left: " + pair.getLeft());   // Apple
System.out.println("right: " + pair.getRight()); // 100

나는 두 개의 value를 가지고 있는 자료구조라고 처음에 생각 했었는데, 공식문서를 보니 left가 key, right를 value로 칭한다고 한다.

This class is an abstract implementation defining the basic API. It refers to the elements as 'left' and 'right'. It also implements the Map.Entryinterface where the key is 'left' and the value is 'right'.

https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/Pair.html


나는 이 Pair 자료구조를 아래와 같이 사용 하였다.

private Pair<Integer, Integer> getRandomIntegerPair(Set<Pair<Integer, Integer>> usedPairs, int nounMaxSize, int adjectiveMaxSize) {

        Pair<Integer, Integer> pair;

        do {
            int randomNounIdx = getRandomInteger(nounMaxSize);
            int randomAdjectiveIdx = getRandomInteger(adjectiveMaxSize);
            pair = Pair.create(randomNounIdx, randomAdjectiveIdx);

        } while (usedPairs.contains(pair));

        usedPairs.add(pair);

        return pair;
    }

간단하게 코드를 설명하면 인자로 이미 조합된 형용사 인덱스와 명사 인덱스를 Pair 자료구조에 저장 해두고, 이를 Set에 저장 해둔다.

그리고 do-while문을 돌면서 조합되지 않은 형용사 인덱스와 명사 인덱스 조합을 찾는 로직이다.


마무리

나에게 문제 상황이 주어졌을 때 이를 해결 할 수 있는 방법은 매우 많다.

다만 이러한 수 많은 방법들 중 나의 상황에 어떠한 방법이 가장 최적의 성능과 코드 가독성을 챙길 수 있는지를 비교 하는 것이 최고는 아니더라도 현 상황에서의 최선의 방법을 찾는 것이라고 생각한다.

마감 기한이 있는 프로젝트의 경우 이러한 고민을 더욱 깊게 하지 못하는게 아쉽긴 하지만, 한정된 시간 내에서 고민을 하는 것 또한 재미있고 더욱 현실적인 고민을 하게 되는 것 같아 또한 좋았다.


레퍼런스

profile
Hello, World! \n

0개의 댓글

관련 채용 정보