Java for Beginner
675 subscribers
558 photos
156 videos
12 files
851 links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
BitSet, особенности и внутреннее устройство

BitSet — это класс в Java, который представляет собой массив битов с возможностью их динамического увеличения. Он используется для эффективного хранения и манипулирования наборами булевых значений (битов), где каждый бит может быть true (1) или false (0). BitSet принадлежит к пакету java.util и является полезным инструментом для выполнения операций на уровне битов, таких как поиск битовых масок, управление множествами, или работа с флагами.

Особенности BitSet

Эффективное использование памяти:
BitSet предназначен для экономии памяти. В отличие от массивов типа boolean[], где каждый элемент занимает 1 байт, BitSet использует один бит на каждое значение, что значительно снижает объем памяти, требуемой для хранения большого количества булевых значений.

Динамическое расширение:
BitSet динамически изменяет размер своего внутреннего хранилища по мере добавления или изменения значений. Это позволяет работать с большими наборами битов без необходимости заранее задавать их размер.

Быстрые битовые операции:
BitSet предоставляет быстрые методы для выполнения битовых операций, таких как AND, OR, XOR, и NOT. Эти операции применяются ко всему набору битов, что делает BitSet мощным инструментом для задач, требующих обработки множества булевых значений.

Легкость использования:
BitSet предоставляет удобные методы для установки, сброса, проверки и изменения битов по их индексам. Это упрощает работу с булевыми массивами и делает код более читаемым.
Внутреннее устройство
BitSet
BitSet внутри представляет собой массив типа long[], где каждый элемент массива хранит 64 бита. Это позволяет хранить биты компактно и выполнять операции на уровне битов очень быстро, используя встроенные в процессор операции.

Основная структура данных:

Основой BitSet является массив long[]. Каждый элемент этого массива представляет собой 64 бита, которые могут быть установлены в 0 или 1.
public class BitSet implements Cloneable, Serializable {
private long[] words;
private int wordsInUse = 0;
// другие поля и методы...
}
Массив words динамически расширяется по мере необходимости. Параметр wordsInUse отслеживает количество используемых элементов в массиве.


Динамическое расширение массива:

Когда в BitSet устанавливается бит с индексом, превышающим текущий размер массива words, происходит расширение массива.
private void ensureCapacity(int wordsRequired) {
if (words.length < wordsRequired) {
// логика увеличения размера массива...
}
}
Этот процесс автоматический и управляется самим классом BitSet, что позволяет пользователю не беспокоиться о ручном управлении памятью.


Битовые операции:

Основные битовые операции (AND, OR, XOR, NOT) выполняются непосредственно на массиве long[], что обеспечивает высокую производительность. Например, операция AND проходит по каждому элементу массива words и применяет побитовую операцию AND:
public void and(BitSet set) {
for (int i = 0; i < wordsInUse; i++) {
words[i] &= set.words[i];
}
recalculateWordsInUse();
}
Это позволяет применять операции ко всему набору битов за один проход, минимизируя затраты времени.


Индексация битов:

Для работы с конкретными битами внутри BitSet, используется индексация. Индекс бита определяет, в каком элементе массива words он находится, и его позицию внутри этого элемента.
private static int wordIndex(int bitIndex) {
return bitIndex >> 6; // Эквивалентно делению на 64
}

public void set(int bitIndex) {
int wordIndex = wordIndex(bitIndex);
words[wordIndex] |= (1L << bitIndex);
}
Здесь метод wordIndex вычисляет индекс элемента массива, в котором находится нужный бит, а побитовый сдвиг устанавливает значение этого бита.


Эффективное использование памяти и производительности:

Благодаря использованию long[], BitSet позволяет эффективно управлять памятью, особенно при работе с большими наборами данных. Битовые операции выполняются быстро, что делает этот класс пригодным для задач, требующих высокой производительности.

#Java #Training #Medium #BitSet
Основные методы BitSet и их использование

set(int bitIndex) и set(int fromIndex, int toIndex):
Эти методы используются для установки бита или диапазона битов в значение true.
BitSet bitSet = new BitSet();
bitSet.set(2); // Устанавливает бит с индексом 2 в true
bitSet.set(4, 7); // Устанавливает биты с индексами 4, 5 и 6 в true
Если указать диапазон, все биты в этом диапазоне будут установлены в true.


clear(int bitIndex) и clear(int fromIndex, int toIndex):

Эти методы сбрасывают бит или диапазон битов, устанавливая их в false.
bitSet.clear(2); // Сбрасывает бит с индексом 2 в false
bitSet.clear(4, 7); // Сбрасывает биты с индексами 4, 5 и 6 в false
Полезно для обнуления значений или удаления флагов.


get(int bitIndex) и get(int fromIndex, int toIndex):
Эти методы возвращают значение конкретного бита или диапазона битов.
boolean value = bitSet.get(2); // Получает значение бита с индексом 2
BitSet subSet = bitSet.get(4, 7); // Получает поднабор битов с 4 до 6
Возвращаемое значение может быть true или false, а в случае диапазона — новый BitSet.


flip(int bitIndex) и flip(int fromIndex, int toIndex):
Переключает (инвертирует) бит или диапазон битов.
bitSet.flip(2); // Инвертирует бит с индексом 2
bitSet.flip(4, 7); // Инвертирует биты с 4 до 6
Если бит был true, он станет false, и наоборот.


length() и size():
length() возвращает индекс самого старшего бита плюс один, т.е. логическую длину BitSet.
size() возвращает текущий размер внутреннего массива, который является кратным 64.

System.out.println("Length: " + bitSet.length()); // Логическая длина BitSet
System.out.println("Size: " + bitSet.size()); // Текущий размер внутреннего массива
Эти методы полезны для анализа содержимого BitSet и его текущего состояния.


cardinality():
Возвращает количество установленных в true битов (так называемая "мощность" множества).
int numberOfBits = bitSet.cardinality(); // Количество установленных битов
Полезно, когда нужно узнать, сколько значений true содержится в наборе.


and(BitSet set), or(BitSet set), xor(BitSet set):
Методы выполняют побитовые операции AND, OR, XOR над текущим BitSet и заданным BitSet.
BitSet bitSet1 = new BitSet();
bitSet1.set(1);
bitSet1.set(3);

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

bitSet1.and(bitSet2); // AND операция между bitSet1 и bitSet2
bitSet1.or(bitSet2); // OR операция между bitSet1 и bitSet2
bitSet1.xor(bitSet2); // XOR операция между bitSet1 и bitSet2
Эти методы полезны для выполнения сложных битовых операций между двумя наборами.


intersects(BitSet set):
Проверяет, есть ли общие установленные биты между двумя BitSet.
boolean hasIntersection = bitSet1.intersects(bitSet2); // true, если есть общие биты
Метод возвращает true, если есть хотя бы один бит, который установлен в true в обоих наборах.


isEmpty():
Проверяет, есть ли хотя бы один установленный бит в BitSet.
boolean isEmpty = bitSet.isEmpty(); // true, если все биты сброшены
Полезно для проверки пустоты множества.


stream():
Позволяет создать поток из установленных битов BitSet. Этот метод особенно полезен для работы с Stream API.
bitSet.stream().forEach(System.out::println); // Выводит индексы установленных битов
Это удобный способ итерирования по установленным битам с использованием функциональных возможностей Java.


Примеры использования

Оптимизация использования памяти:
Если вам нужно хранить большой набор булевых значений, BitSet помогает оптимизировать использование памяти, так как каждый бит занимает всего 1 бит.
BitSet largeSet = new BitSet();
for (int i = 0; i < 1000000; i++) {
if (i % 2 == 0) {
largeSet.set(i);
}
}

System.out.println("Количество установленных битов: " + largeSet.cardinality());
В этом примере BitSet используется для хранения большого количества булевых значений, что значительно экономит память по сравнению с использованием массивов boolean[].


#Java #Training #Medium #BitSet