![](https://qinglite-1253448069.cos.ap-shanghai.myqcloud.com/7521/xiaohongshu/mmbiz_jpg/Uic0S1r5o6Ov06qjRyP24TRzWx7Yvryq18icICgsWVUdicE4DTPHBADU8Da8d36o82Ovb652MVfkxGxaayRyYuEIQ/0%3Fwx_fmt%3Djpeg?imageMogr2/format/webp)
链接 | www.jianshu.com/p/97778b21bd00阿里巴巴出了一本Java规范,在国内java开发眼里被赋予了神圣的殿堂,我不推荐你用阿里巴巴的开发手册。目前Google Guava在实际应用中非常广泛,本篇博客将以博主对 Guava 使用的认识以及在项目中的经验来给大家分享!学习使用 Google Guava可以让你快乐编程,写出优雅的 Java 代码,在业务允许的条件下,我推荐使用 Guava编程!Google 出品 Java 编码规范,科学又权威,强烈推荐!Joiner/Splitter/CharMatcher也许还不够友好,至少让我们用起来还不够爽,还得操心!举个栗子,比如String提供的split方法,我们得关心空字符串吧,还得考虑返回的结果中存在null元素吧,只提供了前后trim的方法(如果我想对中间元素进行trim呢)。那么,看下面的代码示例,guava让你不必在操心这些:![](https://filescdn.proginn.com/5378c4a7822c3b88d2d0a428cf5157fc/57edeab46c3e13e8f184516adb19b1e5.webp)
Joiner是连接器,Splitter是分割器,通常我们会把它们定义为static final,利用on生成对象后在应用到String进行处理,这是可以复用的。要知道apache commons StringUtils提供的都是static method。更加重要的是,guava提供的Joiner/Splitter是经过充分测试,它的稳定性和效率要比apache高出不少,这个你可以自行测试下。发现没有我们想对String做什么操作,就是生成自己定制化的Joiner/Splitter,多么直白,简单,流畅的API!对于Joiner,常用的方法是 跳过NULL元素:skipNulls() / 对于NULL元素使用其他替代:useForNull(String)对于Splitter,常用的方法是:trimResults()/omitEmptyStrings()。注意拆分的方式,有字符串,还有正则,还有固定长度分割(太贴心了!)其实除了Joiner/Splitter外,guava还提供了字符串匹配器:CharMatcher![](https://filescdn.proginn.com/c6abc9a263f0b0a1ced47a831f2c5f99/fb7db6fc931d66a96214216ff2461d73.webp)
CharMatcher,将字符的匹配和处理解耦,并提供丰富的方法供你使用!
guava对JDK提供的原生类型操作进行了扩展,使得功能更加强大![](https://filescdn.proginn.com/d68eb6362a85a5b8394ea387d21c5aee/9f97077f1ff29057df1ece7106348871.webp)
guava提供了Bytes/Shorts/Ints/Iongs/Floats/Doubles/Chars/Booleans这些基本数据类型的扩展支持,只有你想不到的,没有它没有的!JDK的集合,提供了有序且可以重复的List,无序且不可以重复的Set。那这里其实对于集合涉及到了2个概念,一个order,一个dups。那么List vs Set,and then some ?
![](https://filescdn.proginn.com/44b7943214f4e6fa9a6ade9b2ee4da3e/a418ff4886d80297d92358186c6fb01b.webp)
Multiset是什么,我想上面的图,你应该了解它的概念了。Multiset就是无序的,但是可以重复的集合,它就是游离在List/Set之间的“灰色地带”!(至于有序的,不允许重复的集合嘛,guava还没有提供,当然在未来应该会提供UniqueList,我猜的,哈哈)![](https://filescdn.proginn.com/6022d770a710e05270cc09491f57caa8/a348b2b09be09402f8f30df9e12e4ce4.webp)
Multiset自带一个有用的功能,就是可以跟踪每个对象的数量。Immutable vs unmodifiable
![](https://filescdn.proginn.com/e9d7dbf0d0003319f256cd58d9ad0a92/2ca5c0db4d58a463bad87ed3f96204b8.webp)
你看到JDK提供的unmodifiable的缺陷了吗?实际上,Collections.unmodifiableXxx所返回的集合和源集合是同一个对象,只不过可以对集合做出改变的API都被override,会抛出UnsupportedOperationException。也即是说我们改变源集合,导致不可变视图(unmodifiable View)也会发生变化,oh my god!当然,在不使用guava的情况下,我们是怎么避免上面的问题的呢?![](https://filescdn.proginn.com/e344596dfb90c279f8ad1d58efa39b62/9e5884ec2ad3a90f9fafb0bdf0070e47.webp)
上面揭示了一个概念:Defensive Copies,保护性拷贝。OK,unmodifiable看上去没有问题呢,但是guava依然觉得可以改进,于是提出了Immutable的概念,来看:![](https://filescdn.proginn.com/c9989cc48cd048a6cf546c919ed651c2/6b882072bb9d6d327fd0561ee819dc1c.webp)
用Google官方的说法是:we're using just one class,just say exactly what we mean,很了不起吗(不仅仅是个概念,Immutable在COPY阶段还考虑了线程的并发性等,很智能的!)guava提供了很多Immutable集合,比如ImmutableList/ImmutableSet/ImmutableSortedSet/ImmutableMap/......![](https://filescdn.proginn.com/c65efd8ea3263d1e4e0d7bf72b4f7cc9/9e3e4639e0c1d9f6929706138af7e55b.webp)
JDK提供给我们的Map是一个键,一个值,一对一的,那么在实际开发中,显然存在一个KEY多个VALUE的情况(比如一个分类下的书本),我们往往这样表达:Map>,好像有点臃肿!臃肿也就算了,更加不爽的事,我们还得判断KEY是否存在来决定是否new 一个LIST出来,有点麻烦!更加麻烦的事情还在后头,比如遍历,比如删除,so hard......![](https://filescdn.proginn.com/56af3fba03b8330ff9a723c3549c5f65/0a127939f9662c256caecf0b10b184af.webp)
友情提示下,guava所有的集合都有create方法,这样的好处在于简单,而且我们不必在重复泛型信息了。
get()/keys()/keySet()/values()/entries()/asMap()都是非常有用的返回view collection的方法。Multimap的实现类有:ArrayListMultimap/HashMultimap/LinkedHashMultimap/TreeMultimap/ImmutableMultimap/......可不可以双向:BiMap
JDK提供的MAP让我们可以find value by key,那么能不能通过find key by value呢,能不能KEY和VALUE都是唯一的呢。这是一个双向的概念,即forward+backward。在实际场景中有这样的需求吗?比如通过用户ID找到mail,也需要通过mail找回用户名。没有guava的时候,我们需要create forward map AND create backward map,and now just let guava do that for you.![](https://filescdn.proginn.com/2821d1af38f2b903eacb862928239852/5462d5db8ab0923ddae6a8988ac8d90b.webp)
biMap / biMap.inverse() / biMap.inverse().inverse() 它们是什么关系呢?你可以稍微看一下BiMap的源码实现,实际上,当你创建BiMap的时候,在内部维护了2个map,一个forward map,一个backward map,并且设置了它们之间的关系。因此,biMap.inverse() != biMap ;biMap.inverse().inverse() == biMap可不可以多个KEY:Table
我们知道数据库除了主键外,还提供了复合索引,而且实际中这样的多级关系查找也是比较多的,当然我们可以利用嵌套的Map来实现:Map>。为了让我们的代码看起来不那么丑陋,guava为我们提供了Table。![](https://filescdn.proginn.com/c958e544fdb5ddfc8437843dbc66dd90/79bb9076cc430d2cb595a43b09498d2b.webp)
Table涉及到3个概念:rowKey,columnKey,value,并提供了多种视图以及操作方法让你更加轻松的处理多个KEY的场景。![](https://filescdn.proginn.com/fc32d5e03e86b0f6a764994ab66ab3d1/9af7ff8d6613ae38fb9269438ff54553.webp)
上面的代码是为了完成将List集合中的元素,先截取5个长度,然后转成大写。函数式编程的好处在于在集合遍历操作中提供自定义Function的操作,比如transform转换。我们再也不需要一遍遍的遍历集合,显著的简化了代码!![](https://filescdn.proginn.com/9bea799c7515a1bb1a02d43651f7df65/ab9efe33438b90ee8979b628ba0d3dd1.webp)
对集合的transform操作可以通过Function完成Predicate最常用的功能就是运用在集合的过滤当中!
![](https://filescdn.proginn.com/51b5e09b9a200c1ec88306ae6f5eb3c9/8bd2ce064b06c1bac9ef5627650b6cf2.webp)
需要注意的是Lists并没有提供filter方法,不过你可以使用Collections2.filter完成!check null and other:Optional、Preconditions
在guava中,对于null的处理手段是快速失败,你可以看看guava的源码,很多方法的第一行就是:Preconditions.checkNotNull(elements);
要知道null是模糊的概念,是成功呢,还是失败呢,还是别的什么含义呢?![](https://filescdn.proginn.com/d3164ef7db98eae6f892551dd8968ce2/5857484eb92b398d10a003ef4b28d59e.webp)
对于大多数互联网项目而言,缓存的重要性,不言而喻!如果我们的应用系统,并不想使用一些第三方缓存组件(如redis),我们仅仅想在本地有一个功能足够强大的缓存,很可惜JDK提供的那些SET/MAP还不行!![](https://filescdn.proginn.com/9bea9056ed99324f785596fc466cdde1/880a7b6ab7e8e02928c341a99aa6d3fb.webp)
首先,这是一个本地缓存,guava提供的cache是一个简洁、高效,易于维护的。为什么这么说呢?因为并没有一个单独的线程用于刷新 OR 清理cache,对于cache的操作,都是通过访问/读写带来的,也就是说在读写中完成缓存的刷新操作!其次,我们看到了,我们非常通俗的告诉cache,我们的缓存策略是什么,SO EASY!在如此简单的背后,是guava帮助我们做了很多事情,比如线程安全。JDK中提供了Future/FutureTask/Callable来对异步回调进行支持,但是还是看上去挺复杂的,能不能更加简单呢?比如注册一个监听回调。![](https://filescdn.proginn.com/96e211c8743ed7210bf202103189a95a/c76aad9d0979ad6c7f8b10b2e5f7bde2.webp)
我们可以通过guava对JDK提供的线程池进行装饰,让其具有异步回调监听功能,然后在设置监听器即可!
到这里,这篇文章也只介绍了guava的冰山一角,其实还有很多内容:比如反射、注解、网络、并发、IO等等,好了,希望这篇文章让你快速进阶,快乐编程!这两天我搭建了一个自动发账号密码的商品,想买ChatGPT成品号的可以了解一下。数量不多,预购从速,不用注册可以直接购买,支付页面需要保存下支付二维码,然后去支付宝或者微信扫一扫后。购买后,不会发邮件,需要你再回到商城点击最上面的【查看订单】,可以根据浏览器缓存或你输入的邮箱及密码,看到订单详情,点开就是账号和密码,过程是全自动的。扫码或者直接访问ChatGPT账号商店:http://www.itsmartfish.com
![](https://filescdn.proginn.com/06a5256701897cff305d6a5a48e32d6e/15d2d3648c5ac5b37e5bbec30db441c1.webp)
![](https://filescdn.proginn.com/4697f54b637263477a000cbad6b4a011/839d25933d40911b83f536086873ec00.webp)