Guava introduces a number of new collection types that are not in the JDK, but that we have found to be broadly useful. These are all designed to coexist happily with the JDK collections framework, without shoehorning things into the JDK collection abstractions.
All
Multiset
SortedMultiset
Multimap
ListMultimap
SetMultimap
BiMap
ClassToInstanceMap
Table
Multiset
troditional
Map counts = new HashMap();
for (String word : words) {
Integer count = counts.get(word);
if (count == null) {
counts.put(word, 1);
} else {
counts.put(word, count + 1);
}
}
guava
// List 允许重复,有顺序
// Set 不允许重复、无顺序
// MultiSet 允许重复,不保证顺序
String strWorld="wer|dfd|dd|dfd|dda|de|dr";
String[] words = strWorld.split("\\|");
Multiset multiset = HashMultiset.create();
for (String word : words) {
multiset.add(word);
}
for(String key:multiset.elementSet()){
System.out.println(key+" count:"+multiset.count(key));
}
notice
Guava provides a new collection type, Multiset
, which supports adding multiples of elements. Wikipedia defines a multiset, in mathematics, as “a generalization of the notion of set in which members are allowed to appear more than once...In multisets, as in sets and in contrast to tuples, the order of elements is irrelevant: The multisets {a, a, b} and {a, b, a} are equal.”
There are two main ways of looking at this:
- This is like an
ArrayList
without an ordering constraint: ordering does not matter. - This is like a
Map
, with elements and counts.
methods
Multiset接口定义的接口主要有:
add(E element) :向其中添加单个元素
add(E element,int occurrences) : 向其中添加指定个数的元素
count(Object element) : 返回给定参数元素的个数
remove(E element) : 移除一个元素,其count值 会响应减少
remove(E element,int occurrences): 移除相应个数的元素
elementSet() : 将不同的元素放入一个Set中
entrySet(): 类似与Map.entrySet 返回Set
setCount(E element ,int count): 设定某一个元素的重复次数
setCount(E element,int oldCount,int newCount): 将符合原有重复个数的元素修改为新的重复次数
retainAll(Collection c) : 保留出现在给定集合参数的所有的元素
removeAll(Collectionc) : 去除出现给给定集合参数的所有的元素
Implementations
Multimap
implemented a Map
You rarely use the Multimap interface directly, however; more often you'll use ListMultimap or SetMultimap, which map keys to a List or a Set respectively.
Construction
// 可创建1 key : n value 的map结构
// 可创建1 key : n value 的map结构
Multimap multimap = ArrayListMultimap.create();
for (int i = 0; i < 2; i++) {
multimap.put("aa", i);
multimap.put("bb", i);
}
// 所有value的数量
System.out.println("multimap.size() = " + multimap.size());
System.out.println("multimap.keys() = " + multimap.keys());
// key不存在 会得到空集合,而不是null
List valueList = (List) multimap.get("key");
System.out.println("valueList = " + valueList);
valueList = (List) multimap.get("aa");
System.out.println("valueList = " + valueList);
// 转为map
Map> map = multimap.asMap();
List list2 = (List)map.get("key");
// key 不存在,得到null
System.out.println("list2 = " + list2);
valueList = (List) map.get("aa");
System.out.println("valueList = " + valueList);
Collection> entries = multimap.entries();
System.out.println("entries = " + entries);
View
Multimap也支持一系列强大的视图功能:
1.asMap把自身Multimap
2.entries视图是把Multimap里所有的键值对以Collection
3.keySet视图是把Multimap的键集合作为视图
4.keys视图返回的是个Multiset,这个Multiset是以不重复的键对应的个数作为视图。这个Multiset可以通过支持移除操作而不是添加操作来修改Multimap。
5.values()视图能把Multimap里的所有值“平展”成一个Collection
尽管Multimap的实现用到了Map,但Multimap
1.Multimap.get(key)一定返回一个非null的集合。但这不表示Multimap使用了内存来关联这些键,相反,返回的集合只是个允许添加元素的视图。
2.如果你喜欢像Map那样当不存在键的时候要返回null,而不是Multimap那样返回空集合的话,可以用asMap()返回的视图来得到Map
3.Multimap.containsKey(key)只有在这个键存在的时候才返回true。
4.Multimap.entries()返回的是Multimap所有的键值对。但是如果需要key-collection的键值对,那就得用asMap().entries()。
5.Multimap.size()返回的是entries的数量,而不是不重复键的数量。如果要得到不重复键的数目就得用Multimap.keySet().size()。
Implements
Implementation | Keys 的行为类似 | Values的行为类似 |
---|---|---|
ArrayListMultimap | HashMap | ArrayList |
HashMultimap | HashMap | HashSet |
LinkedListMultimap | LinkedHashMap* | LinkedList* |
LinkedHashMultimap | LinkedHashMap | LinkedHashSet |
TreeMultimap | TreeMap | TreeSet |
ImmutableListMultimap | ImmutableMap | ImmutableList |
ImmutableSetMultimap | ImmutableMap | ImmutableSet |
Multimap提供了丰富的实现,所以你可以用它来替代程序里的Map
Implementation | Keys 的行为类似 | Values的行为类似 |
---|---|---|
ArrayListMultimap | HashMap | ArrayList |
HashMultimap | HashMap | HashSet |
LinkedListMultimap | LinkedHashMap* | LinkedList* |
LinkedHashMultimap | LinkedHashMap | LinkedHashSet |
TreeMultimap | TreeMap | TreeSet |
ImmutableListMultimap | ImmutableMap | ImmutableList |
ImmutableSetMultimap | ImmutableMap | ImmutableSet |
以上这些实现,除了immutable的实现都支持null的键和值。
- LinkedListMultimap.entries()能维持迭代时的顺序。
- LinkedHashMultimap维持插入的顺序,以及键的插入顺序。
要注意并不是所有的实现都正真实现了Map>!(尤其是有些Multimap的实现为了最小话开销,使用了自定义的hash table)
BiMap
troditional
Map nameToId = Maps.newHashMap();
Map idToName = Maps.newHashMap();
nameToId.put("Bob", 42);
idToName.put(42, "Bob");
// what happens if "Bob" or 42 are already present?
// weird bugs can arise if we forget to keep these in sync...
A BiMap
is a Map
that
- allows you to view the "inverse"
BiMap
withinverse()
- ensures that values are unique, making
values()
aSet
HashBiMap hashBiMap = HashBiMap.create();
hashBiMap.put("a1", 1);
hashBiMap.put("a2", 2);
hashBiMap.put("a3", 3);
System.out.println("hashBiMap = " + hashBiMap);
BiMap inverse = hashBiMap.inverse();
System.out.println("inverse = " + inverse);
// BiMap 强制保持 1:1 关系,如果要在已有value上添加另外的key,则会抛出异常
// 要覆盖已有value对应的entry,则可以putforce
hashBiMap.forcePut("a4", 3);
System.out.println("hashBiMap = " + hashBiMap);
BiMap.put(key, value)
will throw anIllegalArgumentException
if you attempt to map a key to an already-present value. If you wish to delete any preexisting entry with the specified value, useBiMap.forcePut(key, value)
instead.- inverse方法会返回一个反转的BiMap,但是注意这个反转的map不是新的map对象,它实现了一种视图关联,这样你对于反转后的map的所有操作都会影响原先的map对象。
Note:
BiMap
utilities likesynchronizedBiMap
live inMaps
.
Table
Table table = HashBasedTable.create();
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
table.put(i, j, i + "-" + j);
}
}
System.out.println("table = " + table);
Map row0 = table.row(0);
System.out.println("row 0 = " + row0);
Map colum0 = table.column(0);
System.out.println("table.column(0) = " + colum0);
Map> rowMap = table.rowMap();
System.out.println("rowMap.get(0).get(0) = " + rowMap.get(0).get(0));
Map> columnMap = table.columnMap();
System.out.println("columnMap.get(0).get(0) = " + columnMap.get(0).get(0));
Implements
Table有以下实现:
HashBasedTable:基于HashMap
TreeBasedTable:基于TreeMap
ImmutableTable:基于ImmutableMap
ArrayTable:ArrayTable是一个需要在构建的时候就需要定下行列的表格。这种表格由二维数组实现,这样可以在密集数据的表格的场合,提高时间和空间的效率。
ClassToInstanceMap
RangeSet
A RangeSet describes a set of disconnected, nonempty ranges. When adding a range to a mutable RangeSet, any connected ranges are merged together, and empty ranges are ignored. For example:
// range.closed [],即闭区间 ,range.closeOpen [),即右开区间
RangeSet rangeSet = TreeRangeSet.create();
rangeSet.add(Range.closed(5,10));
System.out.println("rangeSet:"+rangeSet);
rangeSet.add(Range.closedOpen(12, 15));
System.out.println("rangeSet:"+rangeSet);
// 会合并
rangeSet.add(Range.closedOpen(11, 13));
System.out.println("rangeSet:"+rangeSet);
// 会分割
rangeSet.remove(Range.open(7,8));
System.out.println("rangeSet:"+rangeSet);
RangeMap
RangeMap is a collection type describing a mapping from disjoint, nonempty ranges to values. Unlike RangeSet, RangeMap never "coalesces" adjacent mappings, even if adjacent ranges are mapped to the same values. For example:
// 不会像rangeSet自动合并区间
RangeMap rangeMap = TreeRangeMap.create();
rangeMap.put(Range.closed(1, 5), "1-5");
System.out.println(rangeMap.get(2));
rangeMap.remove(Range.open(2,3));
System.out.println(rangeMap);