1. Обзор
В этом руководстве мы покажем, как использовать интерфейс RangeSet
Google Guava и его реализации.
RangeSet — это
набор, состоящий из нуля или более непустых несвязанных диапазонов. При добавлении диапазона в изменяемый RangeSet
все связанные диапазоны объединяются, а пустые диапазоны игнорируются.
Базовой реализацией RangeSet
является TreeRangeSet
.
2. RangeSet Google Guava
Давайте посмотрим, как использовать класс RangeSet
.
2.1. Зависимость от Maven
Начнем с добавления зависимости библиотеки Google Guava в pom.xml
:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>
Последнюю версию зависимости можно проверить здесь .
3. Создание
Давайте рассмотрим некоторые способы создания экземпляра RangeSet
.
Во-первых, мы можем использовать метод create
из класса TreeRangeSet
для создания изменяемого набора:
RangeSet<Integer> numberRangeSet = TreeRangeSet.create();
Если у нас уже есть коллекции, используйте метод create
из класса TreeRangeSet
, чтобы создать изменяемый набор, передав эту коллекцию:
List<Range<Integer>> numberList = Arrays.asList(Range.closed(0, 2));
RangeSet<Integer> numberRangeSet = TreeRangeSet.create(numberList);
Наконец, если нам нужно создать неизменяемый набор диапазонов, используйте класс ImmutableRangeSet
(создание которого следует шаблону компоновщика):
RangeSet<Integer> numberRangeSet
= new ImmutableRangeSet.<Integer>builder().add(Range.closed(0, 2)).build();
4. Использование
Начнем с простого примера, демонстрирующего использование RangeSet
.
4.1. Добавление к диапазону
Мы можем проверить, находится ли предоставленный ввод в пределах диапазона, присутствующего в любом из элементов диапазона в наборе:
@Test
public void givenRangeSet_whenQueryWithinRange_returnsSucessfully() {
RangeSet<Integer> numberRangeSet = TreeRangeSet.create();
numberRangeSet.add(Range.closed(0, 2));
numberRangeSet.add(Range.closed(3, 5));
numberRangeSet.add(Range.closed(6, 8));
assertTrue(numberRangeSet.contains(1));
assertFalse(numberRangeSet.contains(9));
}
Заметки:
- Закрытый
метод
классаRange
предполагает, что диапазон целочисленных значений находится в диапазоне от 0 до 2 (оба включительно). - Диапазон в
приведенном
выше примере состоит из целых чисел. Мы можем использовать диапазон, состоящий из любого типа, если он реализует интерфейсComparable
, такой какString
,Character
, десятичные числа с плавающей запятой и т. Д. - В случае
ImmutableRangeSet
элемент диапазона, присутствующий в наборе, не может перекрываться с элементом диапазона, который нужно добавить. Если это произойдет, мы получимисключение IllegalArgumentException .
- Ввод диапазона в
RangeSet
не может быть нулевым. Если вводнулевой
, мы получимисключение NullPointerException .
4.2. Удаление диапазона
Давайте посмотрим, как мы можем удалить значения из RangeSet
:
@Test
public void givenRangeSet_whenRemoveRangeIsCalled_removesSucessfully() {
RangeSet<Integer> numberRangeSet = TreeRangeSet.create();
numberRangeSet.add(Range.closed(0, 2));
numberRangeSet.add(Range.closed(3, 5));
numberRangeSet.add(Range.closed(6, 8));
numberRangeSet.add(Range.closed(9, 15));
numberRangeSet.remove(Range.closed(3, 5));
numberRangeSet.remove(Range.closed(7, 10));
assertTrue(numberRangeSet.contains(1));
assertFalse(numberRangeSet.contains(9));
assertTrue(numberRangeSet.contains(12));
}
Как видно, после удаления мы по-прежнему можем получить доступ к значениям, присутствующим в любом из элементов диапазона, оставшихся в наборе.
4.3. Диапазон Диапазон
Давайте теперь посмотрим, каков общий диапазон RangeSet
:
@Test
public void givenRangeSet_whenSpanIsCalled_returnsSucessfully() {
RangeSet<Integer> numberRangeSet = TreeRangeSet.create();
numberRangeSet.add(Range.closed(0, 2));
numberRangeSet.add(Range.closed(3, 5));
numberRangeSet.add(Range.closed(6, 8));
Range<Integer> experienceSpan = numberRangeSet.span();
assertEquals(0, experienceSpan.lowerEndpoint().intValue());
assertEquals(8, experienceSpan.upperEndpoint().intValue());
}
4.4. Получение поддиапазона
Если мы хотим получить часть RangeSet
на основе заданного Range
, мы можем использовать метод subRangeSet
:
@Test
public void
givenRangeSet_whenSubRangeSetIsCalled_returnsSubRangeSucessfully() {
RangeSet<Integer> numberRangeSet = TreeRangeSet.create();
numberRangeSet.add(Range.closed(0, 2));
numberRangeSet.add(Range.closed(3, 5));
numberRangeSet.add(Range.closed(6, 8));
RangeSet<Integer> numberSubRangeSet
= numberRangeSet.subRangeSet(Range.closed(4, 14));
assertFalse(numberSubRangeSet.contains(3));
assertFalse(numberSubRangeSet.contains(14));
assertTrue(numberSubRangeSet.contains(7));
}
4.5. Метод дополнения
Далее, давайте получим все значения, кроме того, которое присутствует в RangeSet
, используя метод дополнения
:
@Test
public void givenRangeSet_whenComplementIsCalled_returnsSucessfully() {
RangeSet<Integer> numberRangeSet = TreeRangeSet.create();
numberRangeSet.add(Range.closed(0, 2));
numberRangeSet.add(Range.closed(3, 5));
numberRangeSet.add(Range.closed(6, 8));
RangeSet<Integer> numberRangeComplementSet
= numberRangeSet.complement();
assertTrue(numberRangeComplementSet.contains(-1000));
assertFalse(numberRangeComplementSet.contains(2));
assertFalse(numberRangeComplementSet.contains(3));
assertTrue(numberRangeComplementSet.contains(1000));
}
4.6. Пересечение с диапазоном
Наконец, когда мы хотим проверить, пересекается ли интервал диапазона, представленный в RangeSet,
с некоторыми или всеми значениями в другом заданном диапазоне, мы можем использовать метод пересечения
:
@Test
public void givenRangeSet_whenIntersectsWithinRange_returnsSucessfully() {
RangeSet<Integer> numberRangeSet = TreeRangeSet.create();
numberRangeSet.add(Range.closed(0, 2));
numberRangeSet.add(Range.closed(3, 10));
numberRangeSet.add(Range.closed(15, 18));
assertTrue(numberRangeSet.intersects(Range.closed(4, 17)));
assertFalse(numberRangeSet.intersects(Range.closed(19, 200)));
}
5. Вывод
В этом руководстве мы проиллюстрировали RangeSet
библиотеки Guava на нескольких примерах. RangeSet в основном
используется для проверки того, попадает ли значение в определенный диапазон, присутствующий в наборе.
Реализацию этих примеров можно найти в проекте GitHub — это проект на основе Maven, поэтому его легко импортировать и запускать как есть.