《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中Json和其他类型相互转换的实现示例

《Python中Json和其他类型相互转换的实现示例》本文介绍了在Python中使用json模块实现json数据与dict、object之间的高效转换,包括loads(),load(),dumps()... 项目中经常会用到json格式转为object对象、dict字典格式等。在此做个记录,方便后续用到该方

python中的显式声明类型参数使用方式

《python中的显式声明类型参数使用方式》文章探讨了Python3.10+版本中类型注解的使用,指出FastAPI官方示例强调显式声明参数类型,通过|操作符替代Union/Optional,可提升代... 目录背景python函数显式声明的类型汇总基本类型集合类型Optional and Union(py

MySQL中查询和展示LONGBLOB类型数据的技巧总结

《MySQL中查询和展示LONGBLOB类型数据的技巧总结》在MySQL中LONGBLOB是一种二进制大对象(BLOB)数据类型,用于存储大量的二进制数据,:本文主要介绍MySQL中查询和展示LO... 目录前言1. 查询 LONGBLOB 数据的大小2. 查询并展示 LONGBLOB 数据2.1 转换为十

Unity新手入门学习殿堂级知识详细讲解(图文)

《Unity新手入门学习殿堂级知识详细讲解(图文)》Unity是一款跨平台游戏引擎,支持2D/3D及VR/AR开发,核心功能模块包括图形、音频、物理等,通过可视化编辑器与脚本扩展实现开发,项目结构含A... 目录入门概述什么是 UnityUnity引擎基础认知编辑器核心操作Unity 编辑器项目模式分类工程

Java集合中的链表与结构详解

《Java集合中的链表与结构详解》链表是一种物理存储结构上非连续的存储结构,数据元素的逻辑顺序的通过链表中的引用链接次序实现,文章对比ArrayList与LinkedList的结构差异,详细讲解了链表... 目录一、链表概念与结构二、当向单链表的实现2.1 准备工作2.2 初始化链表2.3 打印数据、链表长

Python学习笔记之getattr和hasattr用法示例详解

《Python学习笔记之getattr和hasattr用法示例详解》在Python中,hasattr()、getattr()和setattr()是一组内置函数,用于对对象的属性进行操作和查询,这篇文章... 目录1.getattr用法详解1.1 基本作用1.2 示例1.3 原理2.hasattr用法详解2.

MyBatis的xml中字符串类型判空与非字符串类型判空处理方式(最新整理)

《MyBatis的xml中字符串类型判空与非字符串类型判空处理方式(最新整理)》本文给大家介绍MyBatis的xml中字符串类型判空与非字符串类型判空处理方式,本文给大家介绍的非常详细,对大家的学习或... 目录完整 Hutool 写法版本对比优化为什么status变成Long?为什么 price 没事?怎

C#之枚举类型与随机数详解

《C#之枚举类型与随机数详解》文章讲解了枚举类型的定义与使用方法,包括在main外部声明枚举,用于表示游戏状态和周几状态,枚举值默认从0开始递增,也可手动设置初始值以生成随机数... 目录枚举类型1.定义枚举类型(main外)2.使用生成随机数总结枚举类型1.定义枚举类型(main外)enum 类型名字

Python lambda函数(匿名函数)、参数类型与递归全解析

《Pythonlambda函数(匿名函数)、参数类型与递归全解析》本文详解Python中lambda匿名函数、灵活参数类型和递归函数三大进阶特性,分别介绍其定义、应用场景及注意事项,助力编写简洁高效... 目录一、lambda 匿名函数:简洁的单行函数1. lambda 的定义与基本用法2. lambda

C语言自定义类型之联合和枚举解读

《C语言自定义类型之联合和枚举解读》联合体共享内存,大小由最大成员决定,遵循对齐规则;枚举类型列举可能值,提升可读性和类型安全性,两者在C语言中用于优化内存和程序效率... 目录一、联合体1.1 联合体类型的声明1.2 联合体的特点1.2.1 特点11.2.2 特点21.2.3 特点31.3 联合体的大小1