百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

程序员的福音 - Apache Commons Collections

toyiye 2024-07-03 02:07 17 浏览 0 评论


此文是系列文章第九篇,前几篇请点击链接查看

程序猿的福音 - Apache Commons简介

程序员的福音 - Apache Commons Lang

程序员的福音 - Apache Commons IO

程序员的福音 - Apache Commons Codec

程序员的福音 - Apache Commons Compress

程序员的福音 - Apache Commons Exec

程序员的福音 - Apache Commons Email

程序员的福音 - Apache Commons Net


Apache Commons Collections 是对 java.util.Collection 的扩展。


目前 Collections 包有两个 commons-collections 和commons-collections4,commons-collections 最新版本是3.2.2,不支持泛型,目前官方已不在维护。collections4 目前最新版本是4.4,最低要求 Java8 以上。相对于 collections 来说完全支持 Java8 的特性并且支持泛型,该版本无法兼容旧有版本,于是为了避免冲突改名为 collections4。推荐直接使用该版本。(注:两个版本可以共存,使用时需要注意)


包结构如下:

org.apache.commons.collections4
org.apache.commons.collections4.bag
org.apache.commons.collections4.bidimap
org.apache.commons.collections4.collection
org.apache.commons.collections4.comparators
org.apache.commons.collections4.functors
org.apache.commons.collections4.iterators
org.apache.commons.collections4.keyvalue
org.apache.commons.collections4.list
org.apache.commons.collections4.map
org.apache.commons.collections4.multimap
org.apache.commons.collections4.multiset
org.apache.commons.collections4.properties
org.apache.commons.collections4.queue
org.apache.commons.collections4.sequence
org.apache.commons.collections4.set
org.apache.commons.collections4.splitmap
org.apache.commons.collections4.trie


maven坐标如下:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.4</version>
</dependency>


由于其功能较多,下面挑几个有代表的简单介绍一下用法。


01

工具类


1. CollectionUtils

String str = null;
List list1 = Arrays.asList(new String[]{"1", "2", "3"});
List list2 = Arrays.asList(new String[]{"1", "2", "4"});
// 判断是否为空(null或空list都为true)
CollectionUtils.isEmpty(list1);
// 添加元素(忽略null元素)
CollectionUtils.addIgnoreNull(list1, str);
// list是否包含subList中的所有元素
CollectionUtils.containsAll(list1, list2); // false
// list是否包含subList中的任意一个元素
CollectionUtils.containsAny(list1, list2); // true
// list1 减去 list2
CollectionUtils.subtract(list1, list2); // ["3"]
// 合并两个list并去重
CollectionUtils.union(list1, list2); //["1", "2", "3", "4"]
// 取两个list同时存在的元素
CollectionUtils.intersection(list1, list2); // [1", "2"]


2. ListUtils

List list1 = Arrays.asList(new String[]{"1", "2", "3"});
List list2 = Arrays.asList(new String[]{"1", "2", "4"});
// 同CollectionUtils, 返回结果为List
ListUtils.subtract(list1, list2); // ["3"]
ListUtils.union(list1, list2); //["1", "2", "3", "4"]
ListUtils.intersection(list1, list2); // [1", "2"]
// 判断两个集合中的内容是否完全相同(顺序也一致)
ListUtils.isEqualList(list1, list2); // false
// list1如果为null则转换为空List
ListUtils.emptyIfNull(list1);
// list1中所有元素做Hash
ListUtils.hashCodeForList(list1);


除了以上介绍了两个还有 MapUtils,SetUtils,EnumerationUtils,IterableUtils 等不是很常用就不多做介绍了。



02

集合扩展


1. FixedSizeList

FixedSizeList 用于装饰另一个 List 以阻止修改其大小。不支持添加、删除、清除等操作。set 方法是允许的(因为它不会改变列表大小),下面看代码示例

List<String> sourceList = new ArrayList<>();
sourceList.add("1");
// 装饰一下原list
List<String> list = FixedSizeList.fixedSizeList(sourceList);
list.set(0, "11");
println(list); // [11,2,3]
// 以下改变容器size的操作会抛出异常
list.add("4"); // UnsupportedOperationException("List is fixed size")
list.remove("5"); // UnsupportedOperationException("List is fixed size")
list.clear(); // UnsupportedOperationException("List is fixed size")


2. SetUniqueList

SetUniqueList 用来装饰另一个 List 以确保不存在重复元素,内部使用了 Set 来判断重复问题

List<String> sourceList = new ArrayList<>();
sourceList.add("1");
sourceList.add("2");
// 元素不重复的list
SetUniqueList<String> list = SetUniqueList.setUniqueList(sourceList);
// 存在则不处理,不会影响原来顺序
list.add("2");
println(list); // [1,2]


3. TransformedList

TransformedList 装饰另一个 List 以转换添加的对象。add 和 set 方法受此类影响。

List<String> sourceList = new ArrayList<>();
sourceList.add("1");
sourceList.add("2");
// 转换list,在添加元素的时候会通过第二个参数Transformer转换一下
// (Transformer接口只有一个抽象方法可以使用lambda表达式)
       
// transformingList不会对原list的已有元素做转换
TransformedList<String> list = TransformedList.transformingList(sourceList, e -> e.concat("_"));
list.add("a");
println(list); // [1, 2, a_]


// transformedList会对原list的已有元素做转换
list = TransformedList.transformedList(sourceList, e -> e.concat("_"));
list.add("a");
println(list); // [1_, 2_, a_]


4. PredicatedList

PredicatedList 装饰另一个 List ,装饰后的 List 在添加元素的时候会调用 Predicate 接口来判断元素,匹配通过才会被添加到集合中。

List<String> sourceList = new ArrayList<>();
// 在添加元素的时候会通过第二个参数Predicate判断一下是否符合要求,符合要求才添加进来
PredicatedList<String> list = PredicatedList.predicatedList(new ArrayList<>(), e -> e.startsWith("_"));
list.add("_4");
println(list); // [_4]


// 以下会抛异常:java.lang.IllegalArgumentException: Cannot add Object '4'
list.add("4");


5. ListOrderedSet

ListOrderedSet 有序的Set,顺序按照元素添加顺序排列,类似 List

// 有序的set,按照插入顺序排序
Set<String> set = new ListOrderedSet<>();
set.add("aa");
set.add("11");
set.add("哈哈");
println(set); // [aa,11,哈哈]


6. Bag

Bag 接口是带计数功能的集合扩展,它继承了 Collection 接口,可以当做集合来使用

// bag 带计数功能的集合
Bag<String> bag = new HashBag<>();
bag.add("a");
bag.add("b");
bag.add("a");
println(bag.size()); // 3
println(bag.getCount("a")); // 2


集合扩展除了以上列举的几个外,还有很多就不做介绍了,感兴趣的可以自行翻阅源码研究。


03

Map扩展



1. MultiValuedMap

MultiValuedMap 和正常的 Map 有点区别,同一个 key 允许存放多个 value,这些 value 会放到一个 List 中。这个功能如果用 Java 的 Map 我们需要构造一个 Map<String, List<String>> 加个各种操作来实现

// list实现,允许value重复
ListValuedMap<String, String> map = new ArrayListValuedHashMap<>(); 
map.put("user", "张三");
map.put("user", "李四");
map.put("user", "张三");
map.put("age", "12");
// 注意:value的泛型是String, 但是get方法返回的是List<String>
List<String> users2 = map.get("user"); // [张三,李四,张三]


// multiMap的其他方法
map.containsKey("user"); // true
map.containsValue("张三"); // true
map.containsMapping("user", "张三"); // true


int size = map.size(); // 4


Collection<String> ss = map.values();// [张三,李四,张三,12]
map.remove("user"); // 清空user的所有value
// 转换为原生map
Map<String, Collection<String>> jMap = map.asMap();


2. CaseInsensitiveMap

key大小写不敏感的Map

// key大小写不敏感
Map<String, Integer> map = new CaseInsensitiveMap<>();
map.put("one", 1);
map.put("two", 2);
Integer o = map.get("ONE");
println(o); // 1


3. OrderedMap

有顺序的 Map,按照插入顺序排序。如果使用 hashMap 的话 key 会按照 hash 值排序,可能和插入顺序一样,也可能不一样。key 数量和不同 JDK 版本都可能影响顺序,这是由于不同版本 jdk map 的 hash 算法有区别,hash 算法和当前 map 的容量也有关系。

// key有序:按照插入顺序
OrderedMap<String, String> map = new ListOrderedMap<>();
map.put("哈哈", "1");
map.put("此处", "2");
map.put("cc", "3");
map.put("dd", "4");
// 得到的keySet有序
Set<String> set = map.keySet(); // 哈哈,此处,cc,dd
String nk = map.nextKey("此处"); // cc
String pk = map.previousKey("此处"); // 哈哈


4. LRUMap

LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。

各种缓存框架都有对 LRU 算法的支持,如 EhCache,GuavaCache,Redis 等,可以说是很常用的一种算法

LRUMap<String, String> map = new LRUMap<>(2);
map.put("aa", "1");
map.put("bb", "2");
map.put("cc", "3");
// 最早没有被使用的aa将被移出
println(map); // [bb:2, cc:3]
// 访问一次bb,此时在put的话将会移出最早没有被访问的cc
map.get("bb");
map.put("dd", "4");
println(map); // [bb:2, dd:4]


5. PassiveExpiringMap

装饰一个 Map 以在达到过期时间时删除过期条目。当在 Map 中放置键值对时,此装饰器使用 ExpirationPolicy 来确定条目应保持多长时间,由到期时间值定义。当对 Map 做操作的时候才会检查元素是否过期并触发删除操作。

// 存活一秒钟
int ttlMillis = 1000;
PassiveExpiringMap.ExpirationPolicy<String, String> ep = new PassiveExpiringMap.ConstantTimeToLiveExpirationPolicy<>(ttlMillis);
PassiveExpiringMap<String, String> map = new PassiveExpiringMap<>(ep);
map.put("a", "1");
map.put("b", "2");
map.put("c", "3");
// 等待一秒后在获取
Thread.sleep(1000);
String vc = map.get("c");
println(vc); // null


6. ReferenceMap

ReferenceMap 允许垃圾收集器删除映射。可以指定使用什么类型的引用来存储映射的键和值。如果使用的不是强引用,则垃圾收集器可以在键或值变得不可访问,或者 JVM 内存不足时删除映射。用它做一个简易的缓存不会导致存放内容过多导致内存溢出。


关于 Java 的引用类型主要四种 强引用,软引用,弱引用,虚引用。平时我们基本用的都是强引用,关于这四种引用类型不是本文介绍的重点,如果不了解的话可以自行搜索进行学习。


下面直接看 ReferenceMap 代码示例

// key value全部使用软引用,再JVM内存不足的情况下GC会将软引用的键值对回收
ReferenceMap<String, String> map = new ReferenceMap<>(AbstractReferenceMap.ReferenceStrength.SOFT, AbstractReferenceMap.ReferenceStrength.SOFT);
// 其他map操作 ... ...


7. BidiMap

BidiMap 允许在 key 和 value 之间进行双向查找。其中一个键可以查找一个值,一个值可以同样轻松地查找一个键。这个接口扩展了 Map,value 不允许重复,如果重复将同时覆盖旧的键值对。

// 双向map, 可通过value获取key
// value也不允许重复,如果重复将会覆盖旧值
BidiMap<String, String> map = new TreeBidiMap<>();
map.put("dog", "狗");
map.put("cat", "猫");
// value重复的话key也会被覆盖,相当于"cat2:猫"会覆盖掉"cat:猫"
// map.put("cat2", "猫");
println(map); // {cat=猫, dog=狗}
String key = map.getKey("狗");
println(key); // dog


// 反向,value变为key,key变为value
BidiMap<String, String> iMap = map.inverseBidiMap();
println(iMap); // {狗=dog, 猫=cat}
println(iMap.get("狗")); // dog


// 对反向map操作同时影响原map
iMap.put("鱼", "fish");
println(iMap); // {狗=dog, 猫=cat, 鱼=fish}
println(map); // {cat=猫, dog=狗, fish=鱼}


Map 扩展除了刚才介绍了几种外还有一些扩展限于篇幅就不做介绍了



05

总结


Java 集合 和 Map 可以说是非常常用的数据结构了, Commons Collections 作为 Java 集合的扩展,增加了很多功能各异的集合 和 Map,对于实现一些特殊的需求来说是很方便的。如果有对应的需求可以考虑使用。


后续章节我将继续给大家介绍 commons 中其他好用的工具类库,期待你的关注。

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码