程序员的福音 - Apache Commons Collections


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

程序猿的福音 - 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>
    >commons-collections4>
    >4.4>
>

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

01. 工具类

1. CollectionUtils

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");
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<>();
// 在添加元素的时候会通过第二个参数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

// 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> 加个各种操作来实现

// 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 的容量也有关系。

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 做操作的时候才会检查元素是否过期并触发删除操作。

// 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,对于实现一些特殊的需求来说是很方便的。如果有对应的需求可以考虑使用。

 转自:https://www.jianshu.com/p/f2345d69d8f9