天天看点

[Google Guava] 2.3-强大的集合工具类:java.util.Collections中未包含的集合工具

尚未完成: queues, tables工具类

我们用相对直观的方式把工具类与特定集合接口的对应关系归纳如下:

<b>集合接口</b><b></b>

<b>属于</b><b>jdk</b><b>还是</b><b>guava</b>

<b>对应的</b><b>guava</b><b>工具类</b><b></b>

collection

jdk

list

<a href="http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/lists.html">lists</a>

set

<a href="http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/sets.html">sets</a>

sortedset

map

<a href="http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/maps.html">maps</a>

sortedmap

queue

<a href="http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/queues.html">queues</a>

<a href="http://code.google.com/p/guava-libraries/wiki/newcollectiontypesexplained#multiset">multiset</a>

guava

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/multisets.html">multisets</a>

<a href="http://code.google.com/p/guava-libraries/wiki/newcollectiontypesexplained#multimap">multimap</a>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/multimaps.html">multimaps</a>

<a href="http://code.google.com/p/guava-libraries/wiki/newcollectiontypesexplained#bimap">bimap</a>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/maps.html">maps</a>

<a href="http://code.google.com/p/guava-libraries/wiki/newcollectiontypesexplained#table">table</a>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/tables.html">tables</a>

在找类似转化、过滤的方法?请看第四章,函数式风格。

在jdk 7之前,构造新的范型集合时要讨厌地重复声明范型:

<code>1</code>

<code>list&lt;typethatstoolongforitsowngood&gt; list = </code><code>new</code><code>arraylist&lt;typethatstoolongforitsowngood&gt;();</code>

我想我们都认为这很讨厌。因此guava提供了能够推断范型的静态工厂方法:

<code>list&lt;typethatstoolongforitsowngood&gt; list = lists.newarraylist();</code>

<code>2</code>

<code>map&lt;keytype, longishvaluetype&gt; map = maps.newlinkedhashmap();</code>

可以肯定的是,jdk7版本的钻石操作符(&lt;&gt;)没有这样的麻烦:

<code>list&lt;typethatstoolongforitsowngood&gt; list = </code><code>new</code> <code>arraylist&lt;&gt;();</code>

但guava的静态工厂方法远不止这么简单。用工厂方法模式,我们可以方便地在初始化时就指定起始元素。

<code>set&lt;type&gt; copyset = sets.newhashset(elements);</code>

<code>list&lt;string&gt; theseelements = lists.newarraylist(</code><code>"alpha"</code><code>, </code><code>"beta"</code><code>, </code><code>"gamma"</code><code>);</code>

此外,通过为工厂方法命名(effective java第一条),我们可以提高集合初始化大小的可读性:

<code>list&lt;type&gt; exactly100 = lists.newarraylistwithcapacity(</code><code>100</code><code>);</code>

<code>list&lt;type&gt; approx100 = lists.newarraylistwithexpectedsize(</code><code>100</code><code>);</code>

<code>3</code>

<code>set&lt;type&gt; approx100set = sets.newhashsetwithexpectedsize(</code><code>100</code><code>);</code>

确切的静态工厂方法和相应的工具类一起罗列在下面的章节。

注意:guava引入的新集合类型没有暴露原始构造器,也没有在工具类中提供初始化方法。而是直接在集合类中提供了静态工厂方法,例如:

<code>multiset&lt;string&gt; multiset = hashmultiset.create();</code>

在可能的情况下,guava提供的工具方法更偏向于接受iterable而不是collection类型。在google,对于不存放在主存的集合——比如从数据库或其他数据中心收集的结果集,因为实际上还没有攫取全部数据,这类结果集都不能支持类似size()的操作 ——通常都不会用collection类型来表示。

下面列出了一些最常用的工具方法,但更多iterables的函数式方法将在第四章讨论。

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/iterables.html#concat(java.lang.iterable)">concat(iterable&lt;iterable&gt;)</a>

串联多个iterables的懒视图*

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/iterables.html#concat(java.lang.iterable...)">concat(iterable...)</a>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/iterables.html#frequency(java.lang.iterable,%20java.lang.object)">frequency(iterable, object)</a>

返回对象在iterable中出现的次数

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/iterables.html#partition(java.lang.iterable,%20int)">partition(iterable, int)</a>

把iterable按指定大小分割,得到的子集都不能进行修改操作

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/iterables.html#getfirst(java.lang.iterable,%20t)">getfirst(iterable, t default)</a>

返回iterable的第一个元素,若iterable为空则返回默认值

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/iterables.html#getlast(java.lang.iterable)">getlast(iterable)</a>

返回iterable的最后一个元素,若iterable为空则抛出nosuchelementexception

<a href="http://docs.guava-libraries.googlecode.com/git-history/release12/javadoc/com/google/common/collect/fluentiterable.html#last()">fluentiterable.last()</a>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/iterables.html#elementsequal(java.lang.iterable,%20java.lang.iterable)">elementsequal(iterable, iterable)</a>

如果两个iterable中的所有元素相等且顺序一致,返回true

与list.equals(object)比较

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/iterables.html#unmodifiableiterable(java.lang.iterable)">unmodifiableiterable(iterable)</a>

返回iterable的不可变视图

与collections. unmodifiablecollection(collection)比较

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/iterables.html#limit(java.lang.iterable,%20int)">limit(iterable, int)</a>

限制iterable的元素个数限制给定值

<a href="http://docs.guava-libraries.googlecode.com/git-history/release12/javadoc/com/google/common/collect/fluentiterable.html#limit(int)">fluentiterable.limit(int)</a>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/iterables.html#getonlyelement(java.lang.iterable)">getonlyelement(iterable)</a>

获取iterable中唯一的元素,如果iterable为空或有多个元素,则快速失败

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/iterables.html#getonlyelement(java.lang.iterable,%20t)">getonlyelement(iterable, t default)</a>

*译者注:懒视图意味着如果还没访问到某个iterable中的元素,则不会对它进行串联操作。

<code>iterable&lt;integer&gt; concatenated = iterables.concat(</code>

<code>        </code><code>ints.aslist(</code><code>1</code><code>, </code><code>2</code><code>, </code><code>3</code><code>),</code>

<code>        </code><code>ints.aslist(</code><code>4</code><code>, </code><code>5</code><code>, </code><code>6</code><code>)); </code><code>// concatenated包括元素 1, 2, 3, 4, 5, 6</code>

<code>4</code>

<code>string lastadded = iterables.getlast(mylinkedhashset);</code>

<code>5</code>

<code>string theelement = iterables.getonlyelement(thissetisdefinitelyasingleton);</code>

<code>6</code>

<code>//如果set不是单元素集,就会出错了!</code>

通常来说,collection的实现天然支持操作其他collection,但却不能操作iterable。

下面的方法中,如果传入的iterable是一个collection实例,则实际操作将会委托给相应的collection接口方法。例如,往iterables.size方法传入是一个collection实例,它不会真的遍历iterator获取大小,而是直接调用collection.size。

<b>方法</b><b></b>

<b>类似的</b><b>collection</b><b>方法</b><b></b>

<b>等价的</b><b>fluentiterable</b><b>方法</b><b></b>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/iterables.html#addall(java.util.collection,%20java.lang.iterable)">addall(collection addto,   iterable toadd)</a>

collection.addall(collection)

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/iterables.html#contains(java.lang.iterable,%20java.lang.object)">contains(iterable, object)</a>

collection.contains(object)

<a href="http://docs.guava-libraries.googlecode.com/git-history/release12/javadoc/com/google/common/collect/fluentiterable.html#contains(java.lang.object)">fluentiterable.contains(object)</a>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/iterables.html#removeall(java.lang.iterable,%20java.util.collection)">removeall(iterable   removefrom, collection toremove)</a>

collection.removeall(collection)

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/iterables.html#retainall(java.lang.iterable,%20java.util.collection)">retainall(iterable   removefrom, collection toretain)</a>

collection.retainall(collection)

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/iterables.html#size(java.lang.iterable)">size(iterable)</a>

collection.size()

<a href="http://docs.guava-libraries.googlecode.com/git-history/release12/javadoc/com/google/common/collect/fluentiterable.html#size()">fluentiterable.size()</a>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/iterables.html#toarray(java.lang.iterable,%20java.lang.class)">toarray(iterable, class)</a>

collection.toarray(t[])

<a href="http://docs.guava-libraries.googlecode.com/git-history/release12/javadoc/com/google/common/collect/fluentiterable.html#toarray(java.lang.class)">fluentiterable.toarray(class)</a>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/iterables.html#isempty(java.lang.iterable)">isempty(iterable)</a>

collection.isempty()

<a href="http://docs.guava-libraries.googlecode.com/git-history/release12/javadoc/com/google/common/collect/fluentiterable.html#isempty()">fluentiterable.isempty()</a>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/iterables.html#get(java.lang.iterable,%20int)">get(iterable, int)</a>

list.get(int)

<a href="http://docs.guava-libraries.googlecode.com/git-%20history/release12/javadoc/com/google/common/collect/fluentiterable.html#get(int)">fluentiterable.get(int)</a>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/iterables.html#tostring(java.lang.iterable)">tostring(iterable)</a>

collection.tostring()

<a href="http://docs.guava-libraries.googlecode.com/git-history/release12/javadoc/com/google/common/collect/fluentiterable.html#tostring()">fluentiterable.tostring()</a>

除了上面和第四章提到的方法,fluentiterable还有一些便利方法用来把自己拷贝到不可变集合

immutablelist

immutableset

<a href="http://docs.guava-libraries.googlecode.com/git-history/release12/javadoc/com/google/common/collect/fluentiterable.html#toimmutableset()">toimmutableset()</a>

immutablesortedset

<a href="http://docs.guava-libraries.googlecode.com/git-history/release12/javadoc/com/google/common/collect/fluentiterable.html#toimmutablesortedset(java.util.comparator)">toimmutablesortedset(comparator)</a>

<b>描述</b><b></b>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/lists.html#partition(java.util.list,%20int)">partition(list, int)</a>

把list按指定大小分割

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/lists.html#reverse(java.util.list)">reverse(list)</a>

<code>list countup = ints.aslist(</code><code>1</code><code>, </code><code>2</code><code>, </code><code>3</code><code>, </code><code>4</code><code>, </code><code>5</code><code>);</code>

<code>list countdown = lists.reverse(thelist); </code><code>// {5, 4, 3, 2, 1}</code>

<code>list&lt;list&gt; parts = lists.partition(countup, </code><code>2</code><code>);</code><code>//{{1,2}, {3,4}, {5}}</code>

lists提供如下静态工厂方法:

<b>具体实现类型</b><b></b>

<b>工厂方法</b><b></b>

arraylist

linkedlist

直接当作set使用,因为setview也实现了set接口;

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/sets.html#union(java.util.set,%20java.util.set)">union(set, set)</a>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/sets.html#intersection(java.util.set,%20java.util.set)">intersection(set, set)</a>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/sets.html#difference(java.util.set,%20java.util.set)">difference(set, set)</a>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/sets.html#symmetricdifference(java.util.set,%20java.util.set)">symmetricdifference(set,   set)</a>

使用范例:

<code>set&lt;string&gt; wordswithprimelength = immutableset.of(</code><code>"one"</code><code>, </code><code>"two"</code><code>, </code><code>"three"</code><code>, </code><code>"six"</code><code>, </code><code>"seven"</code><code>, </code><code>"eight"</code><code>);</code>

<code>set&lt;string&gt; primes = immutableset.of(</code><code>"two"</code><code>, </code><code>"three"</code><code>, </code><code>"five"</code><code>, </code><code>"seven"</code><code>);</code>

<code>setview&lt;string&gt; intersection = sets.intersection(primes,wordswithprimelength);</code>

<code>// intersection包含"two", "three", "seven"</code>

<code>return</code> <code>intersection.immutablecopy();</code><code>//可以使用交集,但不可变拷贝的读取效率更高</code>

<b>另请参见</b><b></b>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/sets.html#cartesianproduct(java.util.list)">cartesianproduct(list&lt;set&gt;)</a>

返回所有集合的笛卡儿积

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/sets.html#cartesianproduct(java.util.set...)">cartesianproduct(set...)</a>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/sets.html#powerset(java.util.set)">powerset(set)</a>

返回给定集合的所有子集

<code>set&lt;string&gt; animals = immutableset.of(</code><code>"gerbil"</code><code>, </code><code>"hamster"</code><code>);</code>

<code>set&lt;string&gt; fruits = immutableset.of(</code><code>"apple"</code><code>, </code><code>"orange"</code><code>, </code><code>"banana"</code><code>);</code>

<code>set&lt;list&lt;string&gt;&gt; product = sets.cartesianproduct(animals, fruits);</code>

<code>// {{"gerbil", "apple"}, {"gerbil", "orange"}, {"gerbil", "banana"},</code>

<code>//  {"hamster", "apple"}, {"hamster", "orange"}, {"hamster", "banana"}}</code>

<code>7</code>

<code>8</code>

<code>set&lt;set&lt;string&gt;&gt; animalsets = sets.powerset(animals);</code>

<code>9</code>

<code>// {{}, {"gerbil"}, {"hamster"}, {"gerbil", "hamster"}}</code>

sets提供如下静态工厂方法:

hashset

linkedhashset

treeset

比方说,我们有一堆字符串,这些字符串的长度都是独一无二的,而我们希望能够按照特定长度查找字符串:

<code>immutablemap&lt;integer, string&gt; stringsbyindex = maps.uniqueindex(strings,</code>

<code>    </code><code>new</code> <code>function&lt;string, integer&gt; () {</code>

<code>        </code><code>public</code> <code>integer apply(string string) {</code>

<code>            </code><code>return</code> <code>string.length();</code>

<code>        </code><code>}</code>

<code>    </code><code>});</code>

如果索引值不是独一无二的,请参见下面的multimaps.index方法。

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/mapdifference.html#entriesincommon()">entriesincommon()</a>

两个map中都有的映射项,包括匹配的键与值

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/mapdifference.html#entriesdiffering()">entriesdiffering()</a>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/mapdifference.html#entriesonlyonleft()">entriesonlyonleft()</a>

键只存在于左边map的映射项

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/mapdifference.html#entriesonlyonright()">entriesonlyonright()</a>

键只存在于右边map的映射项

<code>map&lt;string, integer&gt; left = immutablemap.of(</code><code>"a"</code><code>, </code><code>1</code><code>, </code><code>"b"</code><code>, </code><code>2</code><code>, </code><code>"c"</code><code>, </code><code>3</code><code>);</code>

<code>mapdifference&lt;string, integer&gt; diff = maps.difference(left, right);</code>

<code>diff.entriesincommon(); </code><code>// {"b" =&gt; 2}</code>

<code>diff.entriesonlyonleft(); </code><code>// {"a" =&gt; 1}</code>

<code>diff.entriesonlyonright(); </code><code>// {"d" =&gt; 5}</code>

guava中处理bimap的工具方法在maps类中,因为bimap也是一种map实现。

<b>bimap</b><b>工具方法</b><b></b>

<b>相应的</b><b>map</b><b>工具方法</b><b></b>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/maps.html#synchronizedbimap(com.google.common.collect.bimap)">synchronizedbimap(bimap)</a>

collections.synchronizedmap(map)

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/maps.html#unmodifiablebimap(com.google.common.collect.bimap)">unmodifiablebimap(bimap)</a>

collections.unmodifiablemap(map)

maps提供如下静态工厂方法:

hashmap

linkedhashmap

treemap

enummap

concurrentmap:支持所有操作

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/maps.html#newconcurrentmap()">basic</a>

identityhashmap

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/maps.html#newidentityhashmap()">basic</a>

<b>说明</b><b></b>

<b>和</b><b>collection</b><b>方法的区别</b><b></b>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/multisets.html#containsoccurrences(com.google.common.collect.multiset,%20com.google.common.collect.multiset)">containsoccurrences(multiset   sup, multiset sub)</a>

对任意o,如果sub.count(o)&lt;=super.count(o),返回true

collection.containsall忽略个数,而只关心sub的元素是否都在super中

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/multisets.html#removeoccurrences(com.google.common.collect.multiset,%20com.google.common.collect.multiset)">removeoccurrences(multiset   removefrom, multiset toremove)</a>

对toremove中的重复元素,仅在removefrom中删除相同个数。

collection.removeall移除所有出现在toremove的元素

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/multisets.html#retainoccurrences(com.google.common.collect.multiset,%20com.google.common.collect.multiset)">retainoccurrences(multiset   removefrom, multiset toretain)</a>

修改removefrom,以保证任意o都符合removefrom.count(o)&lt;=toretain.count(o)

collection.retainall保留所有出现在toretain的元素

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/multisets.html#intersection(com.google.common.collect.multiset,%20com.google.common.collect.multiset)">intersection(multiset,   multiset)</a>

返回两个multiset的交集;

没有类似方法

<code>01</code>

<code>multiset&lt;string&gt; multiset1 = hashmultiset.create();</code>

<code>02</code>

<code>multiset1.add(</code><code>"a"</code><code>, </code><code>2</code><code>);</code>

<code>03</code>

<code>04</code>

<code>multiset&lt;string&gt; multiset2 = hashmultiset.create();</code>

<code>05</code>

<code>multiset2.add(</code><code>"a"</code><code>, </code><code>5</code><code>);</code>

<code>06</code>

<code>07</code>

<code>multiset1.containsall(multiset2); </code><code>//返回true;因为包含了所有不重复元素,</code>

<code>08</code>

<code>//虽然multiset1实际上包含2个"a",而multiset2包含5个"a"</code>

<code>09</code>

<code>multisets.containsoccurrences(multiset1, multiset2); </code><code>// returns false</code>

<code>10</code>

<code>11</code>

<code>multiset2.removeoccurrences(multiset1); </code><code>// multiset2 现在包含3个"a"</code>

<code>12</code>

<code>multiset2.removeall(multiset1);</code><code>//multiset2移除所有"a",虽然multiset1只有2个"a"</code>

<code>13</code>

<code>multiset2.isempty(); </code><code>// returns true</code>

multisets中的其他工具方法还包括:

<a href="http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/multisets.html#copyhighestcountfirst(com.google.common.collect.multiset)">copyhighestcountfirst(multiset)</a>

返回multiset的不可变拷贝,并将元素按重复出现的次数做降序排列

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/multisets.html#unmodifiablemultiset(com.google.common.collect.multiset)">unmodifiablemultiset(multiset)</a>

返回multiset的只读视图

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/multisets.html#unmodifiablesortedmultiset(com.google.common.collect.sortedmultiset)">unmodifiablesortedmultiset(sortedmultiset)</a>

返回sortedmultiset的只读视图

<code>multiset.add(</code><code>"a"</code><code>, </code><code>3</code><code>);</code>

<code>multiset.add(</code><code>"b"</code><code>, </code><code>5</code><code>);</code>

<code>multiset.add(</code><code>"c"</code><code>, </code><code>1</code><code>);</code>

<code>immutablemultiset highestcountfirst = multisets.copyhighestcountfirst(multiset);</code>

<code>//highestcountfirst,包括它的entryset和elementset,按{"b", "a", "c"}排列元素</code>

比方说,我们想把字符串按长度分组。

<code>immutableset digits = immutableset.of(</code><code>"zero"</code><code>, </code><code>"one"</code><code>, </code><code>"two"</code><code>, </code><code>"three"</code><code>, </code><code>"four"</code><code>, </code><code>"five"</code><code>, </code><code>"six"</code><code>, </code><code>"seven"</code><code>, </code><code>"eight"</code><code>, </code><code>"nine"</code><code>);</code>

<code>function&lt;string, integer&gt; lengthfunction = </code><code>new</code> <code>function&lt;string, integer&gt;() {</code>

<code>    </code><code>public</code> <code>integer apply(string string) {</code>

<code>        </code><code>return</code> <code>string.length();</code>

<code>    </code><code>}</code>

<code>};</code>

<code>immutablelistmultimap&lt;integer, string&gt; digitsbylength= multimaps.index(digits, lengthfunction);</code>

<code>/*</code>

<code>*  digitsbylength maps:</code>

<code>*  3 =&gt; {"one", "two", "six"}</code>

<code>*  4 =&gt; {"zero", "four", "five", "nine"}</code>

<code>*  5 =&gt; {"three", "seven", "eight"}</code>

<code>14</code>

<code>*/</code>

<code>arraylistmultimap&lt;string, integer&gt; multimap = arraylistmultimap.create();</code>

<code>multimap.putall(</code><code>"b"</code><code>, ints.aslist(</code><code>2</code><code>, </code><code>4</code><code>, </code><code>6</code><code>));</code>

<code>multimap.putall(</code><code>"a"</code><code>, ints.aslist(</code><code>4</code><code>, </code><code>2</code><code>, </code><code>1</code><code>));</code>

<code>multimap.putall(</code><code>"c"</code><code>, ints.aslist(</code><code>2</code><code>, </code><code>5</code><code>, </code><code>3</code><code>));</code>

<code>treemultimap&lt;integer, string&gt; inverse = multimaps.invertfrom(multimap, treemultimap&lt;string, integer&gt;.create());</code>

<code>//注意我们选择的实现,因为选了treemultimap,得到的反转结果是有序的</code>

<code>* inverse maps:</code>

<code>*  1 =&gt; {"a"}</code>

<code>*  2 =&gt; {"a", "b", "c"}</code>

<code>*  3 =&gt; {"c"}</code>

<code>*  4 =&gt; {"a", "b"}</code>

<code>*  5 =&gt; {"c"}</code>

<code>15</code>

<code>*  6 =&gt; {"b"}</code>

<code>16</code>

<code>map&lt;string, integer&gt; map = immutablemap.of(</code><code>"a"</code><code>, </code><code>1</code><code>, </code><code>"b"</code><code>, </code><code>1</code><code>, </code><code>"c"</code><code>, </code><code>2</code><code>);</code>

<code>setmultimap&lt;string, integer&gt; multimap = multimaps.formap(map);</code>

<code>// multimap:["a" =&gt; {1}, "b" =&gt; {1}, "c" =&gt; {2}]</code>

<code>multimap&lt;integer, string&gt; inverse = multimaps.invertfrom(multimap, hashmultimap&lt;integer, string&gt;.create());</code>

<code>// inverse:[1 =&gt; {"a","b"}, 2 =&gt; {"c"}]</code>

multimaps提供了传统的包装方法,以及让你选择map和collection类型以自定义multimap实现的工具方法。

只读包装

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/multimaps.html#unmodifiablemultimap(com.google.common.collect.multimap)">multimap</a>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/multimaps.html#unmodifiablelistmultimap(com.google.common.collect.listmultimap)">listmultimap</a>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/multimaps.html#unmodifiablesetmultimap(com.google.common.collect.setmultimap)">setmultimap</a>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/multimaps.html#unmodifiablesortedsetmultimap(com.google.common.collect.sortedsetmultimap)">sortedsetmultimap</a>

同步包装

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/multimaps.html#synchronizedmultimap(com.google.common.collect.multimap)">multimap</a>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/multimaps.html#synchronizedlistmultimap(com.google.common.collect.listmultimap)">listmultimap</a>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/multimaps.html#synchronizedsetmultimap(com.google.common.collect.setmultimap)">setmultimap</a>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/multimaps.html#synchronizedsortedsetmultimap(com.google.common.collect.sortedsetmultimap)">sortedsetmultimap</a>

自定义实现

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/multimaps.html#newmultimap(java.util.map,%20com.google.common.base.supplier)">multimap</a>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/multimaps.html#newlistmultimap(java.util.map,%20com.google.common.base.supplier)">listmultimap</a>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/multimaps.html#newsetmultimap(java.util.map,%20com.google.common.base.supplier)">setmultimap</a>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/multimaps.html#newsortedsetmultimap(java.util.map,%20com.google.common.base.supplier)">sortedsetmultimap</a>

自定义multimap的方法允许你指定multimap中的特定实现。但要注意的是:

multimap假设对map和supplier产生的集合对象有完全所有权。这些自定义对象应避免手动更新,并且在提供给multimap时应该是空的,此外还不应该使用软引用、弱引用或虚引用。

无法保证修改了multimap以后,底层map的内容是什么样的。

即使map和supplier产生的集合都是线程安全的,它们组成的multimap也不能保证并发操作的线程安全性。并发读操作是工作正常的,但需要保证并发读写的话,请考虑用同步包装器解决。

只有当map、supplier、supplier产生的集合对象、以及multimap存放的键值类型都是可序列化的,multimap才是可序列化的。

multimap.get(key)返回的集合对象和supplier返回的集合对象并不是同一类型。但如果supplier返回的是随机访问集合,那么multimap.get(key)返回的集合也是可随机访问的。

请注意,用来自定义multimap的方法需要一个supplier参数,以创建崭新的集合。下面有个实现listmultimap的例子——用treemap做映射,而每个键对应的多个值用linkedlist存储。

<code>listmultimap&lt;string, integer&gt; mymultimap = multimaps.newlistmultimap(</code>

<code>    </code><code>maps.&lt;string, collection&gt;newtreemap(),</code>

<code>    </code><code>new</code> <code>supplier&lt;linkedlist&gt;() {</code>

<code>        </code><code>public</code> <code>linkedlist get() {</code>

<code>            </code><code>return</code> <code>lists.newlinkedlist();</code>

<code>// 使用linkedhashmaps替代hashmaps</code>

<code>table&lt;string, character, integer&gt; table = tables.newcustomtable(</code>

<code>maps.&lt;string, map&lt;character, integer&gt;&gt;newlinkedhashmap(),</code>

<code>new</code> <code>supplier&lt;map&lt;character, integer&gt;&gt; () {</code>

<code>public</code> <code>map&lt;character, integer&gt; get() {</code>

<code>return</code> <code>maps.newlinkedhashmap();</code>

<code>}</code>

<code>});</code>

unmodifiable

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/tables.html#unmodifiabletable(com.google.common.collect.table)">table</a>

<a href="http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/tables.html#unmodifiablerowsortedtable(com.google.common.collect.rowsortedtable)">rowsortedtable</a>