manchesterandthecity 2025. 2. 17. 22:29

자바 BitSet 클래스

1. BitSet이란?

BitSet은 자바에서 비트 배열을 다룰 수 있도록 제공하는 클래스이다.

boolean 값을 저장하는 boolean[] 배열보다 메모리를 효율적으로 사용할 수 있으며, 비트 연산을 활용하여 빠르게 데이터를 조작할 수 있다.

BitSet은 내부적으로 long[] 배열을 사용하여 비트를 저장하며, 필요에 따라 크기를 동적으로 조정할 수 있다.


2. BitSet의 주요 특징

  • 비트 단위로 저장: 0과 1로 이루어진 비트 배열을 저장 및 관리할 수 있음
  • 자동 크기 조정: 선언 시 크기를 지정하지 않아도 필요에 따라 크기가 자동으로 확장됨
  • 효율적인 메모리 사용: boolean[] 배열보다 메모리 사용량이 적음
  • 빠른 연산 속도: 비트 단위 연산 (AND, OR, XOR 등)을 지원하여 빠른 연산 가능
  • 0 기반 인덱스: 비트는 0부터 시작하는 인덱스로 접근 가능

3. BitSet 기본 사용법

3.1. BitSet 생성

import java.util.BitSet;

public class BitSetExample {
    public static void main(String[] args) {
        BitSet bitSet = new BitSet(); // 기본 크기로 BitSet 생성
        BitSet bitSetWithSize = new BitSet(10); // 초기 크기 10으로 생성
    }
}

3.2. 비트 설정 및 조회

BitSet bitSet = new BitSet();
bitSet.set(0); // 0번 비트를 1로 설정
bitSet.set(3); // 3번 비트를 1로 설정
bitSet.set(5, true); // 5번 비트를 1로 설정

System.out.println(bitSet); // 출력: {0, 3, 5}
System.out.println(bitSet.get(3)); // true (3번 비트는 1)
System.out.println(bitSet.get(4)); // false (4번 비트는 0)

3.3. 비트 해제 및 토글

bitSet.clear(3); // 3번 비트를 0으로 설정
bitSet.flip(5); // 5번 비트를 반전 (1 → 0 또는 0 → 1)
System.out.println(bitSet); // 출력: {0}

3.4. 논리 연산

BitSet bitSet1 = new BitSet();
bitSet1.set(0);
bitSet1.set(2);

BitSet bitSet2 = new BitSet();
bitSet2.set(1);
bitSet2.set(2);

bitSet1.and(bitSet2); // AND 연산 (둘 다 1인 경우만 유지)
System.out.println(bitSet1); // 출력: {2}

bitSet1.or(bitSet2); // OR 연산 (하나라도 1이면 유지)
System.out.println(bitSet1); // 출력: {0, 1, 2}

bitSet1.xor(bitSet2); // XOR 연산 (둘 다 1이면 0, 하나만 1이면 유지)
System.out.println(bitSet1); // 출력: {0, 1}

4. BitSet의 기타 유용한 메서드

메서드 설명
set(int index) 특정 비트를 1로 설정
clear(int index) 특정 비트를 0으로 설정
flip(int index) 특정 비트를 반전 (0↔1)
get(int index) 특정 비트의 값을 반환 (true/false)
cardinality() 1로 설정된 비트의 개수 반환
length() 가장 높은 1의 인덱스 + 1 반환
size() 내부적으로 사용되는 비트 배열 크기 반환
isEmpty() 모든 비트가 0인지 확인
toString() 1로 설정된 비트 목록을 문자열로 반환

 

예제:

BitSet bitSet = new BitSet();
bitSet.set(0);
bitSet.set(3);
bitSet.set(5);

System.out.println(bitSet.cardinality()); // 1로 설정된 비트 개수: 3
System.out.println(bitSet.length()); // 가장 높은 1의 인덱스 + 1: 6
System.out.println(bitSet.isEmpty()); // false (비트가 하나 이상 1임)
System.out.println(bitSet); // 출력: {0, 3, 5}

5. BitSet과 배열 비교

비교 항목 BitSet boolean 배열
메모리 효율성 높음 낮음 (각 요소가 1 byte)
크기 조정 자동 확장 고정 크기
논리 연산 지원 (AND, OR, XOR) 직접 구현해야 함
사용 용도 비트 플래그, 집합 연산 단순한 논리 값 저장

6. BitSet의 활용 예제

6.1. 중복 검사 (빠른 중복 체크)

int[] numbers = {1, 3, 5, 7, 3, 1};
BitSet seen = new BitSet();

for (int num : numbers) {
    if (seen.get(num)) {
        System.out.println("중복된 숫자: " + num);
    }
    seen.set(num);
}

6.2. 소수 판별 (에라토스테네스의 체)

int n = 50;
BitSet primes = new BitSet(n + 1);
primes.set(2, n + 1);

for (int i = 2; i * i <= n; i++) {
    if (primes.get(i)) {
        for (int j = i * i; j <= n; j += i) {
            primes.clear(j);
        }
    }
}
System.out.println("소수: " + primes);

7. 결론

BitSet은 메모리를 절약하면서도 빠른 비트 연산을 수행할 수 있도록 도와주는 강력한 도구이다.

boolean[] 배열보다 훨씬 효율적으로 데이터를 저장하고 연산할 수 있으며, 대량의 데이터를 다루는 경우 특히 유용하다.

데이터 중복 검사, 논리 연산, 집합 연산, 비트 플래그 등 다양한 활용이 가능하므로, 적절한 상황에서 BitSet을 적극 활용하면 성능을 크게 향상시킬 수 있다!