Guava工程包含了若干被Google的 Java项目广泛依赖 的核心库,例如:集合 [collections] 、缓存 [caching] 、原生类型支持 [primitives support] 、并发库 [concurrency libraries] 、通用注解 [common annotations] 、字符串处理 [string processing] 、I/O 等等。

guava类似Apache Commons工具集

基本工具包Base

Optional

guava的Optional类似于Java 8新增的Optional类,都是用来处理null的,不过guava的是抽象类,其实现类为Absent和Present,而java.util的是final类。其中一部分方法名是相同的。

Guava用Optional表示可能为null的T类型引用。一个Optional实例可能包含非null的引用(我们称之为引用存在),也可能什么也不包括(称之为引用缺失)。它从不说包含的是null值,而是用存在或缺失来表示。但Optional从不会包含null值引用。


public class OptionalDemo {public static void main(String[] args) {Integer value1=null;Integer value2=10;/*创建指定引用的Optional实例,若引用为null则快速失败返回absent()absent()创建引用缺失的Optional实例*/Optional<Integer> a=Optional.fromNullable(value1);Optional<Integer> b=Optional.of(value2); //返回包含给定的非空引用Optional实例System.out.println(sum(a,b));}private static Integer sum(Optional<Integer> a,Optional<Integer> b){//isPresent():如果Optional包含非null的引用(引用存在),返回trueSystem.out.println("First param is present: "+a.isPresent());System.out.println("Second param is present: "+b.isPresent());Integer value1=a.or(0);  //返回Optional所包含的引用,若引用缺失,返回指定的值Integer value2=b.get(); //返回所包含的实例,它必须存在,通常在调用该方法时会调用isPresent()判断是否为nullreturn value1+value2;}
}

Preconditions

前置条件Preconditions提供静态方法来检查方法或构造函数,被调用是否给定适当的参数。它检查的先决条件。其方法失败抛出IllegalArgumentException。


public class PreconditionsDemo {public static void main(String[] args) {try {getValue(5);} catch (IndexOutOfBoundsException e){System.out.println(e.getMessage());}try {sum(4,null);} catch (NullPointerException e){System.out.println(e.getMessage());}try {sqrt(-1);} catch (IllegalArgumentException e){System.out.println(e.getMessage());}}private static double sqrt(double input){Preconditions.checkArgument(input>0.0,"Illegal Argument passed: Negative value %s.",input);return Math.sqrt(input);}private static int sum(Integer a,Integer b){a=Preconditions.checkNotNull(a,"Illegal Argument passed: First parameter is Null.");b=Preconditions.checkNotNull(b,"Illegal Argument passed: First parameter is Null.");return a+b;}private static int getValue(int input){int[] data={1,2,3,4,5};int index=Preconditions.checkElementIndex(input,data.length,"Illegal Argument passed: Invalid index.");return data[index];}
}

Joiner

Joiner 提供了各种方法来处理字符串加入操作,对象等。

Joiner的实例不可变的,因此是线程安全的。

Warning: joiner instances are always immutable; a configuration method such as { useForNull} has no effect on the instance it is invoked on! You must store and use the new joiner instance returned by the method. This makes joiners thread-safe, and safe to store as {@code static final} constants.

   {@code // Bad! Do not do this! Joiner joiner = Joiner.on(‘,’); joiner.skipNulls(); // does nothing!分开写跳过null就不起作用了,因为实例不可改变 return joiner.join(“wrong”, null, “wrong”);}

public class JoinerDemo {public static void main(String[] args) {/*on:制定拼接符号,如:test1-test2-test3 中的 “-“ 符号skipNulls():忽略NULL,返回一个新的Joiner实例useForNull(“Hello”):NULL的地方都用字符串”Hello”来代替*/StringBuilder sb=new StringBuilder();Joiner.on(",").skipNulls().appendTo(sb,"Hello","guava");System.out.println(sb);System.out.println(Joiner.on(",").useForNull("none").join(1,null,3));System.out.println(Joiner.on(",").skipNulls().join(Arrays.asList(1,2,3,4,null,6)));Map<String,String>map=new HashMap<>();map.put("key1","value1");map.put("key2","value2");map.put("key3","value3");System.out.println(Joiner.on(",").withKeyValueSeparator("=").join(map));}
}

Splitter

Splitter 能够将一个字符串按照指定的分隔符拆分成可迭代遍历的字符串集合,Iterable


public class SplitterDemo {public static void main(String[] args) {/*on():指定分隔符来分割字符串limit():当分割的子字符串达到了limit个时则停止分割fixedLength():根据长度来拆分字符串trimResults():去掉子串中的空格omitEmptyStrings():去掉空的子串withKeyValueSeparator():要分割的字符串中key和value间的分隔符,分割后的子串中key和value间的分隔符默认是=*/System.out.println(Splitter.on(",").limit(3).trimResults().split(" a,  b,  c,  d"));//[ a, b, c,d]System.out.println(Splitter.fixedLength(3).split("1 2 3"));//[1 2,  3]System.out.println(Splitter.on(" ").omitEmptyStrings().splitToList("1  2 3"));System.out.println(Splitter.on(",").omitEmptyStrings().split("1,,,,2,,,3"));//[1, 2, 3]System.out.println(Splitter.on(" ").trimResults().split("1 2 3")); //[1, 2, 3],默认的连接符是,System.out.println(Splitter.on(";").withKeyValueSeparator(":").split("a:1;b:2;c:3"));//{a=1, b=2, c=3}}
}

Objects

java7及以后的版本建议使用jdk中的Objects类

EventBus

Guava为我们提供了事件总线EventBus库,它是事件发布-订阅模式的实现,让我们能在领域驱动设计(DDD)中以事件的弱引用本质对我们的模块和领域边界很好的解耦设计。

Guava为我们提供了同步事件EventBus和异步实现AsyncEventBus两个事件总线,他们都不是单例的。

Guava发布的事件默认不会处理线程安全的,但我们可以标注@AllowConcurrentEvents来保证其线程安全

如果Listener A监听Event A, 而Event A有一个子类Event B, 此时Listener A将同时接收Event A和B消息

事件


//Guava 发布-订阅模式中传递的事件,是一个普通的POJO类
public class OrderEvent {  //事件private String message;public OrderEvent(String message) {this.message = message;}public String getMessage() {return message;}
}

订阅


public class EventListener { //订阅者//@Subscribe保证有且只有一个输入参数,如果你需要订阅某种类型的消息,只需要在指定的方法上加上@Subscribe注解即可@Subscribepublic void listen(OrderEvent event){System.out.println("receive message: "+event.getMessage());}/*一个subscriber也可以同时订阅多个事件Guava会通过事件类型来和订阅方法的形参来决定到底调用subscriber的哪个订阅方法*/@Subscribepublic void listen(String message){System.out.println("receive message: "+message);}
}

多个订阅者


public class MultiEventListener {@Subscribepublic void listen(OrderEvent event){System.out.println("receive msg: "+event.getMessage());}@Subscribepublic void listen(String message){System.out.println("receive msg: "+message);}
}

public class EventBusDemo {public static void main(String[] args) {EventBus eventBus=new EventBus("jack");/*如果多个subscriber订阅了同一个事件,那么每个subscriber都将收到事件通知并且收到事件通知的顺序跟注册的顺序保持一致*/eventBus.register(new EventListener()); //注册订阅者eventBus.register(new MultiEventListener());eventBus.post(new OrderEvent("hello")); //发布事件eventBus.post(new OrderEvent("world"));eventBus.post("!");}
}

DeadEvent

如果EventBus发送的消息都不是订阅者关心的称之为Dead Event。


public class DeadEventListener {boolean isDelivered=true;@Subscribepublic void listen(DeadEvent event){isDelivered=false;System.out.println(event.getSource().getClass()+"  "+event.getEvent()); //source通常是EventBus}public boolean isDelivered() {return isDelivered;}
}

Collection

不可变集合

不可变对象有很多优点,包括:

  • 当对象被不可信的库调用时,不可变形式是安全的;
  • 不可变对象被多个线程调用时,不存在竞态条件问题
  • 不可变集合不需要考虑变化,因此可以节省时间和空间。所有不可变的集合都比它们的可变形式有更好的内存利用率(分析和测试细节);

  • 不可变对象因为有固定不变,可以作为常量来安全使用。

JDK也提供了Collections.unmodifiableXXX方法把集合包装为不可变形式,但:

  • 笨重而且累赘:不能舒适地用在所有想做防御性拷贝的场景;

  • 不安全:要保证没人通过原集合的引用进行修改,返回的集合才是事实上不可变的;

  • 低效:包装过的集合仍然保有可变集合的开销,比如并发修改的检查、散列表的额外空间,等等。

创建不可变集合方法:

  • copyOf方法,如ImmutableSet.copyOf(set);

  • of方法,如ImmutableSet.of(“a”, “b”, “c”)或 ImmutableMap.of(“a”, 1, “b”, 2);

  • Builder工具


public class ImmutableDemo {public static void main(String[] args) {ImmutableSet<String> set=ImmutableSet.of("a","b","c","d");ImmutableSet<String> set1=ImmutableSet.copyOf(set);ImmutableSet<String> set2=ImmutableSet.<String>builder().addAll(set).add("e").build();System.out.println(set);ImmutableList<String> list=set.asList();}
}

新型集合类

Multiset

Multiset可统计一个词在文档中出现了多少次


public class MultiSetDemo {public static void main(String[] args) {Multiset<String> set=LinkedHashMultiset.create();set.add("a");set.add("a");set.add("a");set.add("a");set.setCount("a",5); //添加或删除指定元素使其在集合中的数量是countSystem.out.println(set.count("a")); //给定元素在Multiset中的计数System.out.println(set);System.out.println(set.size()); //所有元素计数的总和,包括重复元素System.out.println(set.elementSet().size()); //所有元素计数的总和,不包括重复元素set.clear(); //清空集合System.out.println(set);}
}

Multimap

Multimap可以很容易地把一个键映射到多个值。换句话说,Multimap是把键映射到任意多个值的一般方式。


public class MultiMapDemo {public static void main(String[] args) {Multimap<String,Integer> map= HashMultimap.create(); //Multimap是把键映射到任意多个值的一般方式map.put("a",1); //key相同时不会覆盖原valuemap.put("a",2);map.put("a",3);System.out.println(map); //{a=[1, 2, 3]}System.out.println(map.get("a")); //返回的是集合System.out.println(map.size()); //返回所有”键-单个值映射”的个数,而非不同键的个数System.out.println(map.keySet().size()); //返回不同key的个数Map<String,Collection<Integer>> mapView=map.asMap();}
}

BiMap

BiMap


public class BitMapDemo {public static void main(String[] args) {BiMap<String,String> biMap= HashBiMap.create();biMap.put("sina","sina.com");biMap.put("qq","qq.com");biMap.put("sina","sina.cn"); //会覆盖原来的value/*在BiMap中,如果你想把键映射到已经存在的值,会抛出IllegalArgumentException异常如果对特定值,你想要强制替换它的键,请使用 BiMap.forcePut(key, value)*/biMap.put("tecent","qq.com"); //抛出异常biMap.forcePut("tecent","qq.com"); //强制替换keySystem.out.println(biMap);System.out.println(biMap.inverse().get("sina.com")); //通过value找keySystem.out.println(biMap.inverse().inverse()==biMap); //true}
}

Table

Table它有两个支持所有类型的键:”行”和”列”。


public class TableDemo {public static void main(String[] args) {//记录学生在某门课上的成绩Table<String,String,Integer> table= HashBasedTable.create();table.put("jack","java",100);table.put("jack","c",90);table.put("mike","java",93);table.put("mike","c",100);Set<Table.Cell<String,String,Integer>> cells=table.cellSet();for (Table.Cell<String,String,Integer> cell : cells) {System.out.println(cell.getRowKey()+" "+cell.getColumnKey()+" "+cell.getValue());}System.out.println(table.row("jack"));System.out.println(table);System.out.println(table.rowKeySet());System.out.println(table.columnKeySet());System.out.println(table.values());}
}

Collections2

filter():只保留集合中满足特定要求的元素


public class FilterDemo {public static void main(String[] args) {List<String> list= Lists.newArrayList("moon","dad","refer","son");Collection<String> palindromeList= Collections2.filter(list, input -> {return new StringBuilder(input).reverse().toString().equals(input); //找回文串});System.out.println(palindromeList);}
}

transform():类型转换


public class TransformDemo {public static void main(String[] args) {Set<Long> times= Sets.newHashSet();times.add(91299990701L);times.add(9320001010L);times.add(9920170621L);Collection<String> timeStrCol= Collections2.transform(times, new Function<Long, String>() {@Nullable@Overridepublic String apply(@Nullable Long input) {return new SimpleDateFormat("yyyy-MM-dd").format(input);}});System.out.println(timeStrCol);}
}

多个Function组合


public class TransformDemo {public static void main(String[] args) {List<String> list= Lists.newArrayList("abcde","good","happiness");//确保容器中的字符串长度不超过5Function<String,String> f1=new Function<String, String>() {@Nullable@Overridepublic String apply(@Nullable String input) {return input.length()>5?input.substring(0,5):input;}};//转成大写Function<String,String> f2=new Function<String, String>() {@Nullable@Overridepublic String apply(@Nullable String input) {return input.toUpperCase();}};Function<String,String> function=Functions.compose(f1,f2);Collection<String> results=Collections2.transform(list,function);System.out.println(results);}
}

集合操作:交集、差集、并集


public class CollectionsDemo {public static void main(String[] args) {Set<Integer> set1= Sets.newHashSet(1,2,3,4,5);Set<Integer> set2=Sets.newHashSet(3,4,5,6);Sets.SetView<Integer> inter=Sets.intersection(set1,set2); //交集System.out.println(inter);Sets.SetView<Integer> diff=Sets.difference(set1,set2); //差集,在A中不在B中System.out.println(diff);Sets.SetView<Integer> union=Sets.union(set1,set2); //并集System.out.println(union);}
}

Cache

缓存在很多场景下都是相当有用的。例如,计算或检索一个值的代价很高,并且对同样的输入需要不止一次获取值的时候,就应当考虑使用缓存。

Guava Cache与ConcurrentMap很相似,但也不完全一样。最基本的区别是ConcurrentMap会一直保存所有添加的元素,直到显式地移除。相对地,Guava Cache为了限制内存占用,通常都设定为自动回收元素。在某些场景下,尽管LoadingCache 不回收元素,它也是很有用的,因为它会自动加载缓存。

Guava Cache是一个全内存的本地缓存实现,它提供了线程安全的实现机制。

通常来说,Guava Cache适用于:

  • 你愿意消耗一些内存空间来提升速度。

  • 你预料到某些键会被查询一次以上。

  • 缓存中存放的数据总量不会超出内存容量。(Guava Cache是单个应用运行时的本地缓存。它不把数据存放到文件或外部服务器。

如果这不符合你的需求,请尝试Memcached这类工具)

Guava Cache有两种创建方式:

  • cacheLoader
  • callable callback

LoadingCache是附带CacheLoader构建而成的缓存实现


public class LoadingCacheDemo {public static void main(String[] args) {LoadingCache<String,String> cache= CacheBuilder.newBuilder().maximumSize(100) //最大缓存数目.expireAfterAccess(1, TimeUnit.SECONDS) //缓存1秒后过期.build(new CacheLoader<String, String>() {@Overridepublic String load(String key) throws Exception {return key;}});cache.put("j","java");cache.put("c","cpp");cache.put("s","scala");cache.put("g","go");try {System.out.println(cache.get("j"));TimeUnit.SECONDS.sleep(2);System.out.println(cache.get("s")); //输出s} catch (ExecutionException | InterruptedException e) {e.printStackTrace();}}
}

public class CallbackDemo {public static void main(String[] args) {Cache<String,String> cache= CacheBuilder.newBuilder().maximumSize(100).expireAfterAccess(1, TimeUnit.SECONDS).build();try {String result=cache.get("java", () -> "hello java");System.out.println(result);} catch (ExecutionException e) {e.printStackTrace();}}
}

refresh机制:
- LoadingCache.refresh(K) 在生成新的value的时候,旧的value依然会被使用。
- CacheLoader.reload(K, V) 生成新的value过程中允许使用旧的value
- CacheBuilder.refreshAfterWrite(long, TimeUnit) 自动刷新cache

并发

ListenableFuture

传统JDK中的Future通过异步的方式计算返回结果:在多线程运算中可能或者可能在没有结束返回结果,Future是运行中的多线程的一个引用句柄,确保在服务执行返回一个Result。

ListenableFuture可以允许你注册回调方法(callbacks),在运算(多线程执行)完成的时候进行调用, 或者在运算(多线程执行)完成后立即执行。这样简单的改进,使得可以明显的支持更多的操作,这样的功能在JDK concurrent中的Future是不支持的。


public class ListenableFutureDemo {public static void main(String[] args) {//将ExecutorService装饰成ListeningExecutorServiceListeningExecutorService service= MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());//通过异步的方式计算返回结果ListenableFuture<String> future=service.submit(() -> {System.out.println("call execute..");return "task success!";});//有两种方法可以执行此Future并执行Future完成之后的回调函数future.addListener(() -> {  //该方法会在多线程运算完的时候,指定的Runnable参数传入的对象会被指定的Executor执行try {System.out.println("result: "+future.get());} catch (InterruptedException | ExecutionException e) {e.printStackTrace();}},service);Futures.addCallback(future, new FutureCallback<String>() {@Overridepublic void onSuccess(@Nullable String result) {System.out.println("callback result: "+result);}@Overridepublic void onFailure(Throwable t) {System.out.println(t.getMessage());}},service);}
}

IO


public class FileDemo {public static void main(String[] args) {File file=new File(System.getProperty("user.dir"));}//写文件private void writeFile(String content,File file) throws IOException {if (!file.exists()){file.createNewFile();}Files.write(content.getBytes(Charsets.UTF_8),file);}//读文件private List<String> readFile(File file) throws IOException {if (!file.exists()){return ImmutableList.of(); //避免返回null}return Files.readLines(file,Charsets.UTF_8);}//文件复制private void copyFile(File from,File to) throws IOException {if (!from.exists()){return;}if (!to.exists()){to.createNewFile();}Files.copy(from,to);}}

Google Guava官方教程(中文版)
guava-importnew

Google的Guava开发库快速快速入门相关推荐

  1. 30款Linux 高性能网络开发库开源软件

    转载至:https://blog.csdn.net/lifan_3a/article/details/38410081 Lua的epoll模块 lua-epoll Lua的epoll模块 更多细节,请 ...

  2. GUI 图片显示(SDL 多媒体开发库)——基于 rt-smart 微内核操作系统

    目录 SDL 跨平台多媒体开发库简介 快速体验 rt-smart:GUI SDL SDL GUI 开发环境搭建及演示 硬件环境搭建 软件环境搭建 1.下载 AR-Pi Smart SDK 2.下载和安 ...

  3. springmvc+activiti 完美整合- 流程在线设计+代码生成器+UI快速开发库,提高一半的开发效率

    JEECG(J2EE Code Generation) 是一款基于代码生成器的智能开发平台,采用代码生成+手工MERGE半智能开发模式, 可以帮助解决Java项目60%的重复工作,让开发更多关注业务逻 ...

  4. JEECG V3.0版本 (工作流在线定义+UI快速开发库+代码生成器) 全新架构技术,漂亮的界面+智能代码生成+智能工作流

    简要说明 JEECG V3.0版本推翻原有SSH2架构,采用SpringMVC+Hibernate+Spring jdbc基础架构, 采用面向声明的开发模式,基于泛型方式编写极少代码即可实现复杂的数据 ...

  5. JEECG V3.0 版本(jbpm5 工作流自定义+WEB UI快速开发库+代码生成器) spring mvc +hibernate

    简要说明 JEECG V3.0版本推翻了原有SSH2架构,采用SpringMVC+Hibernate+Spring jdbc基础架构, 采用面向声明的开发模式,基于泛型方式编写极少代码即可实现复杂的数 ...

  6. Python快速编程入门#学习笔记02# |第十章 :Python计算生态与常用库(附.小猴子接香蕉、双人乒乓球小游戏源码)

    全文目录 学习目标 1. Python计算生态概述 1.1 Python计算生态概述 2. Python生态库的构建与发布 2.1 模块的构建与使用 * 2.1.1第三方库/模块导入的格式 2.2 包 ...

  7. Android 开源热库汇总(二):快速开发库

    Android 开源热库汇总(一):基本库 Android 开源热库汇总(二):快速开发库 1.常用控件 PhotoView 一款ImageView展示框架,支持缩放,响应手势 https://git ...

  8. Python快速编程入门#学习笔记01# |第一章 :Python基础知识 (Python发展历程、常见的开发工具、import模块导入)

    全文目录 ==先导知识== 1 认识Python 1.1.1 Python的发展历程 1.1.2 Python语言的特点 2. Python解释器的安装与Python程序运行 1.2.1 安装Pyth ...

  9. HTML5+app开发学习之快速入门篇

    HTML5+app开发学习之快速入门篇 5+app开发概念理解相关 开发环境与支持 快速入门实战 5+app开发概念理解相关 见博文:学习跨平台移动应用开发必须理解的一些概念 开发环境与支持 开发环境 ...

  10. 开源纯C日志函数库iLOG3快速入门(八、如果你喜欢简单日志函数甚于日志函数库)...

    2019独角兽企业重金招聘Python工程师标准>>> 开源纯C日志函数库iLOG3快速入门(八.如果你喜欢简单日志函数甚于日志函数库) 很多网友来信坚持表达了在项目中应使用简单日志 ...

最新文章

  1. 什么是以太坊?它到底怎么运作的?
  2. python全栈工程师薪水_不止 20K,Python 工程师薪资再飙升(内附转型指南)
  3. windows下使用git管理github项目
  4. 别不承认!搞懂那些数理原理,才发现它们和枯燥根本不沾边!
  5. 网站架构之缓存应用(摘录)
  6. Oracle视图添加约束,Oracle创建视图的语法
  7. 有弹性的 net/http 服务
  8. Linux基础——怎么样从手机 (Android安卓/IOS苹果) 通过 SSH 远程 Linux
  9. grep 两个字符串_Linux运维工程师想要的12个grep指令
  10. 不会用Camtasia的“库”,你可能错过了一个亿
  11. kill mysql 进程_如何快速处理mysql连接数占满的问题?
  12. Excel-舒尔特方格(专注力训练)
  13. MOOC 课后讨论5.2 判别是否是前缀码的算法
  14. 南丁格尔图文字颜色跟随
  15. java日期计算天数_Java 两个日期间的天数计算
  16. 鸢尾花数据集的线性多分类
  17. 市场模式缭乱,合适的模式脱颖而出?众筹卖货模式在线分享分析
  18. 离散数学(一):命题及命题联结词
  19. MySQL批量修改表的编码和字符集
  20. libyuv的编译与使用

热门文章

  1. html5中的web worker的用法
  2. 黑客语言Python
  3. Codeforces 1032F Vasya and Maximum Matching dp
  4. Luogu P5008 逛庭院
  5. 百度ocr文字识别接口使用
  6. 内置模块(time、random、hashlib、os)
  7. 1051: [HAOI2006]受欢迎的牛 (tarjan强连通分量+缩点)
  8. Atitit 发帖机系列(8)  词法分析器v5 版本新特性说明)
  9. 数据结构 树的遍历(递归遍历练习)
  10. 很好的c++和Python混合编程文章