Back-end

[Java] String 배열 대신 HashSet을 이용하여 문자 찾기

somuxsomu 2024. 1. 19. 16:04

 
 

String배열(String[]) 대신 HashSet을 이용하여 문자 찾기

 

 


 
클라이언트에서 요청 온 파라미터(과일)이
내가 선언한 과일리스트에 포함 되어있는지 안되어 있는지 확인 후
ture/false를 반환해주는 로직을 만들고 싶다.
 
참고로,

리스트안에 들어갈 내용은
DB에서 조회한 값이 아닌 하드코딩된 문자열을 넣어야 한다.
 

 
 
내가 처음에 개발한 방법은 
 
위 코드를 보면,
String[]에 선언된 과일배열에 In_array 메소드를 사용했다.
forEach를 사용해 있으면 true, 없으면 false를 리턴해주는 메소드이다.
 
하지만 이렇게 String[]을 선언하고 과일 여부를 체크하는 방법보다는,
HashSet으로 선언을 하고 contains를 이용해서 찾는게

속도 면에서는 훨-씬- 좋다고 하여

 


리팩토링을 해보려고 한다.
 
 

 
 
위 코드가 개선된 코드이다.
 
HashSet으로 선언을 했고,
HashSet을 호출해서 contains를 이용해서 과일 여부 확인을 해주는 로직이다.
 
contains는 true, false를 리턴해주기 때문에
훨씬 더 간단하고 직관적인 로직이 되었다.
 

 




Java에서 Set을 초기화 할 수 있는 방법은 3가지가 있다.

 

1.  초기화 블록을 사용한 방법

private final Set<String> testSet = new HashSet<String>() {{
    add("A");
    add("B");
    add("C");
    // ... 나머지 요소들 ...
}};

 
 

2. Arrays.asList()를 사용한 방법

private final Set<String> testSet = new HashSet<>(Arrays.asList("A", "B", "C", /* ... */));

 
 

3. Java 9 이상의 버전 Set.of()를 사용한 방법

private final Set<String> testSet = Set.of("A", "B", "V", /* ... */);

 

대신, Set.of는 최대 10개까지 작성 할 수 있다.
즉 갯수가 정해져 있다. 



나는 1번 방식을 선택하였고,
함수를 호출 할 때마다 new해주는 방식이 아닌,
따로 메소드로 빼서 미리 생성을 해둔 HashSet을호출하는 방식으로 개발하였다.

 
그렇게 개발 한 이유는,

 

 
함수가 호출될 때마다 new HashSet()을 사용하면 매번 새로운 HashSet 객체가 생성된다.
매 호출 시마다 새로운 Set을 만들어서 데이터를 추가하는 것을 의미한다. 

 


1. 메모리 소비

매 호출 시마다 새로운 Set이 생성되므로 메모리 소비가 높아진다.
특히 Set에 많은 양의 데이터가 들어있거나 함수 호출이 빈번한 경우에 불리하다.

2. 데이터 초기화

Set이 호출될 때마다 데이터를 처음부터 다시 초기화한다.
따라서 이전에 추가된 데이터는 새로운 Set에는 존재하지 않는다.


 
이와 달리,

함수 호출 시에 미리 생성된 Set을 사용하는 경우에는


 


1. 메모리 효율

미리 생성된 Set을 함수가 호출될 때마다 재사용하므로 메모리 소비가 낮아진다.

2. 데이터 재활용

함수 호출이 끝난 후에도 Set 객체가 유지되므로,
함수 호출 간에 데이터를 공유할 수 있다.
즉, 이전에 추가된 데이터는 계속 Set에 남아 있는다.


 

그러면 이제 성능 문제에 대해 알아보자,

 

성능 문제의 두 가지 측면


1. contains vs for each


    과일이 10만개 있다고 가정을 하면,


foreach는

평균적으로 5만개의 과일을 봐야 찾을 수 있고,

결국 과일의 갯수와 foreach의 속도는 비례한다.


        hashset의 contains는

hash 값으로 비교하기때문에,

과일의 갯수와 무관하게 상수시간안에 있는지 없는지 찾을 수 있다.

 


2. hashset을 함수 안에서 만들기 vs 밖에서 만들기


hashset에서 contains는 과일의 갯수와 무관하게 동작하지만,
hashset을 생성하기 위해서는 과일의 갯수에 비례하는 시간이 걸린다.


     함수 호출마다 hashset을 생성하고, contains를 한번 호출하면

contains에 쓰는 시간보다 hashset을 만드는 시간이 더 걸린다!


그래서 과일의 종류가 변하지 않는 hashset을 함수 밖에서, 클래스의 필드로 선언하면
  클래스가 생성될 때 hashset이 생성되고, 함수 호출할때는 contains 한번만 하면된다.


 

 

따라서,

함수 호출 할때 마다
데이터를 초기화해야 하는지 여부와 메모리 사용에 대한 고려를 통해 
어떤 방식을 선택할지 결정하여 사용하면 된다 !
 
 
일반적으로는,

 데이터를 미리 초기화하고 함수 호출 시 재사용하는 것이 효율적이다!