龙空技术网

程序员的福音 - Apache Commons Collections

菜鸟码农的Java笔记 567

前言:

如今看官们对“apachecommons包有哪几个”都比较注重,你们都需要了解一些“apachecommons包有哪几个”的相关内容。那么小编在网摘上网罗了一些有关“apachecommons包有哪几个””的相关文章,希望小伙伴们能喜欢,我们一起来学习一下吧!

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

程序猿的福音 - 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.collections4org.apache.commons.collections4.bagorg.apache.commons.collections4.bidimaporg.apache.commons.collections4.collectionorg.apache.commons.collections4.comparatorsorg.apache.commons.collections4.functorsorg.apache.commons.collections4.iteratorsorg.apache.commons.collections4.keyvalueorg.apache.commons.collections4.listorg.apache.commons.collections4.maporg.apache.commons.collections4.multimaporg.apache.commons.collections4.multisetorg.apache.commons.collections4.propertiesorg.apache.commons.collections4.queueorg.apache.commons.collections4.sequenceorg.apache.commons.collections4.setorg.apache.commons.collections4.splitmaporg.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 减去 list2CollectionUtils.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, 返回结果为ListListUtils.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则转换为空ListListUtils.emptyIfNull(list1);// list1中所有元素做HashListUtils.hashCodeForList(list1);

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

02

集合扩展

1. FixedSizeList

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

List<String> sourceList = new ArrayList<>();sourceList.add("1");// 装饰一下原listList<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");// 元素不重复的listSetUniqueList<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()); // 3println(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"); // truemap.containsValue("张三"); // truemap.containsMapping("user", "张三"); // trueint size = map.size(); // 4Collection<String> ss = map.values();// [张三,李四,张三,12]map.remove("user"); // 清空user的所有value// 转换为原生mapMap<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,ddString nk = map.nextKey("此处"); // ccString 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的话将会移出最早没有被访问的ccmap.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变为valueBidiMap<String, String> iMap = map.inverseBidiMap();println(iMap); // {狗=dog, 猫=cat}println(iMap.get("狗")); // dog// 对反向map操作同时影响原mapiMap.put("鱼", "fish");println(iMap); // {狗=dog, 猫=cat, 鱼=fish}println(map); // {cat=猫, dog=狗, fish=鱼}

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

05

总结

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

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

标签: #apachecommons包有哪几个 #apachecommons #apachecommons排序