一、简介
Guava
在原有的Java
集合类型上新增了多种集合类型,而其中一个类型就是MultiSet
.
MultiSet
的使用场景十分常见,基本上用于统计次数相关的业务都可以用到它.
MultiSets
工具类基本上就是为它而诞生的.提供了如验证包含关系、批量移除元素出现次数等实用方法......
二、常用方法
1、验证super Multiset是否包含sub MultiSet方法 - containsOccurrences()
containsOccurrences(Multiset> superMultiset, Multiset> subMultiset)
方法将会比较superMultiset
是否完全包含subMultiset
,如果完全包含返回TRUE
,否则返回FALSE
.
简单实验代码:
Multiset multisetSup = TreeMultiset.create();
multisetSup.add(1, 5);
multisetSup.add(2, 10);
//元素节点不完全包含
Multiset multisetSub1 = TreeMultiset.create();
multisetSub1.add(1, 5);
multisetSub1.add(3, 10);
//元素节点完全包含但是出现次数不完全包含
Multiset multisetSub2 = TreeMultiset.create();
multisetSub2.add(1, 6);
multisetSub2.add(2, 9);
//元素节点以及出现次数都完全包含
Multiset multisetSub3 = TreeMultiset.create();
multisetSub3.add(1, 4);
multisetSub3.add(2, 9);
//测试containsOccurrences方法
//和Collection.containsAll不同,它只校验元素是否被包含,并且会忽略掉count的存在
System.out.println("=======================测试containsOccurrences()方法 - 元素节点不完全包含=======================" + Multisets.containsOccurrences(multisetSup, multisetSub1));
System.out.println("=======================测试containsOccurrences()方法 - 元素节点完全包含但是出现次数不完全包含=======================" + Multisets.containsOccurrences(multisetSup, multisetSub2));
System.out.println("=======================测试containsOccurrences()方法 - 元素节点以及出现次数都完全包含=======================" + Multisets.containsOccurrences(multisetSup, multisetSub3));
实验结果:
=======================测试containsOccurrences()方法 - 元素节点不完全包含=======================false
=======================测试containsOccurrences()方法 - 元素节点完全包含但是出现次数不完全包含=======================false
=======================测试containsOccurrences()方法 - 元素节点以及出现次数都完全包含=======================true
可以发现实验结果与预期一致.
值得注意的是
:
superMultiset
和subMultiset
都不能为NULL
.
2、移除指定MultiSet元素出现次数方法 - removeOccurrences()
MultiSets
提供了移除指定MultiSet元素次数的方法 - removeOccurrences( Multiset> multisetToModify, Multiset> occurrencesToRemove)
.
它的作用为将需要移除的occurrencesToRemove
作用于待修改的multisetToModify
上,multisetToModify
将移除掉和occurrencesToRemove
节点相同的出现次数.如果原有multisetToModify
发生了变化则返回TRUE
,否则返回FALSE
.
简单实验代码:
//测试removeOccurrences方法
//它将会把需要修改的Multiset以及将要移除的MultiSet做扣减
//当前方法的含义理解为批量删除multisetToModify中的指定节点存在数量
//MultiSet提供了remove()方法可以删除存在的节点以及删除指定节点的次数,为啥不直接支持批量的而要放在MultiSets中呢?
//MultiSet提供了removeAll()方法支持批量删除节点,为什么此时不能支持删除指定的次数?
//这是有什么考虑在里面么?我认为从使用者角度来说MultiSet直接支持了就不用在多调用一个工具类岂不是更方便?
//初始化待修改的MultiSet
Multiset multisetToModify = TreeMultiset.create();
multisetToModify.add(1, 5);
multisetToModify.add(2, 5);
//初始化作为指定条件的MultiSet
Multiset removeTo = TreeMultiset.create();
//扣减存在的元素且出现次数小于原有元素出现次数
removeTo.add(1, 3);
//扣减存在的元素且出现次数大于原有元素出现次数
removeTo.add(2, 6);
//扣减不存在的元素
removeTo.add(3, 1);
System.out.println("=======================测试removeOccurrences()方法=======================" + Multisets.removeOccurrences(multisetToModify, removeTo));
System.out.println(multisetToModify);
实验结果:
=======================测试removeOccurrences()方法=======================true
[1 x 2]
可以发现实验结果与预期一致.对于存在的节点扣除需要移除的出现次数,对于不存在的节点则不进行任何操作.
值得注意的是
:
multisetToModify
和occurrencesToRemove
都不能为NULL
.
3、保留覆盖方法 - retainOccurrences()
当我们只想对原有Multiset
保留指定的信息时,Multisets
提供了retainOccurrences( Multiset> multisetToModify, Multiset> multisetToRetain)
方法,它就完美实现了保留逻辑,将想要保留的数据信息multisetToRetain
作用于待调整的数据multisetToModify
上面,如果multisetToModify
发生了变化返回TRUE
,否则返回FALSE
.
实验代码:
//测试retainOccurrences()方法
//它会将需要修改的MultiSet与需要保留的MultiSet进行比对,返回是否被修改
//如果被修改 - 那么原有的节点以及节点对应的数值将会被替换
//类似于replace()方法
Multiset removeFrom = TreeMultiset.create();
removeFrom.add(1, 5);
removeFrom.add(2, 5);
removeFrom.add(4, 5);
Multiset toRetain = TreeMultiset.create();
//保留已存在的节点
toRetain.add(1, 4);
//保留已存在的节点
toRetain.add(2, 5);
//保留不存在的节点
toRetain.add(3, 6);
System.out.println("=======================测试retainOccurrences()方法=======================" + Multisets.retainOccurrences(removeFrom, toRetain));
System.out.println(removeFrom);
实验结果:
=======================测试retainOccurrences()方法=======================true
[1 x 4, 2 x 5]
可以发现相交的节点都保留multisetToRetain
中的节点信息,其余的都被干掉了.
值得注意的是
:
multisetToModify
和occurrencesToRetain
都不能为NULL
.
4、两个MultiSet取交集方法 - intersection()
当然比较常用的取交集的方法MultiSets
也是提供的 - intersection( final Multiset
,它会对两个Multiset
的元素取交集,交集的出现次数已最小的次数为准.
实验代码:
//测试交集方法 - 交集的结果以最小集为准
Multiset section1 = TreeMultiset.create();
section1.add(1, 5);
section1.add(2, 5);
Multiset section2 = TreeMultiset.create();
section2.add(1, 4);
section2.add(2, 5);
section2.add(3, 6);
Multiset intersection = Multisets.intersection(section1, section2);
System.out.println("=======================测试intersection()方法=======================" + intersection);
实验结果:
=======================测试intersection()方法=======================[1 x 4, 2 x 5]
可以发现目标结果与预期一致.
值得注意的是
:
multiset1
和multiset2
都不能为NULL
.
5、根据元素出现次数降序排序方法 - copyHighestCountFirst
Multisets
提供了降序排序方法 - copyHighestCountFirst(Multiset
,它会返回一个不可变的视图,视图元素顺序按照元素出现次数到下排序.
实验代码:
//测试通过元素出现次数降序排序方法
Multiset multiset = TreeMultiset.create();
//测试元素出现次数相同 - 录入不规则顺序 - before
multiset.add(12, 7);
multiset.add(1, 5);
multiset.add(2, 6);
//测试元素出现次数相同 - 录入不规则顺序 - before
multiset.add(11, 7);
multiset.add(3, 7);
//测试元素出现次数相同 - 录入不规则顺序 - after
multiset.add(10, 7);
multiset.add(4, 8);
multiset.add(5, 9);
System.out.println("=========================测试copyHighestCountFirst方法()=====================" + Multisets.copyHighestCountFirst(multiset));
实验结果:
=========================测试copyHighestCountFirst方法()=====================[5 x 9, 4 x 8, 3 x 7, 10 x 7, 11 x 7, 12 x 7, 2 x 6, 1 x 5]
可以发现当出现元素出现次数不同的时候,按照元素出现次数最多的元素降序排序,相同的时候......最终返回的是一个不可变的视图
......未完待续