在一开始接触guava的时候我是抵触的。当时这样觉得:相比C++,Java的运行速度有点慢,那么Guava是基于Java封装的运行速度肯定比Java慢,所以不应该使用Java。现在回头来看当时的想法真的有点可笑,真是应了一句话:凡是你排斥的就是你要学习的。下面写几个Guava的优点:

  • 优化良好,运行速度快,不要觉得封装的就会速度慢,很多人一看到封装两字就会觉得慢,真是肤浅。guava的封装一条语句完成一系列复杂操作。以这一系列操作来看使用,在最优的实现上来看是一样的。Guava基本上已经优化到了最优,而你自己编写一系列代码,不一定最优,所以guava得速度更快
  • 提高代码的可读性,代码简介易读。这个在后续的文章之中读者会看到。
  • 稳定性高,没有bug。
  • 支持函数式编程,Java在Java8中才有

MultiMap:在Map的Value中存放多个元素

MultiMap是一个一个Key对应多个Value的数据结构,他的外部结构类似于java.util.Map,但是实质上他们并没有联系。先看一个例子:

1
2
Map<String, HashSet<String>> hMap = new HashMap<String, HashSet<String>>();

从我开始写Java的时候已经不知道遇到这种恶心的结构多少次了。采用Java原生方法的写法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
如下的代码是将person的list转换成以name为key,person列表为value的Map
Map<String, HashSet<String>> hMap = new HashMap<String, HashSet<String>>();
for(Person p: personList){
HashSet<Person> set = hMap.get(p.getName());
if(set == null){
set = new HashSet<Person>();
hMap.put(p.getName(), set);
}
set.add(p);
}

相信只要写Java程序的人都会遇到上面的数据结构,每次看到上面这一坨代码,就难受。换成Guava的MultiMap写法如下:

1
2
3
4
5
6
7
8
Multimap<String, String> map = HashMultimap.create();
for(Person p: personList){
map.put(p.getName(), p);
}

简单明了,看起来清爽多了。
MultiMap的主要实现类有如下几个,可以对比Map类来理解。

实现类 详细解释
HashMultimap key是HashMap的key,value是一个HashSet的集合
ArrayListMultimap key是HashMap的key,value是一个ArrayList的集合
LinkedHashMultimap key是LinkedHashMap的key,value是一个LinkedHashSet的集合
TreeMultimap key是TreeMap的key,value是一个TreeSet的集合
ImmutableMultimap 不可修改的MultiMap,其他的结构类似HashMultiMap

BiMap: 双向Map

BiMap实现了java.util.Map。它的特点是它的value和key都是不可以重复的,换句话说,它的key和value是等价的,如果你向BiMap中存放了重复的元素,它会抛出IllegalArgumentException。
示例:众所周知Map数据结构支持用key来查找value,而且非常方便,但是在很多的应用当中,我们需要根据value来查找key那么使用Map结构就会很麻烦。我们通常会按照如下的代码来操作:

1
2
3
4
5
6
7
8
9
10
11
for(Map.Entry<User,Address> entry:map.entrySet()){
if(entry.getValue.equals(targetAddress)){
return entry.getKey();
}
}
return null;

如果我们将User和Address放在Guava的BiMap数据结构中,查找过程就可以简化为如下的代码:

1
2
3
4
BiMap<User,Address> biMap = new HashBiMap<User,Address>();
return biMap.inverse().get(targetAddress);

BiMap的常用实现如下:

实现类 详细解释
HashBiMap key和value集合都有hashmap的实现
EnumBiMap key和value都必须是 enum类型
ImmutableiMap 不可修改的BiMap

MapMaker: ConcurrentMap的构造工具

MapMaker可以用来构建ConcurrentMap,选项多,操作灵活。
例如:
1 构造一个有8把锁的ConcurrentMap

1
ConcurrentMap<String,Object> map = new MapMaker().concurrencyLevel(8).makeMap();

2 构造一个自动过期移除的ConcurrentMap

1
2
ConcurrentMap<String,Object> map = new MapMaker().expireAfterWrite(30,TimeUnit.SECONDS).makeMap();

3 构造一个有最大数目限制的ConcurrentMap

1
2
ConcurrentMap<String,Object> map = new MapMaker().maximumSize(100).makeMap();

4 构造一个上面几个选项联合的map
……………….

MapDifference: Map的交集并集差集操作

MapDifference主要是用来进行两个Map的比较操作,例如交集,并集,差集……..
1 求出两个Map完全相同的entry

1
2
3
MapDifference<String,Object> mapDifference = Maps.difference(mapA,mapB);
Map<String,Object> commonMap = mapDifference.entriesInCommon();

2 求出两个Map中的key相同,但是value不相同的entry

1
2
3
4
MapDifference<String,Object> mapDifference = Maps.difference(mapA,mapB);
Map<String,Object> entriesDiffering = mapDifference.entriesDiffering();

3 求出两个map,左边有,右边没有的entry

1
2
3
4
MapDifference<String,Object> mapDifference = Maps.difference(mapA,mapB);
Map<String,Object> entriesOnlyOnLeft = mapDifference.entriesEntriesOnlyOnLeft();

4 求出两个Map,右边有,左边没有的entry

1
2
3
4
MapDifference<String,Object> mapDifference = Maps.difference(mapA,mapB);
Map<String,Object> entriesOnlyOnRight = mapDifference.entriesEntriesOnlyOnRight();

Maps:map工具类集合

1 将一个List转换成Map

1
2
3
4
5
6
7
8
9
10
11
12
13
14
List<Person> personList = new ArrayList<Person>();
....
Map<String,Person> personMaps = Maps.uniqueIndex(personList,new Function<Person,String>(){
public String apply(Person person){
retuan person.getName();
}
})

2 将properties转换成Map

1
2
3
4
5
6
Properties properties = new Properties();
........
Map<String,String> map = Maps.fromProperties(properties);

3 对Map按照entry进行过滤,过滤出用户地址为“中关村”的map集合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Map<String,Person> map = new HashMap<String,Person>();
Predicate<Entry<String,Person>> perdicate = new Predicate<Map.Entry<String,Person>> (){
public boolean apply(Entry<String,Person> input){
retuen input.getValue().getAddress().equales("中关村");
}
}
Map<String,Person> resultMap = Maps.filterEntries(map,predicate);

4 对Map按照key进行过滤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Map<String,Person> map = new HashMap<String,Person>();
Predicate<String> perdicate = new Predicate<String> (){
public boolean apply(String input){
retuen input.contains("gcl");
}
}
Map<String,Person> resultMap = Maps.filterEntries(map,predicate);

5 对Map按照value进行过滤

1
2
3
4
5
6
7
8
9
10
11
12
13
Map<String,Person> map = new HashMap<String,Person>();
Predicate<Person> perdicate = new Predicate<Person> (){
public boolean apply(Person input){
retuen input.getAge()>=22;
}
}
Map<String,Person> resultMap = Maps.filterEntries(map,predicate);

RangeMap:key为一个区间的Map

例如:成绩 85-100评级为A,成绩70-84评级为,成绩60-69为,成绩0-59为D。


RaneMap<Integer,String> rangeMap = TreeRangeMap.create();  

rangeMap.put(Range.closed(85,100),"A");  

rangeMap.put(Range.closed(70,84),"C");  

rangeMap.put(Range.closed(60,69),"B");  

rangeMap.put(Range.closed(0,59),"D");  

String level = rangeMap.get(87);

得到结果为;A