Guava:Range 区间范围工具

发布时间:2024年01月10日

简介

Range?表示一个间隔或一个序列。它被用于获取一组数字/串在一个特定范围之内。可比较类型的区间API,包括连续和离散类型。

Range 定义了连续跨度的范围边界,这个连续跨度是一个可以比较的类型(Comparable type)。比如1到100之间的整型数据。

在数学里面的范围是有边界和无边界之分的;同样,在Guava中也有这个说法。如果这个范围是有边界的,那么这个范围又可以分为包括?开集(不包括端点)和?闭集(包括端点);如果是无解的可以用?+∞?表示。

Guava 用更紧凑的方法表示范围,如果枚举的话,一共有九种范围表示。

概念表示范围对应方法
(a..b){x | a < x < b}open(C, C)
[a..b]{x | a <= x <= b}closed(C, C)
[a..b){x | a <= x < b}closedOpen(C, C)
(a..b]{x | a < x <= b}openClosed(C, C)
(a..+∞){x | x > a}greaterThan(C)
[a..+∞){x | x >= a}atLeast(C)
(-∞..b){x | x < b}lessThan(C)
(-∞..b]{x | x <= b}atMost(C)
(-∞..+∞)all valuesall()

上面的?ab?称为?端点;a?为?下端点,b?为?上端点。

Guava 中的?Range?要求:

  • 上端点不能小于下端点。

  • 极端情况下,上下端点有可能是相等的,但要求区间是闭区间或半开半闭区间(至少有一个端点是包含在区间中的)

如下示例:

  • [a..a]:单元素区间

  • [a..a);?(a..a]:空区间,但它们是有效的

  • (a..a):无效区间,构造这样的 Range 将会抛出异常

Guava 用类型?Range<C>?表示区间。所有区间实现都是不可变类型。

类方法说明

方法名称方法描述
all()?返回包含类型C所有值的Range
apply(C input)?已过时。 仅提供满足Predicate接口
atLeast(C endpoint)?返回大于等于endpoint的所有值Range
atMost(C endpoint)?返回小于等于endpoint的所有值Range
canonical(DiscreteDomain<C>?domain)?返回在给定domain离散域下Range的规范形式
closed(C lower, C upper)?返回一个Range,包含大于等于lower小于等于upper范围的所有值,数学表示 [lower,upper]
closedOpen(C lower, C upper)?返回一个Range,包含大于等于lower严格小于upper范围的所有值,数学表示 [lower,upper).
contains(C value)?判断Range中是否包含指定的value
containsAll(Iterable<??extends?C>?values)?判断指定values中是否所有值都包含在Range中
downTo(C endpoint, BoundType boundType)?
返回下限临界值为endpoint的区间,下限开闭性由boundType指定
encloseAll(Iterable<C>?values)?返回Range与传入values比较后的最小范围区间
encloses(Range<C>?other)?返回传入Range是否包含在调用此方法的Range中
equals(@Nullable Object object)?
如果object是具有与此范围相同的端点和绑定类型的范围,则返回true
gap(Range<C>?otherRange)?
返回两个Range之间的最大范围
greaterThan(C endpoint)?
返回严格大于endpoint的所有值Range
hashCode()?返回此范围的哈希码。
hasLowerBound()?返回Range是否存在下限
hasUpperBound()?返回Range是否存在上限
intersection(Range<C>?connectedRange)?返回两个Range的最大交集,如果Range无交集,抛出异常IllegalArgumentException.
booleanisConnected(Range<C>?other)?
返回两个Range是否能够连续上.
isEmpty()?判断Range是否为空,即上下限是否相等,例如 [v..v) or (v..v].
lessThan(C endpoint)?
返回严格小于endpoint的所有值Range
lowerBoundType()?返回Range的下限类型BoundType,即开闭性
lowerEndpoint()?返回Range下限的临界点值
open(C lower, C upper)?返回一个Range,包含严格大于lower小于upper范围的所有值,数学表示(lower,upper)
openClosed(C lower, C upper)?返回一个Range,包含严格大于lower小于等于upper范围的所有值,数学表示 (lower,upper]
range(C lower, BoundType lowerType, C upper, BoundType upperType)?返回一个Range,包含lower和upper范围的所有值,临界值的开闭可以通过BoundType设置,BoundType 是枚举类型,标识开闭.
ssingleton(C value)返回唯一包含传入value的Range
span(Range<C>?other)?返回两个Range的并集
toString()?返回此范围的字符串表示形式,例如 "[3..5)"
upperBoundType()?返回Range的上限类型BoundType,即开闭性
upperEndpoint()?返回Range上限的临界点值
upTo(C endpoint, BoundType boundType)?
返回上限临界值为endpoint的区间,上限开闭性由boundType指定

使用Demo

import com.google.common.collect.*;
import com.google.common.primitives.Ints;
import junit.framework.TestCase;
import java.math.BigDecimal;
import java.util.Set;

public class RangeTest extends TestCase {

    /**
     * 1、构建区间
     */
    public void test1(){
        //无上界区间
        Range<Integer> downTo = Range.downTo(3, BoundType.OPEN);// (3..+∞)
        //无下界区间
        Range<Integer> upTo = Range.upTo(3, BoundType.CLOSED);// (-∞..3]
        //有界区间
        Range<Integer> range = Range.range(1, BoundType.CLOSED, 6, BoundType.OPEN);// [1..6) 等同于 Range.closedOpen(1, 6)
    }

    /**
     * 区间测算
     */
    public void test2(){
        BigDecimal bigDecimal = BigDecimal.valueOf(1.2);
        Range<Integer> closed = Range.closed(1, 3);
        System.out.println(closed.contains(1));// return true
        System.out.println(closed.contains(3));     // return false

        System.out.println(Range.lessThan(5).contains(5));      // return false
        System.out.println(Range.greaterThan(4).contains(5));//true

        Range<Integer> closed2 = Range.closed(1, 4);
        System.out.println(closed2.containsAll(Ints.asList(1, 2, 3)));   // return true
        System.out.println(closed2.containsAll(Ints.asList(1, 2, 5))); //false
    }

    /**
     * 区间工具判断
     */
    public void test3(){
        //判断区间是否有特定边界,或是无限的
        Range<Integer> closedOpen = Range.closedOpen(3, 3);
        closedOpen.hasLowerBound(); // return true
        closedOpen.hasUpperBound(); // return true

        //判断是否为空区间。
        boolean empty = Range.closedOpen(4, 4).isEmpty();// return true
        boolean empty1 = Range.openClosed(4, 4).isEmpty();// return true
        boolean empty2 = Range.closed(4, 4).isEmpty();// return false
        //Range.open(4, 4).isEmpty();             // Range.open throws IllegalArgumentException

        //返回区间的端点值;如果区间没有对应的边界,抛出 IllegalStateException。
        Integer lowerEndpoint = Range.closed(3, 10).lowerEndpoint();// return 3
        Integer lowerEndpoint1 = Range.open(3, 10).lowerEndpoint();// return 3

        BoundType lowerBoundType = Range.closed(3, 10).lowerBoundType();// return CLOSED
        BoundType upperBoundType = Range.open(3, 10).upperBoundType();// return OPEN
    }

    /**
     * 区间工具与区间工具的关系判断
     */
    public void test4(){
        //(1)包含 [encloses]
        boolean encloses = Range.closed(3, 5).encloses(Range.open(5, 10));// return false
        boolean encloses1 = Range.closed(0, 9).encloses(Range.closed(3, 4));// return true
        boolean encloses2 = Range.open(3, 5).encloses(Range.open(5, 10));// return false

        //(2)相连 [isConnected]这等同于数学上的定义”两个区间的并集是连续集合的形式”(空区间的特殊情况除外)。
        boolean connected = Range.closed(3, 5).isConnected(Range.open(5, 10));// return true
        boolean connected1 = Range.closed(0, 9).isConnected(Range.closed(3, 4));// return true
        boolean connected2 = Range.closed(0, 5).isConnected(Range.closed(3, 9));// return true
        boolean connected3 = Range.open(3, 5).isConnected(Range.open(5, 10));// return false
        boolean connected4 = Range.closed(1, 5).isConnected(Range.closed(6, 10));// return false

        //(3)交集 [intersection]
        Range<Integer> intersection = Range.closed(3, 5).intersection(Range.open(5, 10));// return (5, 5]
        Range<Integer> intersection1 = Range.closed(0, 9).intersection(Range.closed(3, 4));// return [3, 4]
        Range<Integer> intersection2 = Range.closed(0, 5).intersection(Range.closed(3, 9));// return [3, 5]
        //Range<Integer> intersection3 = Range.open(3, 5).intersection(Range.open(5, 10));// java.lang.IllegalArgumentException: Invalid range: (5..5)
        //Range<Integer> intersection4 = Range.closed(1, 5).intersection(Range.closed(6, 10));// java.lang.IllegalArgumentException: Invalid range: [6..5]

        //(4)跨区间 [span]
        Range<Integer> span = Range.closed(3, 5).span(Range.open(5, 10));// return [3, 10)
        Range<Integer> span1 = Range.closed(0, 9).span(Range.closed(3, 4));// return [0, 9]
        Range<Integer> span2 = Range.closed(0, 5).span(Range.closed(3, 9));// return [0, 9]
        Range<Integer> span3 = Range.open(3, 5).span(Range.open(5, 10));// return (3, 10)
        Range<Integer> span4 = Range.closed(1, 5).span(Range.closed(6, 10));// return [1, 10]

    }

    public void test6() {
        Range<Integer> range = Range.closed(20, 30);
        print("closed", ContiguousSet.create(range, DiscreteDomain.integers()));

        range = Range.open(20, 30);
        print("open", ContiguousSet.create(range, DiscreteDomain.integers()));

        range = Range.openClosed(20, 30);
        print("openClosed", ContiguousSet.create(range, DiscreteDomain.integers()));

        range = Range.closedOpen(20, 30);
        print("closedOpen", ContiguousSet.create(range, DiscreteDomain.integers()));

        range = Range.greaterThan(20);
        System.out.println("greaterThan: " + ContiguousSet.create(range, DiscreteDomain.integers()).toString());

        range = Range.atLeast(20);
        System.out.println("atLeast: " + ContiguousSet.create(range, DiscreteDomain.integers()).toString());

        range = Range.lessThan(30);
        System.out.println("lessThan: " + ContiguousSet.create(range, DiscreteDomain.integers()).toString());

        range = Range.atMost(30);
        System.out.println("atMost: " + ContiguousSet.create(range, DiscreteDomain.integers()).toString());

        range = Range.all();
        System.out.println("all: " + ContiguousSet.create(range, DiscreteDomain.integers()).toString());
    }

    public static void print(String type, Set<Integer> ranges) {
        System.out.println(type + ":" + ranges + "      list:" + Lists.newArrayList(ranges));
    }

}

文章来源:https://blog.csdn.net/qq_63815371/article/details/135481220
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。