一、maven坐标
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
二、MoreExecutors.listeningDecorator()
测试代码
public static void main(String[] args) throws ExecutionException, InterruptedException {
long start = System.currentTimeMillis();
ListeningExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
ListenableFuture<Integer> listenableFuture = executorService.submit(()->getInteger1() );
ListenableFuture<Integer> listenableFuture1 = executorService.submit(()->getInteger2() );
ListenableFuture<Integer> listenableFuture2 = executorService.submit(()->getInteger3() );
System.out.println("线程一:"+String.valueOf(listenableFuture.get()));
System.out.println("线程二:"+String.valueOf(listenableFuture1.get()));
System.out.println("线程三:"+String.valueOf(listenableFuture2.get()));
System.out.println("总耗时:"+(System.currentTimeMillis()-start));
}
public static Integer getInteger1() throws Exception {
System.out.println("call execute..");
TimeUnit.SECONDS.sleep(1);
return 7;
}
public static Integer getInteger2() throws Exception {
System.out.println("call execute..");
TimeUnit.SECONDS.sleep(2);
return 8;
}
public static Integer getInteger3() throws Exception {
System.out.println("call execute..");
TimeUnit.SECONDS.sleep(3);
return 9;
}
输出
结果
从测试代码和输出可以看出,MoreExecutors.listeningDecorator()是多线程并行的,但是会阻塞到主线程。很想我们jdk7提供的fork/join多线程框架。
String
1.Strings.padEnd方法
//padEnd普全右
String a="12345";
String b=Strings.padEnd(a, 10, 'x');
System.out.println(b);
结果为:12345xxxxx
2.Strings.padStart方法
//padStart 普全左
String a="12345";
String b=Strings.padStart(a, 10, 'x');
System.out.println(b);
结果为:xxxxx12345
3.Strings.isNullOrEmpty 方法
//Strings.isNullOrEmpty 校验空值
String a="";
boolean b=Strings.isNullOrEmpty(a);
System.out.println(b);
结果为:true
4.Strings.nullToEmpty 方法
//Strings.nullToEmpty 如果为null 转为""
String a=null;
String b=Strings.nullToEmpty(a);
System.out.println(b);
结果为:
5.Strings.emptyToNull 方法
//Strings.emptyToNull 如果为"" 转为null
String a="";
String b=Strings.emptyToNull(a);
System.out.println(b);
结果为:null
6.Strings.repeat 方法
//Strings.repeat 重复字符串
String a="123";
String b=Strings.repeat(a, 3);
System.out.println(b);
结果为:123123123
7.Strings.commonPrefix 方法
//Strings.commonPrefix 获取a,b左公共部分字符串
String a="abcdsfsfs";
String b="abc3sfsd";
String c=Strings.commonPrefix(a, b);
System.out.println(c);
结果为:abc
8.Strings.commonSuffix 方法
//Strings.commonSuffix 获取a,b右公共部分字符串
String a="faaxyz";
String b="fwefxyz";
String c=Strings.commonSuffix(a, b);
System.out.println(c);
System.out.println(c);
结果为:xyz
三,Joiner 连接工具类
分析源码可知:该类构造方法被private修身,无法直接通过new实现
通过调用on传如分隔符来得到实例。
1.连接List列表
Joiner joiner = Joiner.on(",");
List<String> list =new ArrayList<String>();
list.add("xiaoming");
list.add("xiaohong");
list.add("wangsan");
System.out.println(joiner.join(list));
结果:xiaoming,xiaohong,wangsan
2.连接Iterator列表
Joiner joiner = Joiner.on(",");
List<String> list =new ArrayList<String>();
list.add("xiaoming");
list.add("xiaohong");
list.add("wangsan");
Iterator<String> it=list.iterator();
System.out.println(joiner.join(it));
结果:xiaoming,xiaohong,wangsan
3.连接多个字符串
Joiner joiner = Joiner.on(",");
System.out.println(joiner.join("123","345","56","43"));
结果:123,345,56,43
4.连接字符串与列表
Joiner joiner = Joiner.on(",");
List<String> list =new ArrayList<String>();
list.add("xiaoming");
list.add("xiaohong");
list.add("wangsan");
StringBuilder builder=new StringBuilder("标题");
System.out.println(joiner.appendTo(builder,list));
结果:标题xiaoming,xiaohong,wangsan
5.跳过null值连接
“`
Joiner joiner = Joiner.on(“,”).skipNulls();
List list =new ArrayList();
list.add(“xiaoming”);
list.add(null);
list.add(“wangsan”);
StringBuilder builder=new StringBuilder(“标题”);
###6.替换null值进行连接
Joiner joiner = Joiner.on(",").useForNull("123");//替换null为123
List<String> list =new ArrayList<String>();
list.add("xiaoming");
list.add(null);
list.add("wangsan");
StringBuilder builder=new StringBuilder("标题");
System.out.println(joiner.appendTo(builder,list));
“`
结果:标题xiaoming,123,wangsan
四.Splitter 工具类
主要功能是拆分字符串为集合 Map等。
通过分析源码可知,该工具类同意通过 on函数传入拆分字符得到实例。
1.拆分字符串为List集合
Splitter splitter =Splitter.on(",");
String str="a,b,c,d,e,f,g";
List<String> list=splitter.splitToList(str);
System.out.println(list);
结果:[a, b, c, d, e, f, g]
2.忽略空字符
Splitter splitter =Splitter.on(",").omitEmptyStrings();
String str="a,b,c,d,,f,g";
List<String> list=splitter.splitToList(str);
System.out.println(list);
结果:[a, b, c, d, f, g]
3.忽略空字符且去除字符串前后空格
Splitter splitter =Splitter.on(",").omitEmptyStrings().trimResults();
String str="a,b,c,d,,f, g ";
List<String> list=splitter.splitToList(str);
System.out.println(list);
结果:[a, b, c, d, f, g]
五、 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];
}
}
六、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注解即可
@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);
}
}
多个订阅者
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);
}
}
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;
@Subscribe
public void listen(DeadEvent event){
isDelivered=false;
System.out.println(event.getSource().getClass()+" "+event.getEvent()); //source通常是EventBus
}
public boolean isDelivered() {
return isDelivered;
}
}