《Guava学习笔记之二》:新集合类型

2024-05-14 03:58

本文主要是介绍《Guava学习笔记之二》:新集合类型,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《Guava学习笔记之二》:新集合类型

先看一张Java和Guava的集合对比图,如下:(图截取于http://ifeve.com/google-guava-immutablecollections/)

在上篇博文中,我们了解了不可变集合,例如:ImmutableSet、ImmutableList等。

这篇博文,就来看下Multiset、MultiMap、BiMap、Table等。

1、MultiSet

我们都知道在Java中Set集合是不接受重复的元素的哈。但是
MultiSet:接受重复值的Set,即可以多次添加相等的元素

Multiset继承自JDK中的Collection接口,而不是Set接口,所以包含重复元素并没有违反原有的接口契约。

可以用两种方式看待Multiset:

1、没有元素顺序限制的ArrayList

2、Map<E, Integer>,键为元素,值为计数

Guava的Multiset API也结合考虑了这两种方式:
当把Multiset看成普通的Collection时,它表现得就像无序的ArrayList:

  • 1、add(E)添加单个给定元素
  • 2、iterator()返回一个迭代器,包含Multiset的所有元素(包括重复的元素)
  • 3、size()返回所有元素的总个数(包括重复的元素)

当把Multiset看作Map

    @Testpublic void testMultiSet(){Set<String> set = Sets.newHashSet("a","b","c");Multiset<String> multiset =  HashMultiset.create();multiset.addAll(set);multiset.add("a");System.out.println(multiset);Set<String> keys = multiset.elementSet();for(String key:keys){System.out.println(key+", count:" +multiset.count(key));}}

输出:

[a x 2, b, c]
a, count:2
b, count:1
c, count:1

2、MultiMap

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

可以用两种方式思考Multimap的概念:”键-单个值映射”的集合:

a -> 1 a -> 2 a ->4 b -> 3 c -> 5

或者”键-值集合映射”的映射:

a -> [1, 2, 4] b -> 3 c -> 5

一般来说,Multimap接口应该用第一种方式看待,但asMap()视图返回Map<K, Collection<V>>,让你可以按另一种方式看待Multimap。重要的是,不会有任何键映射到空集合:一个键要么至少到一个值,要么根本就不在Multimap中。

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

Multimap.get(key)以集合形式返回键所对应的值视图,即使没有任何对应的值,也会返回空集合。ListMultimap.get(key)返回List,SetMultimap.get(key)返回Set。

Multimap的视图

Multimap还支持若干强大的视图:

1、asMap为Multimap<K, V>提供Map<K,Collection<V>>形式的视图。返回的Map支持remove操作,并且会反映到底层的Multimap,但它不支持put或putAll操作。更重要的是,如果你想为Multimap中没有的键返回null,而不是一个新的、可写的空集合,你就可以使用asMap().get(key)。(你可以并且应当把asMap.get(key)返回的结果转化为适当的集合类型——如SetMultimap.asMap.get(key)的结果转为Set,ListMultimap.asMap.get(key)的结果转为List.

2、entries用Collection<Map.Entry<K, V>>返回Multimap中所有”键-单个值映射”——包括重复键。(对SetMultimap,返回的是Set)

3、keySet用Set表示Multimap中所有不同的键。

4、keys用Multiset表示Multimap中的所有键,每个键重复出现的次数等于它映射的值的个数。可以从这个Multiset中移除元素,但不能做添加操作;移除操作会反映到底层的Multimap。

5、values()用一个”扁平”的Collection包含Multimap中的所有值。这有一点类似于Iterables.concat(multimap.asMap().values()),但它直接返回了单个Collection,而不像multimap.asMap().values()那样是按键区分开的Collection。

看一个例子:

    @Testpublic void testMultimap(){Multimap<String,Integer> multimap = ArrayListMultimap.create();multimap.put("a", 1);multimap.put("a", 2);multimap.put("b", 3);multimap.put("c", 4);System.out.println(multimap);System.out.println(multimap.size());//所有元素的个数System.out.println(multimap.keySet().size());//不同的key的个数//检查multimap是否有"x"这个键String key ="x";//这个检查就说明了即使multimap中不含key,也不是返回null,而是返回的是一个空集合if(multimap.get(key)!=null){System.out.println("multimap中含有key:"+key);}//asMap的使用Map<String,Collection<Integer>> map = multimap.asMap();if(map.get(key)==null){//这里可以直接用 map.containsKey(key)System.out.println("multimap中不含有key:"+key);}}

运行结果:

{a=[1, 2], b=[3], c=[4]}
4
3
multimap中含有key:x
multimap中不含有key:x

Multimap不是Map,Multimap<K, V>不是Map<K,Collection<V>>,虽然某些Multimap实现中可能使用了map。它们之间的显著区别包括:

1、Multimap.get(key)总是返回非null、但是可能空的集合。这并不意味着Multimap为相应的键花费内存创建了集合,而只是提供一个集合视图方便你为键增加映射值(注:如果有这样的键,返回的集合只是包装了Multimap中已有的集合;如果没有这样的键,返回的空集合也只是持有Multimap引用的栈对象,让你可以用来操作底层的Multimap。因此,返回的集合不会占据太多内存,数据实际上还是存放在Multimap中)。如果你更喜欢像Map那样,为Multimap中没有的键返回null,请使用asMap()视图获取一个Map<K, Collection<V>>。(或者用静态方法Multimaps.asMap()为ListMultimap返回一个Map<K, List<V>>。对于SetMultimap和SortedSetMultimap,也有类似的静态方法存在)

2、当且仅当有值映射到键时,Multimap.containsKey(key)才会返回true。尤其需要注意的是,如果键k之前映射过一个或多个值,但它们都被移除后,Multimap.containsKey(key)会返回false。

3、Multimap.entries()返回Multimap中所有”键-单个值映射”——包括重复键。如果你想要得到所有”键-值集合映射”,请使用asMap().entrySet()。

4、Multimap.size()返回所有”键-单个值映射”的个数,而非不同键的个数。要得到不同键的个数,请改用Multimap.keySet().size()

关于更多guava新的集合可以看这里:http://ifeve.com/google-guava-newcollectiontypes/。

小结

关于这些新的集合,只需要知道有这些东西就可以了,虽然有一些注意事项,但是在我们使用的时候,我们只需要查阅下资料和API就可以很快的上手使用。

参考资料

1、http://ifeve.com/google-guava-newcollectiontypes/

这篇关于《Guava学习笔记之二》:新集合类型的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/987690

相关文章

Python如何计算两个不同类型列表的相似度

《Python如何计算两个不同类型列表的相似度》在编程中,经常需要比较两个列表的相似度,尤其是当这两个列表包含不同类型的元素时,下面小编就来讲讲如何使用Python计算两个不同类型列表的相似度吧... 目录摘要引言数字类型相似度欧几里得距离曼哈顿距离字符串类型相似度Levenshtein距离Jaccard相

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

Go语言中三种容器类型的数据结构详解

《Go语言中三种容器类型的数据结构详解》在Go语言中,有三种主要的容器类型用于存储和操作集合数据:本文主要介绍三者的使用与区别,感兴趣的小伙伴可以跟随小编一起学习一下... 目录基本概念1. 数组(Array)2. 切片(Slice)3. 映射(Map)对比总结注意事项基本概念在 Go 语言中,有三种主要

C#比较两个List集合内容是否相同的几种方法

《C#比较两个List集合内容是否相同的几种方法》本文详细介绍了在C#中比较两个List集合内容是否相同的方法,包括非自定义类和自定义类的元素比较,对于非自定义类,可以使用SequenceEqual、... 目录 一、非自定义类的元素比较1. 使用 SequenceEqual 方法(顺序和内容都相等)2.

Redis的Zset类型及相关命令详细讲解

《Redis的Zset类型及相关命令详细讲解》:本文主要介绍Redis的Zset类型及相关命令的相关资料,有序集合Zset是一种Redis数据结构,它类似于集合Set,但每个元素都有一个关联的分数... 目录Zset简介ZADDZCARDZCOUNTZRANGEZREVRANGEZRANGEBYSCOREZ

IDEA如何将String类型转json格式

《IDEA如何将String类型转json格式》在Java中,字符串字面量中的转义字符会被自动转换,但通过网络获取的字符串可能不会自动转换,为了解决IDEA无法识别JSON字符串的问题,可以在本地对字... 目录问题描述问题原因解决方案总结问题描述最近做项目需要使用Ai生成json,可生成String类型

Mysql 中的多表连接和连接类型详解

《Mysql中的多表连接和连接类型详解》这篇文章详细介绍了MySQL中的多表连接及其各种类型,包括内连接、左连接、右连接、全外连接、自连接和交叉连接,通过这些连接方式,可以将分散在不同表中的相关数据... 目录什么是多表连接?1. 内连接(INNER JOIN)2. 左连接(LEFT JOIN 或 LEFT

Redis的Hash类型及相关命令小结

《Redis的Hash类型及相关命令小结》edisHash是一种数据结构,用于存储字段和值的映射关系,本文就来介绍一下Redis的Hash类型及相关命令小结,具有一定的参考价值,感兴趣的可以了解一下... 目录HSETHGETHEXISTSHDELHKEYSHVALSHGETALLHMGETHLENHSET

Python中异常类型ValueError使用方法与场景

《Python中异常类型ValueError使用方法与场景》:本文主要介绍Python中的ValueError异常类型,它在处理不合适的值时抛出,并提供如何有效使用ValueError的建议,文中... 目录前言什么是 ValueError?什么时候会用到 ValueError?场景 1: 转换数据类型场景

C# dynamic类型使用详解

《C#dynamic类型使用详解》C#中的dynamic类型允许在运行时确定对象的类型和成员,跳过编译时类型检查,适用于处理未知类型的对象或与动态语言互操作,dynamic支持动态成员解析、添加和删... 目录简介dynamic 的定义dynamic 的使用动态类型赋值访问成员动态方法调用dynamic 的