Multiset —— 把重复的元素放入集合
一、接口声明
以下是 com.google.common.collect.Multiset<E>
接口的声明:
@GwtCompatible public interface Multiset<E> extends Collection<E>
二、接口方法
官方文档:https://google.github.io/guava/releases/27.0.1-jre/api/docs/com/google/common/collect/Multiset.html
修饰符和类型 | 方法描述 |
---|---|
boolean | add(E element) 向其中添加单个元素. |
int | add(E element, int occurrences) 增加给定元素在Multiset中的计数 |
boolean | contains(@Nullable Object element) 是否包含元素. |
boolean | containsAll(Collection<?> elements) 如果这个多集至少包含一个出现的指定集合中的所有元素. |
int | count(@Nullable Object element) 返回给定参数元素的个数. |
Set<E> | elementSet() Multiset中不重复元素的集合,类型为Set |
Set<Multiset.Entry<E>> | entrySet() 和Map的entrySet类似,返回Set<multiset.entry |
boolean | equals(@Nullable Object object) 比较指定对象与此multiset是否相等. |
default void | forEach(Consumer<? super E> action) 元素遍历. |
default void | forEachEntry(ObjIntConsumer<? super E> action) 为此多集中的每个不同元素运行指定的操作,以及该元素的出现次数。 |
int | hashCode() 返回此multiset的哈希码. |
Iterator<E> | iterator() 返回一个迭代器,包含Multiset的所有元素(包括重复的元素) |
boolean | remove(@Nullable Object element) 移除一个元素,其count值 会响应减少. |
int | remove(@Nullable Object element, int occurrences) 减少给定元素在Multiset中的计数 |
boolean | removeAll(Collection<?> c) 去除出现给给定集合参数的所有的元素. |
boolean | retainAll(Collection<?> c) 保留出现在给定集合参数的所有的元素. |
int | setCount(E element, int count) 设置给定元素在Multiset中的计数,不可以为负数. |
boolean | setCount(E element, int oldCount, int newCount) 将符合原有重复个数的元素修改为新的重复次数. |
int | size() 返回所有元素的总个数(包括重复的元素) |
default Spliterator<E> | spliterator() 在此集合中的元素上创建Spliterator. |
String | toString() 返回该对象的字符串表示. |
从接口 java.util.Collection
继承的方法有:addAll
, clear
, isEmpty
, parallelStream
, removeIf
, stream
, toArray
三、Multiset 介绍
在JDK中,List
和 Set
有一个基本的区别,就是 List 可以包含多个相同对象,且是有顺序的,而 Set 不能有重复,且不保证顺序(有些实现有顺序,例如 LinkedHashSet
和 SortedSet
等)所以 Multiset
占据了 List
和 Set
之间的一个灰色地带:允许重复,但是不保证顺序。事实上,Multiset 并没有实现 java.util.Set
接口,它更像是一个 Bag。普通的 Set 就像这样:[car, ship, bike]
,而 Multiset 会是这样:[car x 2, ship x 6, bike x 3]
。
1、使用场景
常见使用场景:Multiset
有一个有用的功能,就是跟踪每种对象的数量,所以你可以用来进行数字统计。 常见的普通实现方式如下:
public void wordCounts(List words) { Map<String, Integer> counts = new HashMap<String, Integer>(); for (String word : words) { Integer count = counts.get(word); if (count == null) { counts.put(word, 1); } else { counts.put(word, count + 1); } } }
如果我们需要得到某个单词(比如good)的出现次数,我们可能这么写:
int goodCount = counts.get("good");
很麻烦对吗?而且Map中的 get(E key)
的含义都不那么明显。那如果我们用 Multisets
来看看:
import com.google.common.collect.HashMultiset; import com.google.common.collect.Multiset; Multiset countMultiset = HashMultiset.create(); countMultiset.addAll(words);
很简单吧?甚至连循环都不需要。那么我们怎么得到某个单词(比如good)的出现次数?很简单:
int goodCount= countMultiset.count("good");
在 Multiset
中提供了一个 count(Object element)
方法,得到某个对象在 Multiset
中出现的次数,这个显然比在 Map
里面调 get
的可读性好多了,不是吗?
注意: Multiset 提供 setCount(E, int)
方法,可以修改元素 E 在 Multiset 中的次数,但是不能把元素出现的次数修改为负数和大于 Integer.MAX_VALUE
的值。否则将会抛出异常。
2、Multiset 不是 Map
Multiset
也不是 Map<E, Integer>
类型的结构, 我们可以用 Map<E, Integer>
来实现 Multiset
,但是利用 Map<E,Integer>
实现 Multiset
和 Guava 的实现还是有很大的区别的,主要表现如下:
Multiset
中的元素出现的次数只能为正数,如果E的出现次数为0,那么E将不出现在multiset中,是不能在elementSet()和entrySet()的视图中;multiset.size()
返回这个集合的大小,相当于在 multiset 中元素的出现的总数。如果想得到 multiset 中不同元素出现的总数,可以利用elementSet().size()
来实现;multiset.iterator()
可以遍历 multiset 中的所有元素,所以 iteration 遍历的次数就等于multiset.size()
;Multiset
支持添加、删除元素,设置元素出现的次数setCount(elem, 0)
相当于移除elem的所有元素;multiset.count(elem)
方法中的 elem 如果没有出现在 Multiset 中,那么它的返回值永远都是0。
常用的实现了 Multiset 接口的类有:
HashMultiset
:元素存放于 HashMapLinkedHashMultiset
:元素存放于 LinkedHashMap,即元素的排列顺序由第一次放入的顺序决定TreeMultiset
:元素被排序存放于TreeMapEnumMultiset
:元素必须是 enum 类型ImmutableMultiset
:不可修改的 Mutiset
3、Multiset 的各种实现
Guava 提供了多种 Multiset 的实现,大致对应 JDK 中 Map 的各种实现:
Map | 对应的 Multiset | 是否支持null元素 |
---|---|---|
HashMap | HashMultiset | 是 |
TreeMap | TreeMultiset | 是(如果comparator支持的话) |
LinkedHashMap | LinkedHashMultiset | 是 |
ConcurrentHashMap | ConcurrentHashMultiset | 否 |
ImmutableMap | ImmutableMultiset | 否 |
四、示例
public static void main(String args[]){ // 创建 multiset 集合 Multiset<String> multiset = HashMultiset.create(); multiset.add("a"); multiset.add("b"); multiset.add("c"); multiset.add("d"); multiset.add("a"); multiset.add("b"); multiset.add("c"); multiset.add("b"); multiset.add("b"); multiset.add("b"); // 个数 System.out.println("Occurrence of 'b' : " + multiset.count("b")); System.out.println("Total Size : " + multiset.size()); // 遍历 Set<String> set = multiset.elementSet(); System.out.print("Set ["); for (String s : set) { System.out.print(s); } System.out.println("]"); // 使用迭代器 Iterator<String> iterator = multiset.iterator(); System.out.print("MultiSet ["); while (iterator.hasNext()) { System.out.print(iterator.next()); } System.out.println("]"); // 不同元素的个数 System.out.println("MultiSet ["); for (Multiset.Entry<String> entry : multiset.entrySet()) { System.out.println(" Element: " + entry.getElement() + ", Occurrence(s): " + entry.getCount()); } System.out.println("]"); // 删除元素 multiset.remove("b", 2); // 查找元素 System.out.println("Occurence of 'b' : " + multiset.count("b")); }
结果
Occurrence of 'b' : 5 Total Size : 10 Set [abcd] MultiSet [aabbbbbccd] MultiSet [ Element: a, Occurrence(s): 2 Element: b, Occurrence(s): 5 Element: c, Occurrence(s): 2 Element: d, Occurrence(s): 1 ] Occurence of 'b' : 3
五、相关文章
未经允许请勿转载:程序喵 » Google Guava 快速入门 —— 【新集合】Multiset 类