快捷搜索:  汽车  科技

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 否

SortedMultiset

SortedMultiset支持高效的获取指定范围的子集

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的各种实现

guavabloomfilter性能:Guava系列之新的集合类型(1)

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

ClassToInstanceMap是一种特殊的Map:它的键是类型,而值是符合键所指类型的对象

ClassToInstanceMap<Number> numberDefaults= MutableClassToInstanceMap.create(); numberDefaults.putInstance(Integer.class 6);

还有RangeSet、RangeMap平时用的比较少,大家有需要可以去Guava官网上了解一下 https://github.com/google/guava/wiki/NewCollectionTypesExplained

猜您喜欢: