guavabloomfilter性能:Guava系列之新的集合类型
guavabloomfilter性能:Guava系列之新的集合类型Guava提供了多种Multiset的实现,大致对应JDK中Map的各种实现: //通过create()方法创建 Multiset<String> multiset = HashMultiset.create(); //可直接添加元素 multiset.add("a"); multiset.add("b"); multiset.add("c"); multiset.add("c"); multiset.add("c"); List<String> list = new ArrayList<String>(); list.
14/100
Guava中新增加了一些集合类型,是对JDK集合类型的补充,使开发者更方便使用集合类型来实现业务功能
Multiset首先我们来看一下日常研发中常用到的一个场景,统计一个list中每个元素出现的次数,我们大概会这样写:
List<String> list = new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");
list.add("d");
list.add("b");
list.add("b");
Map<String Integer> countMap = new HashMap<String Integer>();
for(String str : list){
if(countMap.get(str) != null){
countMap.put(str countMap.get(str) 1);
} else {
countMap.put(str 1);
}
}
- 首先定义一个list,然后往里面新增若干个元素
- 定义一个Map,遍历list将每个元素出现的次数记录在map里面
显然这样的写法,看起来还是挺笨拙的
Guava提供了Multiset,虽然名字带有Set,但它可以添加重复的元素
Multiset可以看成是ArrayList和Map的结合体
- Multiset是没有元素顺序限制的ArrayList
- Multiset提供了键为元素,值为计数的Map
下面我们来看一下Multiset的实际用法
//通过create()方法创建
Multiset<String> multiset = HashMultiset.create();
//可直接添加元素
multiset.add("a");
multiset.add("b");
multiset.add("c");
multiset.add("c");
multiset.add("c");
List<String> list = new ArrayList<String>();
list.add("xx");
list.add("yy");
list.add("zz");
//也可用addAll方法添加集合进来
multiset.addAll(list);
//获取元素"c"的计数
System.out.println(multiset.count("c"));
//返回去重后的元素set集合
Set<String> set = multiset.elementSet();
//multiset所有元素的个数
System.out.println("multiset.size():" multiset.size());
//multiset去重后的元素个数
System.out.println("elementSet().size():" multiset.elementSet().size());
//元素迭代
Iterator<String> it = multiset.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
//可以通过设置元素的计数,来批量的添加元素,当然能加也能减
multiset.setCount("c" 5);
//将元素的计数设为0,就相当于移除所有的"c"元素
multiset.setCount("c" 0);
//移除一个元素
multiset.remove("c");
//移除两个"c"元素
multiset.remove("c" 2);
可以看出来,Multiset包含了基本的集合操作外,还有一些特有的操作,比如setCount()、按个数remove()
Guava提供了多种Multiset的实现,大致对应JDK中Map的各种实现:
Map 对应的Multiset 是否支持null元素 HashMap HashMultiset 是 TreeMap TreeMultiset 是 LinkedHashMap LinkedHashMultiset 是 ConcurrentHashMap ConcurrentHashMultiset 否 ImmutableMap ImmutableMultiset 否
SortedMultisetSortedMultiset支持高效的获取指定范围的子集
SortedMultiset<String> sortedMultiset = TreeMultiset.create();
sortedMultiset.setCount("c" 5);
sortedMultiset.setCount("a" 3);
sortedMultiset.setCount("b" 2);
//获取第一个元素
sortedMultiset.firstEntry().getElement();
//获了最后一个元素
sortedMultiset.lastEntry().getElement();
//获取子集
SortedMultiset<String> subMultiset = sortedMultiset.subMultiset("a" BoundType.OPEN "b" BoundType.CLOSED);
需要注意,SortedMultiset默认是排好序的,是按元素来进行排序的而不是元素的个数
Multimap在JDK中Map是存储Key-value型数据结构的,并且Key相同时会被覆盖掉 比如
Map<String String> map = new HashMap<String String>();
map.put("key" "value1");
map.put("key" "value2");
最终map里只会存key->value2的值
在很多时候,我们需要一个key对应多个值,在JDK中只能以类似于Map<K List>这种形式来表达 操作起来很不方便
Guava为我们提供了Multimap,可以用来做一个Key映射多个值的操作
Multimap multimap = ArrayListMultimap.create();
//新增元素 直接put
multimap.put("a" "123");
multimap.put("a" "111");
multimap.put("b" "456");
multimap.put("d" "789");
Multimap multimap1 = LinkedListMultimap.create();
multimap1.put("a" "a1_value");
multimap1.put("k2" "k2_value");
//使用putAll方法可以添加一个multimap,这个跟JDK中的putAll一样,而且key相同时会进行合并
multimap.putAll(multimap1);
List<String> list = Lists.newArrayList("a_value1" "a_value2" "a_value3");
//还可以指定key进行批量添加元素,注意此处是追加到key中,不是替换
multimap.putAll("a" list);
//multimap中的所有键值对,重复的算多个
System.out.println(multimap.size());
//key的个数
System.out.println(multimap.keySet().size());
//移除指定key的指定value
multimap.remove("a" "111");
System.out.println(multimap);
//移除整个key的所有value
multimap.removeAll("a");
System.out.println(multimap);
//替换指定key的value
multimap.replaceValues("b" Lists.newArrayList("b1_value" "b2_value"));
//是否包含指定的key
System.out.println(multimap.containsKey("d"));
//是否包含指定的键值对
System.out.println(multimap.containsEntry("d" "789"));
//获取multimap中所有的value
System.out.println(multimap.values());
//返回Multiset
System.out.println(multimap.keys());
//返回Map类型
Map<String List<String>> map = multimap.asMap();
//清空整个集合
multimap.clear();
System.out.println(multimap);
Multimap的各种实现
BiMap在JDK中,如果我们要维护一个双向Map,需要定义两个Map来存储,并且两个要同时进行变更
Map<String String> map1 = Maps.newHashMap();
Map<String String> map2 = Maps.newHashMap();
map1.put("Hello" "Kai");
map2.put("Kai" "Hello");
Guava提供了BiMap,它是一种特殊的Map,可以实现键值的反转
public static void main(String[] args){
BiMap biMap = HashBiMap.create();
biMap.put("a" "123");
System.out.println(biMap);
//对键值对进行反转
System.out.println(biMap.inverse());
//试图将一个key映射到已经存在的值上,会抛异常
biMap.put("b" "123");
//强值将一个key映射到已经存在的值上,会将原来的key覆盖掉
biMap.forcePut("b" "123");
System.out.println(biMap);
}
可以看出,因为BiMap要支持反转,所以它的key和value都必须是唯一的,要不然反转过来就存在一对多的情况
BiMap的各种实现
键–值实现 值–键实现 对应的BiMap实现 HashMap HashMap HashBiMap ImmutableMap ImmutableMap ImmutableBiMap EnumMap EnumMap EnumBiMap EnumMap EnumMap EnumHashBiMap
Table在JDK中当需要做key映射到Key-value对时,你需要这样写Map<K Map<K V>> 这种写法同样不够友好,同时也不便维护
这实际上就是一个表格的行、列、值的结构,Guava里面提供了表格来解决这种场景
//创建row column value结构的table
Table<String String Integer> table = HashBasedTable.create();
table.put("a1" "c1" 23);
table.put("a1" "c2" 77);
table.put("a2" "c2" 44);
//通过rowKey获取columnKey->value的映射关系
System.out.println(table.row("a1"));
//通过columnKey获取rowKey ->value的映射关系
System.out.println(table.column("c2"));
Table有如下几种实现:
- HashBasedTable:本质上用HashMap<R HashMap<C V>>实现;
- TreeBasedTable:本质上用TreeMap<R TreeMap<C V>>实现;
- ImmutableTable:本质上用ImmutableMap<R ImmutableMap<C V>>实现;注:ImmutableTable对稀疏或密集的数据集都有优化。
- ArrayTable:要求在构造时就指定行和列的大小,本质上由一个二维数组实现,以提升访问速度和密集Table的内存利用率。ArrayTable与其他Table的工作原理有点不同,请参见Javadoc了解详情。
ClassToInstanceMap是一种特殊的Map:它的键是类型,而值是符合键所指类型的对象
ClassToInstanceMap<Number> numberDefaults= MutableClassToInstanceMap.create();
numberDefaults.putInstance(Integer.class 6);
还有RangeSet、RangeMap平时用的比较少,大家有需要可以去Guava官网上了解一下 https://github.com/google/guava/wiki/NewCollectionTypesExplained