概述

工具类 就是封装平常用的方法,不需要你重复造轮子,节省开发人员时间,提高工作效率。谷歌作为大公司,当然会从日常的工作中提取中很多高效率的方法出来。所以就诞生了guava。

guava的优点:

  • 高效设计良好的API,被Google的开发者设计,实现和使用
  • 遵循高效的java语法实践
  • 使代码更刻度,简洁,简单
  • 节约时间,资源,提高生产力

Guava工程包含了若干被Google的 Java项目广泛依赖 的核心库,例如:

  • 集合 [collections]
  • 缓存 [caching]
  • 原生类型支持 [primitives support]
  • 并发库 [concurrency libraries]
  • 通用注解 [common annotations]
  • 字符串处理 [string processing]
  • I/O 等等。

使用

引入gradle依赖(引入Jar包)

compile 'com.google.guava:guava:26.0-jre'

1.集合的创建

// 普通Collection的创建
List<String> list = Lists.newArrayList();
Set<String> set = Sets.newHashSet();
Map<String, String> map = Maps.newHashMap();// 不变Collection的创建
ImmutableList<String> iList = ImmutableList.of("a", "b", "c");
ImmutableSet<String> iSet = ImmutableSet.of("e1", "e2");
ImmutableMap<String, String> iMap = ImmutableMap.of("k1", "v1", "k2", "v2");

创建不可变集合 先理解什么是immutable(不可变)对象

  • 在多线程操作下,是线程安全的
  • 所有不可变集合会比可变集合更有效的利用资源
  • 中途不可改变
ImmutableList<String> immutableList = ImmutableList.of("1","2","3","4");

这声明了一个不可变的List集合,List中有数据1,2,3,4。类中的 操作集合的方法(譬如add, set, sort, replace等)都被声明过期,并且抛出异常。 而没用guava之前是需要声明并且加各种包裹集合才能实现这个功能

  // add 方法@Deprecated @Overridepublic final void add(int index, E element) {throw new UnsupportedOperationException();}

当我们需要一个map中包含key为String类型,value为List类型的时候,以前我们是这样写的

Map<String,List<Integer>> map = new HashMap<String,List<Integer>>();
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
map.put("aa", list);
System.out.println(map.get("aa"));//[1, 2]

而现在

Multimap<String,Integer> map = ArrayListMultimap.create();
map.put("aa", 1);
map.put("aa", 2);
System.out.println(map.get("aa"));  //[1, 2]

其他的黑科技集合

MultiSet: 无序+可重复   count()方法获取单词的次数  增强了可读性+操作简单
创建方式:  Multiset<String> set = HashMultiset.create();Multimap: key-value  key可以重复
创建方式: Multimap<String, String> teachers = ArrayListMultimap.create();BiMap: 双向Map(Bidirectional Map) 键与值都不能重复
创建方式:  BiMap<String, String> biMap = HashBiMap.create();Table: 双键的Map Map--> Table-->rowKey+columnKey+value  //和sql中的联合主键有点像
创建方式: Table<String, String, Integer> tables = HashBasedTable.create();...等等(guava中还有很多java里面没有给出的集合类型)

2.将集合转换为特定规则的字符串

以前我们将list转换为特定规则的字符串是这样写的:

//use java
List<String> list = new ArrayList<String>();
list.add("aa");
list.add("bb");
list.add("cc");
String str = "";
for(int i=0; i<list.size(); i++){str = str + "-" +list.get(i);
}
//str 为-aa-bb-cc//use guava
List<String> list = new ArrayList<String>();
list.add("aa");
list.add("bb");
list.add("cc");
String result = Joiner.on("-").join(list);
//result为  aa-bb-cc

把map集合转换为特定规则的字符串

Map<String, Integer> map = Maps.newHashMap();
map.put("xiaoming", 12);
map.put("xiaohong",13);
String result = Joiner.on(",").withKeyValueSeparator("=").join(map);
// result为 xiaoming=12,xiaohong=13

3.将String转换为特定的集合

//use java
List<String> list = new ArrayList<String>();
String a = "1-2-3-4-5-6";
String[] strs = a.split("-");
for(int i=0; i<strs.length; i++){list.add(strs[i]);
}//use guava
String str = "1-2-3-4-5-6";
List<String> list = Splitter.on("-").splitToList(str);
//list为  [1, 2, 3, 4, 5, 6]

如果

str="1-2-3-4- 5-  6  ";

guava还可以使用 omitEmptyStrings().trimResults() 去除空串与空格

String str = "1-2-3-4-  5-  6   ";
List<String> list = Splitter.on("-").omitEmptyStrings().trimResults().splitToList(str);
System.out.println(list);

将String转换为map

String str = "xiaoming=11,xiaohong=23";
Map<String,String> map = Splitter.on(",").withKeyValueSeparator("=").split(str);

4.guava还支持多个字符切割,或者特定的正则分隔

String input = "aa.dd,,ff,,.";
List<String> result = Splitter.onPattern("[.|,]").omitEmptyStrings().splitToList(input);

关于字符串的操作 都是在Splitter这个类上进行的

// 判断匹配结果
boolean result = CharMatcher.inRange('a', 'z').or(CharMatcher.inRange('A', 'Z')).matches('K'); //true// 保留数字文本  CharMatcher.digit() 已过时   retain 保留
//String s1 = CharMatcher.digit().retainFrom("abc 123 efg"); //123
String s1 = CharMatcher.inRange('0', '9').retainFrom("abc 123 efg"); // 123// 删除数字文本  remove 删除
// String s2 = CharMatcher.digit().removeFrom("abc 123 efg");    //abc  efg
String s2 = CharMatcher.inRange('0', '9').removeFrom("abc 123 efg"); // abc  efg

5. 集合的过滤

我们对于集合的过滤,思路就是迭代,然后再具体对每一个数判断,这样的代码放在程序中,难免会显得很臃肿,虽然功能都有,但是很不好看。

guava写法

//按照条件过滤
ImmutableList<String> names = ImmutableList.of("begin", "code", "Guava", "Java");
Iterable<String> fitered = Iterables.filter(names, Predicates.or(Predicates.equalTo("Guava"), Predicates.equalTo("Java")));
System.out.println(fitered); // [Guava, Java]//自定义过滤条件   使用自定义回调方法对Map的每个Value进行操作
ImmutableMap<String, Integer> m = ImmutableMap.of("begin", 12, "code", 15);// Function<F, T> F表示apply()方法input的类型,T表示apply()方法返回类型Map<String, Integer> m2 = Maps.transformValues(m, new Function<Integer, Integer>() {public Integer apply(Integer input) {if(input>12){return input;}else{return input+1;}}});
System.out.println(m2);   //{begin=13, code=15}

set的交集, 并集, 差集

HashSet setA = newHashSet(1, 2, 3, 4, 5);
HashSet setB = newHashSet(4, 5, 6, 7, 8);  SetView union = Sets.union(setA, setB);
System.out.println("union:");
for (Integer integer : union)  System.out.println(integer);           //union 并集:12345867SetView difference = Sets.difference(setA, setB);
System.out.println("difference:");
for (Integer integer : difference)  System.out.println(integer);        //difference 差集:123SetView intersection = Sets.intersection(setA, setB);
System.out.println("intersection:");
for (Integer integer : intersection)  System.out.println(integer);  //intersection 交集:45

map的交集,并集,差集

HashMap<String, Integer> mapA = Maps.newHashMap();
mapA.put("a", 1);mapA.put("b", 2);mapA.put("c", 3);HashMap<String, Integer> mapB = Maps.newHashMap();
mapB.put("b", 20);mapB.put("c", 3);mapB.put("d", 4);MapDifference differenceMap = Maps.difference(mapA, mapB);
differenceMap.areEqual();
Map entriesDiffering = differenceMap.entriesDiffering();
Map entriesOnlyLeft = differenceMap.entriesOnlyOnLeft();
Map entriesOnlyRight = differenceMap.entriesOnlyOnRight();
Map entriesInCommon = differenceMap.entriesInCommon();System.out.println(entriesDiffering);   // {b=(2, 20)}
System.out.println(entriesOnlyLeft);    // {a=1}
System.out.println(entriesOnlyRight);   // {d=4}
System.out.println(entriesInCommon);    // {c=3}

6.检查参数

//use java
if(list!=null && list.size()>0)
'''
if(str!=null && str.length()>0)
'''
if(str !=null && !str.isEmpty())//use guava
if(!Strings.isNullOrEmpty(str))//use java
if (count <= 0) {throw new IllegalArgumentException("must be positive: " + count);
}    //use guava
Preconditions.checkArgument(count > 0, "must be positive: %s", count);  

免去了很多麻烦!并且会使你的代码看上去更好看。而不是代码里面充斥着 !=null, !=""

检查是否为空,不仅仅是字符串类型,其他类型的判断,全部都封装在 Preconditions类里,里面的方法全为静态

其中的一个方法的源码

@CanIgnoreReturnValue
public static <T> T checkNotNull(T reference) {if (reference == null) {throw new NullPointerException();}return reference;
}
方法声明(不包括额外参数) 描述 检查失败时抛出的异常
checkArgument(boolean) 检查boolean是否为true,用来检查传递给方法的参数。 IllegalArgumentException
checkNotNull(T) 检查value是否为null,该方法直接返回value,因此可以内嵌使用checkNotNull。 NullPointerException
checkState(boolean) 用来检查对象的某些状态。 IllegalStateException
checkElementIndex(int index, int size) 检查index作为索引值对某个列表、字符串或数组是否有效。 index > 0 && index < size IndexOutOfBoundsException
checkPositionIndexes(int start, int end, int size) 检查[start,end]表示的位置范围对某个列表、字符串或数组是否有效 IndexOutOfBoundsException

7. MoreObjects

这个方法是在Objects过期后官方推荐使用的替代品,该类最大的好处就是不用大量的重写 toString,用一种很优雅的方式实现重写,或者在某个场景定制使用。

Person person = new Person("aa",11);
String str = MoreObjects.toStringHelper("Person").add("age", person.getAge()).toString();
System.out.println(str);
//输出Person{age=11}

8.强大的Ordering排序器

排序器[Ordering]是Guava流畅风格比较器[Comparator]的实现,它可以用来为构建复杂的比较器,以完成集合排序的功能。

natural()   对可排序类型做自然排序,如数字按大小,日期按先后排序
usingToString() 按对象的字符串形式做字典排序[lexicographical ordering]
from(Comparator)    把给定的Comparator转化为排序器
reverse()   获取语义相反的排序器
nullsFirst()    使用当前排序器,但额外把null值排到最前面。
nullsLast() 使用当前排序器,但额外把null值排到最后面。
compound(Comparator)    合成另一个比较器,以处理当前排序器中的相等情况。
lexicographical()   基于处理类型T的排序器,返回该类型的可迭代对象Iterable<T>的排序器。
onResultOf(Function)    对集合中元素调用Function,再按返回值用当前排序器排序。

示例

Person person = new Person("aa",14);  //String name  ,Integer age
Person ps = new Person("bb",13);
Ordering<Person> byOrdering = Ordering.natural().nullsFirst().onResultOf(new Function<Person,String>(){public String apply(Person person){return person.age.toString();}
});
byOrdering.compare(person, ps);
System.out.println(byOrdering.compare(person, ps)); //1      person的年龄比ps大 所以输出1

9.计算中间代码的运行时间

Stopwatch stopwatch = Stopwatch.createStarted();
for(int i=0; i<100000; i++){// do some thing
}
long nanos = stopwatch.elapsed(TimeUnit.MILLISECONDS);
System.out.println(nanos);

TimeUnit 可以指定时间输出精确到多少时间

10.文件操作

以前我们写文件读取的时候要定义缓冲区,各种条件判断,各种 $%#$@#

而现在我们只需要使用好guava的api 就能使代码变得简洁,并且不用担心因为写错逻辑而背锅了

File file = new File("test.txt");
List<String> list = null;
try {list = Files.readLines(file, Charsets.UTF_8);
} catch (Exception e) {
}Files.copy(from,to);  //复制文件
Files.deleteDirectoryContents(File directory); //删除文件夹下的内容(包括文件与子文件夹)
Files.deleteRecursively(File file); //删除文件或者文件夹
Files.move(File from, File to); //移动文件
URL url = Resources.getResource("abc.xml"); //获取classpath根下的abc.xml文件url

Files类中还有许多方法可以用,可以多多翻阅

11.guava缓存

guava的缓存设计的比较巧妙,可以很精巧的使用。guava缓存创建分为两种,一种是CacheLoader,另一种则是callback方式

Cache的定时清理实现逻辑(失效时间+增加维护accessQueue,writeQueue两个队列用于记录缓存顺序,这样才可以按照顺序淘汰数据):https://crossoverjie.top/2018/06/13/guava/guava-cache/

CacheLoader:

LoadingCache<String,String> cahceBuilder=CacheBuilder.newBuilder()// 设置并发级别,并发级别是指可以同时写缓存的线程数.concurrencyLevel(10)// 设置缓存过期时间.expireAfterWrite(10, TimeUnit.MINUTES)// 设置缓存容器的初始容量.initialCapacity(10)// 设置缓存最大容量,超过之后就会按照LRU最近虽少使用算法来移除缓存项.maximumSize(500)// 设置缓存的移除通知.removalListener(new RemovalListener<Object, Object>() {public void onRemoval(RemovalNotification<Object, Object> notification) {LOGGER.warn(notification.getKey() + " was removed, cause is " + notification.getCause());}}).build(new CacheLoader<String, String>(){@Overridepublic String load(String key) throws Exception {        String strProValue="hello "+key+"!";                return strProValue;}});
System.out.println(cahceBuilder.apply("begincode"));  //hello begincode!
System.out.println(cahceBuilder.get("begincode")); //hello begincode!
System.out.println(cahceBuilder.get("wen")); //hello wen!     //获取缓存值,callable实现缓存回调
System.out.println(cahceBuilder.apply("wen")); //hello wen!   //请求缓存值
System.out.println(cahceBuilder.apply("da"));//hello da!
cahceBuilder.put("begin", "code");   //设置缓存内容
System.out.println(cahceBuilder.get("begin")); //code
cahceBuilder.invalidateAll();    //清除缓存

api中已经把apply声明为过期,声明中推荐使用get方法获取值

callback方式: 回调之中已经实现了对数据的添加,

 Cache<String, String> cache = CacheBuilder.newBuilder().maximumSize(1000).build();  String resultVal = cache.get("code", new Callable<String>() {  public String call() {  String strProValue="begin "+"code"+"!";             //回调实现添加入值;无需put   return strProValue;}  });  System.out.println("value : " + resultVal); //value : begin code!//get回调实现源码V get(K key, int hash, CacheLoader<? super K, V> loader) throws ExecutionException {checkNotNull(key);checkNotNull(loader);try {if (count != 0) { // read-volatile// don't call getLiveEntry, which would ignore loading valuesReferenceEntry<K, V> e = getEntry(key, hash);if (e != null) {long now = map.ticker.read();V value = getLiveValue(e, now);if (value != null) {recordRead(e, now);statsCounter.recordHits(1);return scheduleRefresh(e, key, hash, value, now, loader);}ValueReference<K, V> valueReference = e.getValueReference();if (valueReference.isLoading()) {return waitForLoadingValue(e, key, valueReference);}}}// 缓存中不存在数据return lockedGetOrLoad(key, hash, loader);} catch (ExecutionException ee) {Throwable cause = ee.getCause();if (cause instanceof Error) {throw new ExecutionError((Error) cause);} else if (cause instanceof RuntimeException) {throw new UncheckedExecutionException(cause);}throw ee;} finally {postReadCleanup();}}

以上只是guava使用的一小部分,guava是个大的工具类,第一版guava是2010年发布的,每一版的更新和迭代都是一种创新。

jdk的升级很多都是借鉴guava里面的思想来进行的。

小结

代码可以在 https://github.com/whirlys/elastic-example/tree/master/guava 下载

细节请翻看 guava 文档 https://github.com/google/guava/wiki

参考: 
Google guava工具类的介绍和使用 
Guava工具类学习

谷歌guava工具包详解相关推荐

  1. 阿昌教你使用谷歌guava工具包---集合包

    前言 今天阿昌这里分享一个谷歌guava工具包,自己在工作业务中洋哥推荐的一个集合工具包的partition()方法,看了看这个工具包的方法并不是很多,主要常用也就是以下正文的3个方法. 准备 走开始 ...

  2. [转帖]前端-chromeF12 谷歌开发者工具详解 Sources篇

    前端-chromeF12 谷歌开发者工具详解 Sources篇 原贴地址:https://blog.csdn.net/qq_39892932/article/details/82498748 cons ...

  3. 【guava】 谷歌guava工具包的常用方法 双key的map 、驼峰转下划线等小结

    文章目录 1. maven引入 (某些框架会引入guava 注意版本冲突问题) 2. guava 对集合的处理 3. guava的 双键table (双key map) 4. guava的文件读写 代 ...

  4. foxmail邮件加载失败重试_java retry(重试) spring retry, guava retrying 详解

    系列说明 java retry 的一步步实现机制. java-retry 源码地址 情景导入 简单的需求 产品经理:实现一个按条件,查询用户信息的服务. 小明:好的.没问题. 代码 UserServi ...

  5. java retry(重试) spring retry, guava retrying 详解

    转载 自 http://blog.51cto.com/9250070/2156431 系列说明 java retry 的一步步实现机制. java-retry 源码地址 情景导入 简单的需求 产品经理 ...

  6. 神经网络是怎样理解图片的?谷歌大脑研究员详解特征可视化

    夏乙 编译整理 量子位 出品 | 公众号 QbitAI 我们总是听说人工智能在图像识别上超越了人类,刷脸也逐渐成了生活中司空见惯的事儿.这些图像识别技术背后,通常是深度神经网络. 不过,神经网络究竟是 ...

  7. Guava缓存详解及使用

    缓存 缓存分为本地缓存与分布式缓存.本地缓存为了保证线程安全问题,一般使用ConcurrentMap的方式保存在内存之中,而常见的分布式缓存则有Redis,MongoDB等. 一致性:本地缓存由于数据 ...

  8. 谷歌开发者工具详解 Network篇

    原文链接:https://segmentfault.com/a/1190000010302235 开发者工具初步介绍 在利用chrome浏览器进行web端测试,我们可以通过F12键调起开发者工具. c ...

  9. 怎样用谷歌network调试接口_前端-chromeF12 谷歌开发者工具详解 Network篇

    开发者工具初步介绍 chrome开发者工具最常用的四个功能模块: Elements:主要用来查看前面界面的html的Dom结构,和修改css的样式.css可以即时修改,即使显示.大大方便了开发者调试页 ...

最新文章

  1. 哪些书你看之前以为很枯燥,结果一看却欲罢不能的?
  2. 【安全漏洞】ThinkPHP 3.2.3 漏洞复现
  3. [云炬创业基础笔记]第五章创业机会评估测试13
  4. 【软件工程】第一章重点
  5. 为什么需要Survivor区?只有Eden不行吗?
  6. QScrollArea 详解
  7. 提升NAS网速技能get:网络聚合模式
  8. linux脚本程序是什么意思,什么是shell脚本编程?
  9. 怎么看准确率_做题粗心马虎怎么训练?采取这三项措施,有效提高做题的准确率...
  10. 实例解析:OperaMasks2.0中的DataGrid之一:定义DataGrid
  11. Element UI 中table的验证
  12. 轻量级ORM框架 Bankinate
  13. 本地文件搜索神器everything介绍
  14. 推荐几款微信小程序常用组件库
  15. codeforces Star sky(二维前缀和)
  16. 什么是latch以及如何导致latch争用
  17. 关于AWB的肤色问题
  18. 几何画板用迭代法作图的技巧
  19. MySQL之——mysql5.5 uuid做主键与int做主键的性能实测
  20. datastage Transformation函数之INDEX

热门文章

  1. 首款MeeGo系统上网本 华硕Eee PcX101H独家首测(4)
  2. C语言#pragma使用
  3. VS 之 预编译处理#pragma用法
  4. MySQL——存储引擎与索引应用
  5. linux ftp 删文件夹,Linux FTP账号无法删除文件夹如何解决
  6. 7-5 复数四则运算
  7. GAN深度强化学习1
  8. jetpack compose原理解析
  9. Unable to handle kernel paging request at virtual address 的解决办法
  10. 传输层协议UDP简介