getting started with google guava 笔记
guava 包的一些常用集合操作
- List 转 Map
- Key 关联多个 Value 的 Map 结构
- Key-Value 互转
- 多线程并发阻塞
- 多线程异步回调 CompleteFuture vs Guava 异步回调
List 转 Map
Book book1 = new Book("isbn-1", "深入理解jvm");
Book book2 = new Book("isbn-2", "算法导论");
List<Book> bookList = Lists.newArrayList(book1, book2);
//方式一: java 8 lambda
// Map<String, Book> bookMap = bookList.stream().collect(Collectors.toMap(Book::getIsbn, Function.identity()));
//方式二: guava Maps 工具类
Map<String,Book> bookMap1 = Maps.uniqueIndex(bookList.iterator(), new Function<Book, String>() {
@Nullable
@Override
public String apply(@Nullable Book input) {
return input.getIsbn();
}
});
key 关联多个 value。value之间去重/不去重
//一个 key 关联多个value
ArrayListMultimap<Integer, String> map = ArrayListMultimap.create();
map.put(1, "a");
map.put(1, "aa");
map.put(1, "aa");
//{1=[a, aa, aa]}
System.out.println(map);
//一个 key 关联多个value,value之间可去重
HashMultimap<Integer, String> hashMultimap = HashMultimap.create();
hashMultimap.put(1, "a");
hashMultimap.put(1, "aa");
hashMultimap.put(1, "aa");
//{1=[aa, a]}
System.out.println(hashMultimap);
键值相互映射
- inverse 方法将 key-->value 转换成 value-->key
- 当 put 的 value 相同时,forcePut 方法强制更新key
//键值相互映射: key-->value && value-->key
BiMap<Integer, String> biMap = HashBiMap.create();
biMap.put(1, "a");
biMap.put(2, "b");
//"a"
System.out.println(biMap.get(1));
//"b"
System.out.println(biMap.get(2));
BiMap<String, Integer> inverseMap = biMap.inverse();
//1
System.out.println(inverseMap.get("a"));
//2
System.out.println(inverseMap.get("b"));
BiMap<Integer, String> forceBiMap = HashBiMap.create();
//强制覆盖value
forceBiMap.put(1, "a");
//抛出 IllegalArgumentException
// forceBiMap.put(2, "a");
//success, value 相同时, 将 key 从 1 更新为 2
forceBiMap.forcePut(2, "a");
//false
System.out.println(forceBiMap.containsKey(1));
//true
System.out.println(forceBiMap.containsKey(2));
并发
阻塞获取结果
public static void main(String[] args) {
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
Future<String> future = cachedThreadPool.submit(new Callable<String>() {
@Override
public String call() throws Exception {
//在 cachedThreadPool 中 '异步'执行
return "result";
}
});
//主线程阻塞获得结果
future.get();
}
CompletableFuture 阻塞获取结果
public static void main(String[] args) {
CompletableFuture<String> future = CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
return "result";//使用 forkjoin common pool 线程池执行
}
});
future.get();
//主线程继续执行其他逻辑...
}
guava 异步回调
- 在 executorService 中提交 callable 任务,返回 listenableFuture 对象
- listenableFuture 对象添加监听器(回调逻辑),当 listenableFuture 执行完成时,触发回调逻辑的执行。
- 此回调逻辑是个 Runnable 任务,无法获取 callable 任务的执行结果(无法基于 callable 任务的执行结果做一些处理)
- 若需要基于 callable 任务的执行结果做一些处理,可使用:FutureCallback
public class CallBackTest {
public static void main(String[] args) {
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
ListeningExecutorService executorService = MoreExecutors.listeningDecorator(cachedThreadPool);
ListenableFuture<String> listenableFuture = executorService.submit(new Callable<String>() {
@Override
public String call() throws Exception {
System.out.println("start to execute in " + Thread.currentThread().getName());
//模拟执行2秒钟
sleep(2000);
System.out.println("execute finished in " + Thread.currentThread().getName());
return "result";//callable 任务的执行结果
}
});
listenableFuture.addListener(new Runnable() {
@Override
public void run() {
//
System.out.println("listenableFuture 执行完成后, 执行此回调逻辑");
}
}, executorService);
//主线程继续执行其他逻辑...
}
private static void sleep(long mills) {
try {
TimeUnit.MILLISECONDS.sleep(mills);
} catch (Exception e) {
}
}
}
异步回调处理 callable 结果
基于 guava 的 FutureCallback 来处理 callable 任务的执行结果。
public static void main(String[] args) {
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
ListeningExecutorService executorService = MoreExecutors.listeningDecorator(cachedThreadPool);
ListenableFuture<String> listenableFuture = executorService.submit(new Callable<String>() {
@Override
public String call() throws Exception {
System.out.println("start to execute in " + Thread.currentThread().getName());
//模拟执行2秒钟
sleep(2000);
System.out.println("execute finished in " + Thread.currentThread().getName());
// Integer.valueOf("模拟异常");
return "result";//callable 任务的执行结果
}
});
Futures.addCallback(listenableFuture, new FutureCallback<String>() {
@Override
public void onSuccess(@Nullable String result) {
System.out.println("callable 任务执行成功, 执行结果是: " + result);
}
@Override
public void onFailure(Throwable t) {
System.out.println("callable 任务执行失败, 错误原因是: " + t.getMessage());
}
});
//主线程继续执行其他逻辑...
}
JDK 原生异步回调
- CompletableFuture.supplyAsync 执行一个异步任务(ForkJoinPool.commonPool线程池)
- future.thenApply 添加回调逻辑,当异步任务执行完成时,执行回调逻辑,可在回调逻辑中处理异步任务的执行结果
public static void main(String[] args) throws Exception{
CompletableFuture<String> future = CompletableFuture.supplyAsync(new Supplier<String>() {
@Override
public String get() {
System.out.println("start to run async task in " + Thread.currentThread().getName());
sleep(2000);
System.out.println("finished run async task in " + Thread.currentThread().getName());
return "result";
}
});
future.thenApply(result -> {
String processCallableResult = "process " + result;
System.out.println(processCallableResult);
return processCallableResult;
});
//主线程继续执行其他逻辑...
CompletableFuture 的强大之处
- 多个异步任务之间可编排