您的位置:首页 > 其它

Guava - Collections - New collection types

2013-10-11 11:56 357 查看
Guava提供了很多新的集合类型(这部分也是目前使用最广的)

1.Multiset

The traditional Java idiom for e.g. counting how many times a word occurs in a document is something like:

Map<String,Integer> counts =newHashMap<String,Integer>();
for(String word : words){
Integer count = counts.get(word);
if(count ==null){
counts.put(word,1);
}else{
counts.put(word, count +1);
}
}


在JDK中,List和Set有一个基本的区别,就是List可以包含多个相同对象,且是有顺序的,而Set不能有重复,且不保证顺序(有些实现有顺序,例如LinkedHashSet和SortedSet等)

所以Multiset占据了List和Set之间的一个灰色地带:允许重复,但是不保证顺序。

注意:这种集合在apache commons collections中也被称作“Bag”.

Implementations

Guava provides many implementations of Multiset, which roughly correspond to JDK map implementations.

MapCorresponding MultisetSupports null elements
HashMapHashMultisetYes
TreeMapTreeMultisetYes (if the comparator does)
LinkedHashMapLinkedHashMultisetYes
ConcurrentHashMapConcurrentHashMultisetNo
ImmutableMapImmutableMultisetNo

于是我们使用Multiset就能很好的简化上面的代码

package com.jake.guava.collections;

import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
import org.junit.Test;

import java.util.List;
import java.util.Map;

import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.newHashMap;

/**
* User: jake
* Date: 13-10-11
* Time: 上午11:27
*/
public class MultiSetTest {
@Test
public void countWorldByMultiSetTest() {
List<String> words = newArrayList("a", "b", "b", "b", "b", "b", "fdsf", "fdsf", "fdsf");
Map<String, Integer> counts = newHashMap();
Multiset wordSet = HashMultiset.create();
for (String word : words) {
wordSet.add(word);
}
System.out.println(wordSet.size());
System.out.println(wordSet.elementSet().size());
}

@Test
public void countWorldCommonTest() {
List<String> words = newArrayList("a", "b", "b", "b", "b", "b", "fdsf", "fdsf", "fdsf");
Map<String, Integer> counts = newHashMap();
for (String word : words) {
Integer count = counts.get(word);
if (count == null) {
counts.put(word, 1);
} else {
counts.put(word, count + 1);
}
}
}
}


总结:JDK中没出现的集合类型,实际中用到的地方还是很多的

实用性:高 

2.Multimap(ListMultimap or SetMultimap)

和MultiSet同样有个Multi ,官网上也说明 Guava's Multimapframework makes it easy to handle a mapping from keys to multiple values

说明了,Multimap是用来处理一个key对应多个值,也就是 Map<K, List<V>> or Map<K, Set<V>> 这两种情况。(不包含 Map<K,Map<K,V>这种情况)

一般我们处理Map<K, List<V>> or Map<K, Set<V>> 这种稍显复杂的结构,如下:

应用场景还是比较多的,例如:

学校每个班的学生总数,Map<class,List<Student>>

医院每个病房的病人信息,Map<room,List<Patient>>

我们拿医院来举例,例如现在303病房要添加一个病人,

代码会是如此

@Test
public void multiMapCommonTest(){
List<Patient> pList = newArrayList(new Patient(1,"lucy",303),new Patient(2,"lily",303));
Map<Integer,List<Patient>> patientList = newHashMap();
patientList.put(303, pList);

//此时要入住一个病人到303
Patient p = new Patient(3,"jake",303);
List<Patient> patients = patientList.get(303);
if (patients != null) {
patients.add(p);
} else {
patients = newArrayList();
patients.add(p);
}
}

@Test
public void multiMapGuavaTest() {
//这里要改变一个思路,以前用  Map<K,List<V>>  来存储
//现在用                      Multimap<K,V>   来存储
Multimap<Integer, Patient> patients = ArrayListMultimap.create();
patients.put(303,new Patient(1,"lucy",303));
patients.put(303,new Patient(1,"lily",303));
//此时要入住一个病人到303
Patient p = new Patient(3,"jake",303);
Patient pAnother = new Patient(4,"jone",304);
patients.put(303, p);
patients.put(304, pAnother);

for (Patient patient :patients.get(303) ) {
System.out.println(patient);
}
}


  

//Multimap 也可以通过asMap 转为 Map<K,Collection<V>>形式
Map<Integer,Collection<Patient>> patientmap = patients.asMap();


  

官方提供了很多View,以下这些那就都属于java基础数据的处理了,和Guava没什么关系

Views

Multimap also supports a number of powerful views.

asMap views any Multimap<K, V> as a Map<K, Collection<V>>. The returned map supports remove, and changes to the returned collections write through, but the map does not support put or putAll. Critically, you can use asMap().get(key) when you want null on absent keys rather than a fresh, writable empty collection. (You can and should cast asMap.get(key) to the appropriate collection type -- aSet for a SetMultimap, a List for a ListMultimap -- but the type system does not allow ListMultimap to return Map<K, List<V>> here.)

entries views the Collection<Map.Entry<K, V>> of all entries in the Multimap. (For a SetMultimap, this is a Set.)

keySet views the distinct keys in the Multimap as a Set.

keys views the keys of the Multimap as a Multiset, with multiplicity equal to the number of values associated to that key. Elements can be removed from the Multiset, but not added; changes will write through.

values() views the all the values in the Multimap as a "flattened" Collection<V>, all as one collection. This is similar toIterables.concat(multimap.asMap().values()), but returns a full Collection instead.

Implementations

Multimap provides a wide variety of implementations. You can use it in most places you would have used a Map<K, Collection<V>>.

Implementation   Keys behave like...    Values behave like..
ArrayListMultimap       HashMap              ArrayList
HashMultimap         HashMap              HashSet
LinkedListMultimap*     LinkedHashMap*           LinkedList*
LinkedHashMultimap**   LinkedHashMap           LinkedHashSet
TreeMultimap TreeMap    TreeSet
ImmutableListMultimap   ImmutableMap            ImmutableList
ImmutableSetMultimap   ImmutableMap            ImmutableSet

也就是说会有很多种形式,

Multimap<String, Object> multimap_1 = ArrayListMultimap.create();
Multimap<String, Object> multimap_2 = HashMultimap.create();
Multimap<String, Object> multimap_3 = LinkedListMultimap.create();


依然没有 Map<K,Map<K,V>>的形式!

Each of these implementations, except the immutable ones, support null keys and values.

总结:能够帮助自动分类,和之前的编程习惯有些不同,需要些时间来适应,推荐

实用性:高

3.BiMap

BiMap双向或者叫做反向映射,就是通过value找key,普通思路就是维护着两个同步的Map , keyMap 和valueMap,但是这样做容易出错!

Guava提供BiMap的inverse()方法来实现,

@Test
public void biMapTest(){
ImmutableMap<Integer,String> map = ImmutableMap.of(1,"303",2,"304");
BiMap<Integer, String> biMap = HashBiMap.create(map);
System.out.println(biMap.inverse().get("304"));
}


Implementations

Key-Value Map ImplValue-Key Map ImplCorresponding BiMap
HashMapHashMapHashBiMap
ImmutableMapImmutableMapImmutableBiMap
EnumMapEnumMapEnumBiMap
EnumMapHashMapEnumHashBiMap

总结:使用简单

实用性:中

4.Table

table是一种新的集合,提供了一种二重定位,可以认为是 行 加 列 定位一个值

Table接口提供了以下几种实现方式。使用上很简单

HashBasedTable, which is essentially backed by a HashMap<R, HashMap<C, V>>.

TreeBasedTable, which is essentially backed by a TreeMap<R, TreeMap<C, V>>.

ImmutableTable, which is essentially backed by an ImmutableMap<R, ImmutableMap<C, V>>. (Note: ImmutableTable has optimized implementations for sparser and denser data sets.)

ArrayTable, which requires that the complete universe of rows and columns be specified at construction time, but is backed by a two-dimensional array to improve speed and memory efficiency when the table is dense. ArrayTable works somewhat differently from other implementations; consult the Javadoc for details.

@Test
public void tableTest() {
Table<Integer,Integer,String> table = HashBasedTable.create();
table.put(1, 1, "first row first column");
table.put(1, 2, "first row second column");
table.put(2,1,"second row first column");
System.out.println(table.get(1,2));
Table<Book, Integer, String> test = HashBasedTable.create();
}


可以使用Integer定位,也可以使用Book等对象定位。

总结:简单易懂,

实用性:中

5.ClassToInstanceMap

普通Map是K ,V 键值对,ClassToInstanceMap是 class ,V的键值对形式(加泛型后就没意义了,只能存放一种对象,或者这种对象的子类对象)

示例代码:

@Test
public void classToInstanceMapTest(){

ClassToInstanceMap classToInstanceMapString =MutableClassToInstanceMap.create();
classToInstanceMapString.put(String.class, "");
classToInstanceMapString.put(Integer.class, 1);

Book book = new Book(1,"ST10001","三国志");
classToInstanceMapString.put(Book.class, book);

}


总结:简单易懂,

实用性:中偏低

剩下的RangeSet和RangeMap等Range那一章一起介绍

写的不好,欢迎指正,有时间会进一步完善
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: