一、概述

  Guava引入了很多JDK没有的、但明显有用的新集合类型。这些新类型是为了和JDK集合框架共存,而没有往JDK集合抽象中硬塞其他概念。作为一般规则,Guava集合非常精准地遵循了JDK接口契约。

二、使用

2.1、MultiSet[无序+可重复]-工具类Multisets

  Guava提供了一个新集合类型 Multiset,它可以多次添加相等的元素。维基百科从数学角度这样定义Multiset:”集合[set]概念的延伸,它的元素可以重复出现…与集合[set]相同而与元组[tuple]相反的是,Multiset元素的顺序是无关紧要的:Multiset {a, a, b}和{a, b, a}是相等的”。——译者注:这里所说的集合[set]是数学上的概念,Multiset继承自JDK中的Collection接口,而不是Set接口,所以包含重复元素并没有违反原有的接口契约。

  这个接口没有实现java.util.Set接口,Set接口规定里面是不能够放入重复的元素,如果放入重复元素会被覆盖掉的;然而Multiset接口却是可以放入重复元素的,Set接口中的元素是[1,2,3],Multiset中确可以[1✖️2,2✖️3,3✖️3]来表示多个相同的元素。

Guava提供了多种Multiset的实现,大致对应JDK中Map的各种实现:

Map 对应的Multiset 是否支持null元素
HashMap HashMultiset
TreeMap TreeMultiset 是(如果comparator支持的话)
LinkedHashMap LinkedHashMultiset
ConcurrentHashMap ConcurrentHashMultiset
ImmutableMap ImmutableMultiset

使用

    @Test
public void testMultiSet(){
Multiset<String> multiset= HashMultiset.create();
multiset.add("aa");
multiset.add("bb");
multiset.add("cc",2);
System.out.println(multiset);//[aa, bb, cc x 2]
System.out.println(multiset.size()); //
System.out.println(multiset.count("cc"));//
multiset.setCount("bb",4);
System.out.println(multiset);//[aa, bb x 4, cc x 2]
}

  

2.2、SortedMultiset

  SortedMultiset是Multiset 接口的变种,它支持高效地获取指定范围的子集。比方说,你可以用 latencies.subMultiset(0,BoundType.CLOSED, 100, BoundType.OPEN).size()来统计你的站点中延迟在100毫秒以内的访问,然后把这个值和latencies.size()相比,以获取这个延迟水平在总体访问中的比例。

  TreeMultiset实现SortedMultiset接口。在撰写本文档时,ImmutableSortedMultiset还在测试和GWT的兼容性。

2.3、MultiMap[key-value key可以重复 ]-工具类Multimaps

  程序开发中使用Map<K, List<V>>或Map<K, Set<V>>,并且要忍受这个结构的笨拙。例如,Map<K, Set<V>>通常用来表示非标定有向图。Guava的 Multimap可以很容易地把一个键映射到多个值。换句话说,Multimap是把键映射到任意多个值的一般方式。

  很少会直接使用Multimap接口,更多时候你会用ListMultimap或SetMultimap接口,它们分别把键映射到List或Set。

  Multimap提供了多种形式的实现。在大多数要使用Map<K, Collection<V>>的地方,你都可以使用它们:

实现 键行为类似 值行为类似
ArrayListMultimap HashMap ArrayList
HashMultimap HashMap HashSet
LinkedListMultimap* LinkedHashMap* LinkedList*
LinkedHashMultimap** LinkedHashMap LinkedHashMap
TreeMultimap TreeMap TreeSet
ImmutableListMultimap ImmutableMap ImmutableList
ImmutableSetMultimap ImmutableMap ImmutableSet

  除了两个不可变形式的实现,其他所有实现都支持null键和null值

  *LinkedListMultimap.entries()保留了所有键和值的迭代顺序。详情见doc链接。

  **LinkedHashMultimap保留了映射项的插入顺序,包括键插入的顺序,以及键映射的所有值的插入顺序。

  请注意,并非所有的Multimap都和上面列出的一样,使用Map<K, Collection<V>>来实现(特别是,一些Multimap实现用了自定义的hashTable,以最小化开销)

  如果你想要更大的定制化,请用Multimaps.newMultimap(Map, Supplier<Collection>)list和 set版本,使用自定义的Collection、List或Set实现Multimap。

示例:

    @Test
public void testMultiMap() {
Multimap<String, String> multimap = ArrayListMultimap.create();
multimap.put("fruit", "bannana");
multimap.put("fruit", "apple");//key可以重复
multimap.put("fruit", "apple");//value可以重复,不会覆盖之前的
multimap.put("fruit", "peach");
multimap.put("fish", "crucian");//欧洲鲫鱼
multimap.put("fish", "carp");//鲤鱼
Collection<String> fruits = multimap.get("fruit");
System.err.println(fruits);//[bannana, apple, apple, peach] //对比 HashMultimap
Multimap<String,String> multimap2= HashMultimap.create();
multimap2.put("fruit2", "bannana");
multimap2.put("fruit2", "apple");
multimap2.put("fruit2", "apple"); System.err.println(multimap2.size());//
System.err.println(multimap2.get("fruit2"));//[apple, bannana] 注意: 这里只有一个apple
}

2.4、BiMap[双向Map(Bidirectional Map) 键与值都不能重复]

  传统上,实现键值对的双向映射需要维护两个单独的map,并保持它们间的同步。但这种方式很容易出错,而且对于值已经在map中的情况,会变得非常混乱。例如:

Map<String, Integer> nameToId = Maps.newHashMap();
Map<Integer, String> idToName = Maps.newHashMap();
nameToId.put("Bob", 42);
idToName.put(42, "Bob");
//如果"Bob"和42已经在map中了,会发生什么?
//如果我们忘了同步两个map,会有诡异的bug发生...

BiMap<K, V>是特殊的Map:

  可以用 inverse()反转BiMap<K, V>的键值映射
  保证值是唯一的,因此 values()返回Set而不是普通的Collection
  在BiMap中,如果你想把键映射到已经存在的值,会抛出IllegalArgumentException异常。如果对特定值,你想要强制替换它的键,请使用 BiMap.forcePut(key, value)。

    @Test
public void testBiMap() {
BiMap<String, Integer> userId = HashBiMap.create();
userId.put("lhx",30);
userId.put("zll",28);
String userForId = userId.inverse().get(30);
System.out.println(userForId);//lhx userId.put("jm",30);//报错
String userForId2 = userId.inverse().get(30);
System.out.println(userForId2);//lhx
}

BiMap的各种实现

值实现 键实现 对应的BiMap实现
HashMap HashMap HashBiMap
ImmutableMap ImmutableMap ImmutableBiMap
EnumMap EnumMap EnumBiMap
EnumMap HashMap EnumHashBiMap

注:Maps类中还有一些诸如synchronizedBiMap的BiMap工具方法.

2.5、Table【双键的Map Map--> Table-->rowKey+columnKey+value //和sql中的联合主键有点像】-工具类Tables

  行、列、值。当使用多个键做索引的时候,可能会用类似Map<FirstName, Map<LastName, Person>>的实现,这种方式很丑陋,使用上也不友好。

  Guava为此提供了新集合类型Table,它有两个支持所有类型的键:”行”和”列”。

  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了解详情。

示例

    @Test
public void testTable() {
Table<String, String, Integer> table = HashBasedTable.create();
table.put("a", "b", 4);
table.put("a", "c", 20);
table.put("b", "c", 5); Map<String, Integer> a = table.row("a");// returns a Map mapping {b=4, c=20}
System.out.println(a); Map<String, Integer> column = table.column("c");// returns a Map mapping {a=20, b=5}
System.out.println(column); Integer integer = table.get("a", "c");
System.out.println(integer); //
}

2.6、ClassToInstanceMap

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

  为了扩展Map接口,ClassToInstanceMap额外声明了两个方法:T getInstance(Class<T>) 和T putInstance(Class<T>, T),从而避免强制类型转换,同时保证了类型安全。

  ClassToInstanceMap有唯一的泛型参数,通常称为B,代表Map支持的所有类型的上界。例如:

    class Person{
private String name; public Person(String name) {
this.name = name;
} public String getName() {
return name;
} @Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
} @Test
public void testClassToInstanceMap() {
ClassToInstanceMap<Person> instanceMap=MutableClassToInstanceMap.create();
instanceMap.putInstance(Person.class, new Person("lhx"));
instanceMap.putInstance(Person.class, new Person("lhx2"));
Person person = instanceMap.get(Person.class); // Person{name='lhx2'} 存储了 后一个
System.out.println(person);
}

  从技术上讲,ClassToInstanceMap<B>实现了Map<Class<? extends B>, B>——或者换句话说,是一个映射B的子类型到对应实例的Map。这让ClassToInstanceMap包含的泛型声明有点令人困惑,但请记住B始终是Map所支持类型的上界——通常B就是Object。

  对于ClassToInstanceMap,Guava提供了两种有用的实现:MutableClassToInstanceMap和 ImmutableClassToInstanceMap

2.7、RangeSet

  描述了一组不相连的、非空的区间。当把一个区间添加到可变的RangeSet时,所有相连的区间会被合并,空区间会被忽略。例如:

    @Test
public void testRangeSet() {
RangeSet<Integer> rangeSet = TreeRangeSet.create(); rangeSet.add(Range.closed(1, 10)); // {[1,10]}
rangeSet.add(Range.closedOpen(11, 15));//不相连区间:{[1,10], [11,15)}
rangeSet.add(Range.closedOpen(15, 20)); //相连区间; {[1,10], [11,20)}
rangeSet.add(Range.openClosed(0, 0)); //空区间; {[1,10], [11,20)}
rangeSet.remove(Range.open(5, 10)); //分割[1, 10]; {[1,5], [10,10], [11,20)} System.out.println(rangeSet);//[[1..5], [10..10], [11..20)]
}

  请注意,要合并Range.closed(1, 10)和Range.closedOpen(11, 15)这样的区间,你需要首先用Range.canonical(DiscreteDomain)对区间进行预处理,例如DiscreteDomain.integers()。

  注:RangeSet不支持GWT,也不支持JDK5和更早版本;因为,RangeSet需要充分利用JDK6中NavigableMap的特性。

2.8、RangeMap

  RangeMap描述了”不相交的、非空的区间”到特定值的映射。和RangeSet不同,RangeMap不会合并相邻的映射,即便相邻的区间映射到相同的值。例如:

    @Test
public void testRangeMap() {
RangeMap<Integer, String> rangeMap = TreeRangeMap.create(); rangeMap.put(Range.closed(1, 10), "foo"); //{[1,10] => "foo"}
rangeMap.put(Range.open(3, 6), "bar"); //{[1,3] => "foo", (3,6) => "bar", [6,10] => "foo"}
rangeMap.put(Range.open(10, 20), "foo"); //{[1,3] => "foo", (3,6) => "bar", [6,10] => "foo", (10,20) => "foo"}
rangeMap.remove(Range.closed(5, 11)); //{[1,3] => "foo", (3,5) => "bar", (11,20) => "foo"} System.out.println(rangeMap);//[[1..3]=foo, (3..5)=bar, (11..20)=foo]
}

方式

004-guava 集合-新增集合类型-MultiSet, MultiMap, BiMap , Table, ClassToInstanceMap, RangeSe, RangeMap等的更多相关文章

  1. 强大的Guava中的新集合类型: Multiset, Multimap, BiMap, Table, ClassToInstanceMap, RangeSet, RangeMap等

    一 Multiset /** * 新类型集合: Multiset: Multiset就是可以保存多个相同的对象,并且无序 * 占据了List和Set之间的一个灰色地带 * 其他实现: TreeMult ...

  2. Guava新增集合类型-Multimap

    Guava新增集合类型-Multimap 在日常的开发工作中,我们有的时候需要构造像Map<K, List<V>>或者Map<K, Set<V>>这样比 ...

  3. Guava新增集合类型-Multiset

    Guava新增集合类型-Multiset Guava引进了JDK里没有的,但是非常有用的一些新的集合类型.所有这些新集合类型都能和JDK里的集合平滑集成.Guava集合非常精准地实现了JDK定义的接口 ...

  4. Guava学习笔记:Guava新增集合类型-Multimap

    在日常的开发工作中,我们有的时候需要构造像Map<K, List<V>>或者Map<K, Set<V>>这样比较复杂的集合类型的数据结构,以便做相应的业 ...

  5. [Google Guava]学习--新集合类型Multimap

    每个有经验的Java程序员都在某处实现过Map<K, List<V>>或Map<K, Set<V>>,并且要忍受这个结构的笨拙. 假如目前有个需求是给两 ...

  6. [Google Guava]学习--新集合类型Multiset

    Guava提供了一个新集合类型Multiset,它可以多次添加相等的元素,且和元素顺序无关.Multiset继承于JDK的Cllection接口,而不是Set接口. Multiset主要方法介绍: a ...

  7. Guava新增集合类型-Bimap

    Guava新增集合类型-Bimap BiMap提供了一种新的集合类型,它提供了key和value的双向关联的数据结构. 通常情况下,我们在使用Java的Map时,往往是通过key来查找value的,但 ...

  8. [Google Guava] 2.2-新集合类型

    转自:并发编程网 原文链接:http://ifeve.com/google-guava-newcollectiontypes/ 链接博客其他文章中还有更多的guava其他功能的描述,有空可慢慢看. G ...

  9. Guava集合--新集合类型

    Guava引入了很多JDK没有的.但我们发现明显有用的新集合类型.这些新类型是为了和JDK集合框架共存,而没有往JDK集合抽象中硬塞其他概念.作为一般规则,Guava集合非常精准地遵循了JDK接口契约 ...

随机推荐

  1. dt开发之-自定义函数获取分类名称

    需要在api/extend.func.php 文件中加入的函数 获取分类名称 cat_name($catid) 传入分类id function cat_name($catid) { global $d ...

  2. LINQ查询表达式(3) - LINQ 查询分组

    对查询结果进行分组 分组是 LINQ 最强大的功能之一. 下面的示例演示如何以各种方式对数据进行分组: 按照单个属性. 按照字符串属性的首字母. 按照计算出的数值范围. 按照布尔谓词或其他表达式. 按 ...

  3. 行为型模式(二) 命令模式(Command)

    一.动机(Motivate) 在我们的现实生活中有很多例子可以拿来说明这个模式,我们还拿吃饺子这个事情来说.我的奶奶说了,今天想吃饺子,发出了命令,然后我奶奶就去看电视去了.我们夫妻俩收到命令就开始和 ...

  4. Dynamics 365 on-premises 安装

    安装Dynamics 365环境配置要求: 系统版本:Windows Server 2016 SQL 版本: Microsoft SQL Server 2016 SP2 Dynamics 365 版本 ...

  5. ajax同步与异步的区别

    jquery中ajax方法有个属性async用于控制同步和异步,默认是true,即ajax请求默认是异步请求,有时项目中会用到AJAX同步.这个同步的意思是当JS代码加载到当前AJAX的时候会把页面里 ...

  6. HTTP 包体

    HTTP包体:承载的消息内容 两种传输HTTP包体的方式 定长包体: 不定长包体: HTML FORM表单 HTML FORM表单提交请求时的关键属性 HTML FORM表单提交请求时的关键属性 Mu ...

  7. BZOJ 2502 清理雪道(有源汇上下界最小流)

    题面 滑雪场坐落在FJ省西北部的若干座山上. 从空中鸟瞰,滑雪场可以看作一个有向无环图,每条弧代表一个斜坡(即雪道),弧的方向代表斜坡下降的方向. 你的团队负责每周定时清理雪道.你们拥有一架直升飞机, ...

  8. RocketMQ部分消息消费不到的问题

    在企业项目中,利用RocketMQ接收数据,存库. 由于是第一次在项目中具体的使用RocketMQ,一直采坑. 1.发现问题:在最终的联调过程中,并发压测,订单数据丢失,同一时刻,oms推送900+的 ...

  9. [React] Create an Animate Content Placeholder for Loading State in React

    We will create animated Content Placeholder as React component just like Facebook has when you load ...

  10. 关于Keil4 转到 Keil5以后的一些错误解决

    一, 看自己选择CPU型号,根据型号再做配置 根据自己型号填写