Apache出品集合工具类推荐:Apache Commons Collections SetUtils

1 概览

本文是关于Apache Commons Collections库的SetUtils API。此工具接口将操作Java的Set数据结构。

2 安装依赖

基于maven:

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

基于gradle:

compile 'org.apache.commons:commons-collections4:4.1'

3 predicatedSet()

SetUtils的predicatedSet()方法允许定义要插入Set的元素的条件,接受Set对象和predicate。
通过此方法,可以很轻松地验证一个集合是否满足某个特定条件。比如在使用某个第三方库或接口之前。
任何一个元素的验证失败,都会抛出IllegalArgumentException。下面的代码示例中,要求sourceSset中的字符串必须是L开头,然后返回一个验证通过的结果给validateingSet。

Set<String> validatingSet
  = SetUtils.predicatedSet(sourceSet, s -> s.startsWith("L"));

此外,SetUtils还有predicatedSortedSet()和predicatedNavigableSet()来处理SortedSet和NavigableSet 。

4 Set的合并、交集、插入

SetUtils支持对Set进行合并、交集、插入等操作。
diffence()方法,对两个Set返回不可变的SetUtils.SetView对象。此对象里包含Set a存在,但set b中不存在的元素:

Set<Integer> a = new HashSet<>(Arrays.asList(1, 2, 5));
Set<Integer> b = new HashSet<>(Arrays.asList(1, 2));
SetUtils.SetView<Integer> result = SetUtils.difference(a, b);
  
assertTrue(result.size() == 1 && result.contains(5));

如果对返回的SetView对象做操作,比如add()或addAll()等,会抛出UnsupportedOperationException。
如果要操作返回结果,调用toSet()方法将返回结果从SetUtils.SetView转换为可写的Set对象:

Set<Integer> mutableSet = result.toSet();

SetUtils的合并方法会返回set a和b中所有的元素。同样地,返回结果也是一个SetUtils.SetView对象:

Set<Integer> expected = new HashSet<>(Arrays.asList(1, 2, 5));
SetUtils.SetView<Integer> union = SetUtils.union(a, b);
  
assertTrue(SetUtils.isEqualSet(expected, union));

注意:isEqualSet()是用来检查两个set是否相等的。

为了获取set的交集(同时在set a和b中存在的元素),使用intersection(),返回SetView。

Set<Integer> expected = new HashSet<>(Arrays.asList(1, 2));
SetUtils.SetView<Integer> intersect = SetUtils.intersection(a, b);
  
assertTrue(SetUtils.isEqualSet(expected, intersect));

5 转换Set元素

SetUtils.transformedSet()接受Set对象和一个Transformer接口,Transformer接口的实现将对set里面的每个元素按定义的规则进行转换。
转换逻辑会对每个加入set的元素生效。下面这段代码,会对每个加入set的元素做乘以2的处理:

Set<Integer> a = SetUtils.transformedSet(new HashSet<>(), e -> e * 2  );
a.add(2);
  
assertEquals(a.toArray()[0], 4);

transformedSet()很有用,还可以用来转换元素类型,比如从String转换为Integer。只要保证输出是输入的子类型。
如果我们使用的是SortedSet或NavigableSet,相应地我们可以使用transformedSortedSet()和transformedNavigableSet()。
注意:上面的例子中,我们是实例化了一个HashSet对象传给transformedSet()方法的。如果传递是一个已存在的非空的Set,那么已存在的元素是不会被转换的。如果我们现在转换已存在的元素,那么需要使用org.apache.commons.collections4.set.TransformedSet里面的transformedSet()方法。

Set<Integer> source = new HashSet<>(Arrays.asList(1));
Set<Integer> newSet = TransformedSet.transformedSet(source, e -> e * 2);
  
assertEquals(newSet.toArray()[0], 2);
assertEquals(source.toArray()[0], 2);

如上,source里面的元素也被转换了的,结果被复制到新的集合newSet中。

6 集合差异

SetUtils提供一个静态方法来获取集合的差异。集合a和集合b的差异,就是说只存在于a或b中的元素。
下面看看代码:

Set<Integer> a = new HashSet<>(Arrays.asList(1, 2, 5));
Set<Integer> b = new HashSet<>(Arrays.asList(1, 2, 3));
SetUtils.SetView<Integer> result = SetUtils.disjunction(a, b);
  
assertTrue(
  result.toSet().contains(5) && result.toSet().contains(3));

7 SetUtils的其他方法

SetUtils库还有很多其他方法:

  • synchronizedSet()或synchronizedSortedSet():
    获取线程安全的Sest。但是,官方文档指出,必须手动同步返回set的迭代器,以避免一些不确定的行为。
  • unmodifiableSet():
    获取一个只读的set。对这个set做增加元素的操作,会抛出UnsupportedOperationException异常。
  • emptySet():
    返回类型安全的,不可变的空set。
  • emptyIfNull():
    接受一个null的集合对象。返回一个空的、只读的集合。如果提供空集合,则返回空集合,否则返回提供的集合。
  • orderedSet():
    保持元素加入顺序,返回集合。
  • hashCodeForSet():
    为集合创建一个hashcode。这样,拥有同样元素的集合可以具有一样hashcode。
  • newIdentityHashSet():
    返回一个HashSet,这个集合使用==来判断元素是否相等,而不是用equals()方法。更多说明在这里

8 结论

本文我们讨论了SetUtils库,这个库提供了一些静态方法来更高效简单地操作集合类型的数据结构。
本文相关代码在github,SetUtils的官方文档在这里

编译:https://www.baeldung.com/apache-commons-setutils

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353

推荐阅读更多精彩内容