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值引用。
import com.google.common.base.Optional; /** * Guava用Optional表示可能为null的T类型引用。 * * @author LENOVO * */ 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的引用(引用存在),返回true System.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()判断是否为null return value1 + value2; } }
运行返回:
First param is present: false Second param is present: true 10
Preconditions
前置条件Preconditions提供静态方法来检查方法或构造函数,被调用是否给定适当的参数。它检查的先决条件。其方法失败抛出IllegalArgumentException。
import com.google.common.base.Preconditions; /**前置条件Preconditions提供静态方法来检查方法或构造函数 * @author LENOVO * */ public class PreconditionDemo { 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: Second 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]; } }
返回:
Illegal Argument passed: Invalid index. (5) must be less than size (5) Illegal Argument passed: Second parameter is Null. Illegal Argument passed: Negative value -1.0.
Joiner
Joiner 提供了各种方法来处理字符串加入操作,对象等。
Joiner的实例不可变的,因此是线程安全的。
import java.util.Arrays; import java.util.HashMap; import java.util.Map; import com.google.common.base.Joiner; /**Joiner 提供了各种方法来处理字符串加入操作,对象等 * @author LENOVO * */ 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)); } }
返回:
Hello,guava 1,none,3 1,2,3,4,6 key1=value1,key2=value2,key3=value3
Splitter
Splitter 能够将一个字符串按照指定的分隔符拆分成可迭代遍历的字符串集合,Iterable
import com.google.common.base.Splitter; /**Splitter 能够将一个字符串按照指定的分隔符拆分成可迭代遍历的字符串集合 * @author LENOVO * */ 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} } }
返回:
[a, b, c, d] [1 2, 3] [1, 2, 3] [1, 2, 3] [1, 2, 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类 * @author LENOVO * */ public class OrderEvent { // 事件 private String message; public OrderEvent(String message) { this.message = message; } public String getMessage() { return message; } }
订阅
import com.google.common.eventbus.Subscribe; public class EventListener { // 订阅者 // @Subscribe保证有且只有一个输入参数,如果你需要订阅某种类型的消息,只需要在指定的方法上加上@Subscribe注解即可 @Subscribe public void listen(OrderEvent event) { System.out.println("receive message: " + event.getMessage()); } /* * 一个subscriber也可以同时订阅多个事件 Guava会通过事件类型来和订阅方法的形参来决定到底调用subscriber的哪个订阅方法 */ @Subscribe public void listen(String message) { System.out.println("receive message: " + message); } }
多个订阅者
import com.google.common.eventbus.Subscribe; public class MultiEventListener { @Subscribe public void listen(OrderEvent event) { System.out.println("receive msg: " + event.getMessage()); } @Subscribe public void listen(String message) { System.out.println("receive msg: " + message); } }
Demo:
import com.google.common.eventbus.EventBus; 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("!");//只有他才会执行所有的事件 } }
返回:
receive message: hello receive msg: hello receive message: world receive msg: world receive message: ! receive msg: !
DeadEvent
如果EventBus发送的消息都不是订阅者关心的称之为Dead Event。
import com.google.common.eventbus.DeadEvent; import com.google.common.eventbus.Subscribe; public class DeadEventListener { boolean isDelivered = true; @Subscribe public void listen(DeadEvent event) { isDelivered = false; System.out.println(event.getSource().getClass() + " " + event.getEvent()); // source通常是EventBus } public boolean isDelivered() { return isDelivered; } }
参考:http://www.importnew.com/tag/guava