前言
Guava 是 Google 的一个开源项目,包含许多 Google 核心 Java 常用库,如:集合 [collections] 、缓存 [caching] 、原生类型支持 [primitives support] 、并发库 [concurrency libraries] 、通用注解 [common annotations] 、字符串处理 [string processing] 与 I/O 等。
Maven依赖
<guava.version>19.0</guava.version>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
Guava 集合示例
package com.clinicalresearch.core.utils.Cache;
import com.google.common.base.*;
import com.google.common.base.Optional;
import com.google.common.cache.*;
import com.google.common.collect.*;
import org.apache.commons.lang.StringUtils;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* 简单好用的java缓存框架guava
* Guava Cache与ConcurrentMap很相似,但也不完全一样。最基本的区别是ConcurrentMap会一直保存所有添加的元素,直到显式地移除。
* 相对地,Guava Cache为了限制内存占用,通常都设定为自动回收元素。在某些场景下,尽管LoadingCache 不回收元素,它也是很有用的,因为它会自动加载缓存。
Guava Cache是一个全内存的本地缓存实现,它提供了线程安全的实现机制。
通常来说,Guava Cache适用于:
你愿意消耗一些内存空间来提升速度。
你预料到某些键会被查询一次以上。
缓存中存放的数据总量不会超出内存容量。(Guava Cache是单个应用运行时的本地缓存。它不把数据存放到文件或外部服务器。
* Created by liangguannan on 2019/7/11.
*/
public class GuavaCacheUtils {
private GuavaCacheUtils() {
}
public static LoadingCache<String,Object> LoadingCache() {
LoadingCache<String,Object> cache= CacheBuilder.newBuilder()
.maximumSize(100) //最大缓存数目
.expireAfterAccess(10, TimeUnit.MINUTES) //缓存1分钟后过期
.build(new CacheLoader<String, Object>() {
@Override
public String load(String key) throws Exception {
return key;
}
});
return cache;
}
/* public static Cache Callback() {
try {
LoadingCache<String, String> cache = CacheBuilder.newBuilder()
.maximumSize(1000)
.expireAfterAccess(30L, TimeUnit.MILLISECONDS)
.build(createCacheLoader());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static com.google.common.cache.CacheLoader<String, String> createCacheLoader() {
return new com.google.common.cache.CacheLoader<String, String>() {
@Override
public Employee load(String key) throws Exception {
log.info("加载创建key:" + key);
return new Employee(key, key + "dept", key + "id");
}
};
}*/
/* static {
cache = CacheBuilder.newBuilder().maximumSize(10000)
.expireAfterWrite(24, TimeUnit.HOURS)
.initialCapacity(10)
.removalListener(new RemovalListener<String, Object>() {
@Override
public void onRemoval(RemovalNotification<String, Object> rn) {
System.out.println("被移除缓存{}:{}" +rn.getKey() +"---rn.getValue()"+rn.getValue());
}
}).build();
}*/
public static LoadingCache<String,Object> cache=LoadingCache();
/**
* @desction: 获取缓存
* @author: liangguannan
* @date: 2017/11/22 9:50
*/
public static Object get(String key){
return StringUtils.isNotEmpty(key)?cache.getIfPresent(key):null;
}
/**
* @desction: 放入缓存
* @author: liangguannan
* @date: 2017/11/22 9:50
*/
public static void put(String key,Object value){
if(StringUtils.isNotEmpty(key) && value !=null){
cache.put(key,value);
}
}
/**
* @desction: 移除缓存
* @author: liangguannan
* @date: 2017/11/22 9:50
*/
public static void remove(String key){
if(StringUtils.isNotEmpty(key)){
cache.invalidate(key);
}
}
/**
* @desction: 批量删除缓存
* @author: liangguannan
* @date: 2017/11/22 9:49
*/
public static void remove(List<String> keys){
if(keys !=null && keys.size() >0){
cache.invalidateAll(keys);
}
}
/**
* guava的Optional类似于Java 8新增的Optional类,都是用来处理null的,不过guava的是抽象类,其实现类为Absent和Present,而java.util的是final类。其中一部分方法名是相同的。
Guava用Optional表示可能为null的T类型引用。一个Optional实例可能包含非null的引用(我们称之为引用存在),也可能什么也不包括(称之为引用缺失)。
它从不说包含的是null值,而是用存在或缺失来表示。但Optional从不会包含null值引用。
* @param args
*/
public static void Optional(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;
}
/**
* Joiner 提供了各种方法来处理字符串加入操作,对象等。
Joiner的实例不可变的,因此是线程安全的。
* @param args
*/
public static void Joiner(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 能够将一个字符串按照指定的分隔符拆分成可迭代遍历的字符串集合,Iterable
* @param args
*/
public static void Splitter(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}
}
/**
* 不可变集合
* @param args
*/
public static void Immutable(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可统计一个词在文档中出现了多少次
* @param args
*/
public static void MultiSet(String[] args) {
Multiset<String> set= LinkedHashMultiset.create();
set.add("a");
set.add("a");
set.add("a");
set.add("a");
set.setCount("a",5); //添加或删除指定元素使其在集合中的数量是count
System.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是把键映射到任意多个值的一般方式。
* @param args
*/
public static void MultiMap(String[] args) {
Multimap<String,Integer> map= HashMultimap.create(); //Multimap是把键映射到任意多个值的一般方式
map.put("a",1); //key相同时不会覆盖原value
map.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
* @param args
*/
public static void BiMap(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"); //强制替换key
System.out.println(biMap);
System.out.println(biMap.inverse().get("sina.com")); //通过value找key
System.out.println(biMap.inverse().inverse()==biMap); //true
}
/**
* Table
* Table它有两个支持所有类型的键:”行”和”列”。
*/
public static void Table() {
//记录学生在某门课上的成绩
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")+":"+table.column("java"));
System.out.println(table);
System.out.println(table.rowKeySet());
System.out.println(table.columnKeySet());
System.out.println(table.values());
}
static void sortMap(Map<String, String> param) {
TreeMap<String, String> paramTreeMap = new TreeMap<>(param);
System.out.println(paramTreeMap);
}
public static void test() {
Table<String,String,Integer> table= HashBasedTable.create();
System.out.println("-----put start----------");
for (int i=0;i<6000;i++){
for (int j=0;j<500;j++){
table.put("id:"+i,"varibale"+j,i);
}
}
System.out.println("-----put end----------");
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("----- end----------");
}
public static void main(String[] args) throws Exception {
/* 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);*/
TreeMap<String, String> paramHashMap = new TreeMap<>();
paramHashMap.put("7", "s");
paramHashMap.put("2", "ddd");
paramHashMap.put("1", "gg");
paramHashMap.put("3", "gwwg");
paramHashMap.put("4", "vv");
sortMap(paramHashMap);
}
}