提升编程效率的利器: 解析Google Guava库之集合篇RangeSet范围集合(五)

news2024/11/15 11:18:52

在编程中,我们经常需要处理各种范围集合,例如时间范围、数字范围等。传统的集合类库往往只能处理离散的元素集合,对于范围集合的处理则显得力不从心。为了解决这个问题,Google的Guava库提供了一种强大的数据结构——RangeSet,专门用于高效处理范围集合。

提升编程效率的利器: 解析Google Guava库之集合篇Immutable(一)
提升编程效率的利器: 解析Google Guava库之集合篇Multimap(二)
提升编程效率的利器: 解析Google Guava库之集合篇BitMap(三)
提升编程效率的利器: 解析Google Guava库之集合篇Table二维映射(四)

一、RangeSet简介

RangeSet是Guava库中的一个接口,它表示一组不重叠的、非空的范围集合。RangeSet中的每个范围都是一个Range对象,Range对象表示一个具有起始和结束边界的范围。RangeSet提供了一种方便的方式来管理和操作这些范围。

RangeSet还提供了丰富的查询和操作功能。例如,可以使用contains©方法查询给定的元素是否在RangeSet里,rangeContaining©方法返回包含给定元素的Range(如果不存在则返回null),以及encloses(Range)方法用来判断给定的Range是否包含在RangeSet里面。此外,span()方法返回一个包含在这个RangeSet的所有Range的并集。

要实现RangeSet接口,可以选择使用它的两个主要实现类:ImmutableRangeSet和TreeRangeSet。其中,ImmutableRangeSet是一个不可修改的RangeSet,而TreeRangeSet则是利用树的形式来实现,提供了高效的查询和插入操作。

二、RangeSet的核心特性

  • 自动合并范围:
    当向RangeSet中添加一个新的范围时,它会自动与现有的范围进行合并。如果新的范围与某个现有范围相交或相邻,它们会被合并成一个更大的范围。这种自动合并的特性使得RangeSet能够保持范围的不重叠性,从而简化了范围集合的管理。

  • 高效的查询操作:
    RangeSet提供了丰富的查询操作,可以快速地判断一个元素是否在某个范围内、获取包含某个元素的范围等。这些查询操作都是基于对范围树的高效遍历实现的,能够在对数时间内给出结果。

  • 灵活的范围操作:
    除了基本的查询操作外,RangeSet还支持各种范围操作,如并集、交集、差集等。这些操作可以方便地对范围集合进行组合和变换,满足各种复杂的需求。

三、RangeSet的实现原理

RangeSet的实现原理主要基于一种称为“范围树”的数据结构。范围树是一种平衡树,其中每个节点都表示一个范围。树中的节点按照范围的起始位置进行排序,以便快速查找和定位特定的范围。

当向RangeSet中添加一个新的范围时,它会遍历范围树,找到与新范围相交或相邻的现有范围,并进行合并。合并后的范围会被插入到树中的适当位置,以保持树的平衡性。这种合并和插入操作的时间复杂度都是对数级别的,因此RangeSet能够高效地处理大量的范围添加操作。

对于查询操作,RangeSet可以利用范围树的结构进行快速查找。例如,当查询一个元素是否包含在RangeSet中时,可以从树的根节点开始,沿着适当的分支向下遍历,直到找到一个包含该元素的范围或确定该元素不在RangeSet中。这种查询操作的时间复杂度也是对数级别的,因此RangeSet能够高效地处理大量的查询请求。

四、RangeSet的使用示例

使用 RangeSet 之前,我们得先了解一下 Guava 的Range 类,其实顾名思义就是表达区间范围,我们看一下它的 type 就明白了:
在这里插入图片描述

下面是一个使用RangeSet的简单示例,演示了如何创建一个RangeSet、向其中添加范围、并进行查询操作:

import com.google.common.collect.Range;  
import com.google.common.collect.RangeSet;  
import com.google.common.collect.TreeRangeSet;  
  
public class TreeRangeSetDemo {  
    public static void main(String[] args) {  
        // 创建一个空的TreeRangeSet  
        RangeSet<Integer> rangeSet = TreeRangeSet.create();  
  
        // 向RangeSet中添加几个不连续的范围  
        rangeSet.add(Range.closed(1, 3));     // [1, 3]  
        rangeSet.add(Range.open(5, 8));       // (5, 8)  
        rangeSet.add(Range.closedOpen(10, 12));// [10, 12)  
        rangeSet.add(Range.greaterThan(15));   // (15, +∞)  
  
        // 打印当前RangeSet的内容  
        System.out.println(rangeSet); // [1..3](5..8)[10..12)(15..+∞)  
  
        // 查询某个范围是否包含在RangeSet中  
        System.out.println(rangeSet.contains(Range.closed(2, 3)));   // true  
        System.out.println(rangeSet.contains(Range.open(6, 7)));     // true  
        System.out.println(rangeSet.contains(Range.closed(11, 11))); // true  
        System.out.println(rangeSet.contains(Range.closed(4, 5)));   // false  
  
        // 删除一个范围  
        rangeSet.remove(Range.open(5, 8));  
        System.out.println(rangeSet); // [1..3][10..12)(15..+∞)  
  
        // 获取与指定范围重叠的范围  
        RangeSet<Integer> overlappingRanges = rangeSet.subRangeSet(Range.atLeast(9));  
        System.out.println(overlappingRanges); // [10..12)(15..+∞)  
  
        // 获取指定范围的补集(这里仅展示与[0, 20]范围内的补集)  
        RangeSet<Integer> complement = rangeSet.complement().subRangeSet(Range.closed(0, 20));  
        System.out.println(complement); // (0..1)(3..5)(8..10)[12..15][15..20]  
        // 注意:由于complement()返回的是整个数域中不属于rangeSet的部分,  
        // 我们再次使用subRangeSet来限制补集的范围,以便更好地展示结果。  
  
        // 查询单个元素是否在RangeSet中  
        System.out.println(rangeSet.contains(2));    // true  
        System.out.println(rangeSet.contains(9));    // false  
  
        // 获取包含指定元素的范围  
        Range<Integer> rangeContaining11 = rangeSet.rangeContaining(11);  
        System.out.println(rangeContaining11); // [10..12)  
  
        Range<Integer> rangeContaining4 = rangeSet.rangeContaining(4);  
        System.out.println(rangeContaining4); // null,因为4不在rangeSet中  
  
        // 获取RangeSet的最小和最大元素(注意这不是一个Range,而是两个元素)  
        Integer minValue = rangeSet.asRanges().stream().map(Range::lowerEndpoint).min(Integer::compareTo).orElse(null);  
        Integer maxValue = rangeSet.asRanges().stream().map(Range::upperEndpoint).max(Integer::compareTo).orElse(null);  
        System.out.println("Min value: " + minValue); // Min value: 1  
        System.out.println("Max value: " + maxValue); // Max value: 2147483647 (Integer.MAX_VALUE,因为rangeSet包含(15..+∞))  
    }  
}

在这个例子中,我添加了一些不连续的整数范围,并进行了基本的操作,包括添加、删除范围、查询范围是否存在、获取范围的补集以及与指定范围重叠的范围等。我也演示了如何获取RangeSet中的最小和最大元素,尽管对于无限范围(15…+∞),最大值实际上是Integer.MAX_VALUE,因为TreeRangeSet内部使用Integer来表示范围,并且它会将这个无限范围视为上界为Integer.MAX_VALUE的范围。

请注意,在实际应用中,处理无限范围时应该特别小心,因为整数是有界的,而TreeRangeSet的某些操作可能会受到这个限制的影响。

再来看下 循环遍历 和 使用encloses方法检查范围包含关系 的示例:

        // 创建一个TreeRangeSet并添加一些不连续的范围  
        TreeRangeSet<Integer> rangeSet = TreeRangeSet.create();  
        rangeSet.add(Range.closed(1, 3));  
        rangeSet.add(Range.open(5, 8));  
        rangeSet.add(Range.closedOpen(10, 12));  
        rangeSet.add(Range.greaterThan(15));  
  
        // 使用encloses方法检查范围包含关系  
        boolean enclosesClosedRange = rangeSet.encloses(Range.closed(2, 3)); // true,因为[2,3]被[1,3]完全包含  
        boolean enclosesOpenRange = rangeSet.encloses(Range.open(6, 7)); // true,(6,7)被(5,8)完全包含  
        boolean enclosesSingletonRange = rangeSet.encloses(Range.singleton(11)); // true,11被[10,12)完全包含  
        boolean notEnclosesRange = rangeSet.encloses(Range.closed(4, 5)); // false,[4,5]不被任何范围完全包含  
  
        System.out.println("rangeSet.encloses(Range.closed(2, 3)): " + enclosesClosedRange);  
        System.out.println("rangeSet.encloses(Range.open(6, 7)): " + enclosesOpenRange);  
        System.out.println("rangeSet.encloses(Range.singleton(11)): " + enclosesSingletonRange);  
        System.out.println("rangeSet.encloses(Range.closed(4, 5)): " + notEnclosesRange);  
  
        // 遍历TreeRangeSet中的所有范围  
        System.out.println("Iterating over the ranges in the TreeRangeSet:");  
        Iterator<Range<Integer>> iterator = rangeSet.asRanges().iterator();  
        while (iterator.hasNext()) {  
            Range<Integer> range = iterator.next();  
            System.out.println(range);  
        }  
  
        // 使用增强的for循环遍历(更简洁)  
        System.out.println("Iterating over the ranges using enhanced for loop:");  
        for (Range<Integer> range : rangeSet.asRanges()) {  
            System.out.println(range);  
        }  
    }  

五、总结

Guava的RangeSet提供了一种高效、灵活的方式来处理范围集合。它基于范围树的数据结构,实现了范围的自动合并和高效的查询操作。通过RangeSet,我们可以方便地管理和操作各种范围集合,满足各种复杂的需求。在实际应用中,我们可以利用RangeSet来解决时间范围管理、数字范围限制等问题,提高代码的可读性和维护性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1420770.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【JLU】校园网linux客户端运行方法

终于给这输入法整好了&#xff0c;就像上面图里那样执行命令就行 写一个开机自启的脚本会更方便&#xff0c;每次都运行也挺烦的 补充了一键运行脚本&#xff0c;文件路径$DIR需要自己修改 #!/bin/bash DIR"/home/d0/ubuntu-drclient-64/DrClient" run_per_prog&qu…

微信小程序上传时报错message:Error: 系统错误,错误码:80051,source size 2148KB exceed max limit 2MB

问题&#xff1a; 微信小程序上传时错误码&#xff1a;80051,source size 2248KB exceed max limit 2MB 问题原因&#xff1a; 由于代码中的静态资源 图片大小超了200k以及主包的体积超出1.5M 解决办法 分包 tabBar 是主包的&#xff0c;不需要分包处理&#xff0c;以下是分…

0130-2-秋招面试—HTML篇

2023 HTML面试题 1.src和href的区别 scr用于替换当前元素&#xff0c;href用于在当前文档和外部资源之间建立联系。 <script src"main.js"></script><link href"style.css" rel"stylesheet" />2.对HTML语义化的理解 根据内…

Linux:重定向

Linux&#xff1a;重定向 输出重定向追加重定向输出重定向与追加重定向的本质输入重定向 输出重定向 在Linux中&#xff0c;输出重定向是一种将命令的输出发送到不同位置的方法。通常&#xff0c;执行命令时&#xff0c;输出会显示在终端上。然而&#xff0c;使用输出重定向&a…

5-1 A. DS串应用--KMP算法

题目描述 学习KMP算法&#xff0c;给出主串和模式串&#xff0c;求模式串在主串的位置 算法框架如下&#xff0c;仅供参考 输入 第一个输入t&#xff0c;表示有t个实例 第二行输入第1个实例的主串&#xff0c;第三行输入第1个实例的模式串 以此类推 输入样例&#xff1a; 3 qwe…

产品经理的发展方向是什么?市场需求现状如何?未来有哪些趋势?作为产品经理应该如何准备?

目录 了解产品经理的发展方向 市场需求现状 未来有那些趋势&#xff1f; 作为产品经理应该作何准备? 了解产品经理的发展方向 市场需求现状 未来有那些趋势&#xff1f; 个人软件 &#xff1a;智能终端&#xff0c;轻量化应用&#xff0c;虚拟社交等企业软件&#xff1a…

用GoLand写一个小玩意-git定时push、commit

这里是weihubeats,觉得文章不错可以关注公众号小奏技术&#xff0c;文章首发。拒绝营销号&#xff0c;拒绝标题党 背景 有时候你想刷一刷github的commit墙&#xff0c;或者公司需要每天提交代码&#xff0c;你想摸鱼。就有这么一个小需求&#xff0c;想要自动commit、push代码…

solr的原理是什么

1 Java程序里如果有无限for循环的代码导致CPU负载超高&#xff0c;如何排查&#xff1f; 排查Java程序中由于无限循环导致的CPU负载过高的问题&#xff0c;可以按照以下步骤进行&#xff1a; 资源监控&#xff1a; 使用系统命令行工具&#xff08;如Linux上的top或htop&#xf…

Arrays.asList()方法调用add()或remove()抛出java.lang.UnsupportedOperationException问题

在使用Arrays.asList方法将以,分割的字符串转为list集合时&#xff0c;调用add和remove等方法时会抛出java.lang.UnsupportedOperationException。以下为原因和解决方法。 原因&#xff1a; Arrays.asList()方法返回了一个Arrays类的一个继承了AbstractList的ArrayList内部类…

富文本编辑器CKEditor4简单使用-03(图片上传)

富文本编辑器CKEditor4简单使用-03&#xff08;图片上传&#xff09; 1. 前言1.1 关于CKEditor4的安装及简单使用1.2 关于CKEditor4的插件安装及使用1.3 关于Easy Image 2. CKEditor4自带的默认上传图片按钮功能3. 使用增强的图像插件3.1 什么是增强的图像插件3.2 下载并安装增…

jdk17新特性—— instanceof的模式匹配

目录 一、instanceof模式匹配的概述二、instanceof模式匹配代码示例2.1、jdk17之前 instanceof用法 代码示例2.2、jdk17及之后 instanceof用法 代码示例一2.3、jdk17及之后 instanceof用法 代码示例二 一、instanceof模式匹配的概述 instanceof增加了模式匹配功能&#xff0c;…

vue3之echarts3D环柱图-间隔版

vue3之echarts3D环柱图-间隔版 效果&#xff1a; 版本 "echarts": "^5.4.1", "echarts-gl": "^2.0.9" 核心代码&#xff1a; <template><div class"content"><div ref"eCharts" class"c…

分享4款不能错过的修改照片尺寸的软件!

在当今这个数字化时代&#xff0c;照片已经成为我们分享生活、表达观点的重要方式。但是&#xff0c;你是否曾遇到过这样的问题&#xff1a;一张精美的照片因为尺寸不合适而无法在朋友圈中展现出最佳效果&#xff1f;不用担心&#xff0c;今天我们就来聊聊那些可以帮助你轻松修…

Day02-课后练习2-参考答案(数据类型和运算符)

文章目录 巩固题1、案例&#xff1a;今天是周2&#xff0c;100天以后是周几&#xff1f;2、案例&#xff1a;求三个整数x,y,z中的最大值3、案例&#xff1a;判断今年是否是闰年4、分析如下代码的计算结果5、分析如下代码的计算结果6、分析如下代码的计算结果7、分析如下代码的计…

Real power also called true or active power

Real power also called true or active power flyfish 三相电路的总功率都等于各相功率之和&#xff0c;任意相的有功功率等于该相的相电压乘以相电流&#xff0c;再乘以该相负载的功率因数。 P P A P B P C PP_AP_BP_C PPA​PB​PC​ P有功功率&#xff0c;瓦特(W) U电压…

Springboot 实现基于用户和物品的协同过滤算法

目录 简介 协同过滤算法(简称CF) 算法详解 算法使用 基于用户 基于物品 总结 前言-与正文无关 生活远不止眼前的苦劳与奔波&#xff0c;它还充满了无数值得我们去体验和珍惜的美好事物。在这个快节奏的世界中&#xff0c;我们往往容易陷入工作的漩涡&#xff0c;忘记了停…

简单线性Dp

文章目录 线性Dp的定义AcWing 898. 数字三角形思路CODE正序倒序 AcWing 895. 最长上升子序列Dp 分析CODE AcWing 897. 最长公共子序列Dp 分析CODE 线性Dp的定义 处理起来是线性的&#xff08;&#xff1f;&#xff1f;&#xff1f;&#xff09;&#xff0c;这部分交给ai老先生…

Gurobi输出日志文件的解读【Gurobi】

本章来解读一下Gurobi的刷屏式输出&#xff0c;根本不需要cout&#xff0c;直接通过model.optimize();进行输出。 例如&#xff1a; 现在我们来逐行解读一下&#xff1a; 第一部分&#xff1a;版本型号 可以直接跳过 CPU model: 12th Gen Intel(R) Core(TM) i5-12500H, instr…

【EI会议征稿通知】第五届计算机信息和大数据应用国际学术会议(CIBDA 2024)

第五届计算机信息和大数据应用国际学术会议&#xff08;CIBDA 2024&#xff09; 2024 5th International Conference on Computer Information and Big Data Applications 第五届计算机信息和大数据应用国际学术会议&#xff08;CIBDA 2024&#xff09;将于2024年3月22-24日在…

Google Chrome 中出现 ERR_SSL_KEY_USAGE_INCOMPATIBLE 错误

证书的方式发生了变化&#xff0c;出现了这个新错误&#xff0c;导致我无法浏览该网站。 可以右键属性获取位置 关闭导航器chrome并转到文件夹&#xff0c;找到Local State文件并删除 执行指令结束进程&#xff0c;重新打开浏览器即可 taskkill /im "chrome.exe"…