Guava工具包含了若干被Google的 Java项目广泛依赖 的核心库,例如:
- 集合 [collections]
- 缓存 [caching]
- 原生类型支持 [primitives support]
- 并发库 [concurrency libraries]
- 通用注解 [common annotations]
- 字符串处理 [string processing]
- I/O 等等
引用
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>26.0</version>
</dependency>
集合:
不可变集合
不可变对象有很多优点,包括:
- 当对象被不可信的库调用时,不可变形式是安全的;
- 不可变对象被多个线程调用时,不存在竞态条件问题
- 不可变集合不需要考虑变化,因此可以节省时间和空间。所有不可变的集合都比它们的可变形式有更好的内存利用率(分析和测试细节);
- 不可变对象因为有固定不变,可以作为常量来安全使用。
JDK也提供了Collections.unmodifiableXXX方法把集合包装为不可变形式,但我们认为不够好:
- 笨重而且累赘:不能舒适地用在所有想做防御性拷贝的场景;
- 不安全:要保证没人通过原集合的引用进行修改,返回的集合才是事实上不可变的;
- 低效:包装过的集合仍然保有可变集合的开销,比如并发修改的检查、散列表的额外空间,等等。
不可变集合的创建:copyof、of、builder方法、asList 视图
新集合类型:
- Multiset:既有ArrayList语义,也有map语义
- SortedMultiset:支持高效获取指定范围的子集
- Multimap:将一个键映射到多个值
- BiMap:实现键值的双向映射
- Table:实现表结构,使用多个值做索引
- ClassToInstanceMap:键是类型,值是符合键所指类型的对象
ClassToInstanceMap<Number> numberDefaults=MutableClassToInstanceMap.create();
numberDefaults.putInstance(Integer.class, Integer.valueOf(0));
- RangeSet:描述一组不相连的、非空的区间。当添加新的区间时,所有相连的区间会被合并,空区间会被忽略
- RangeMap:描述了不相交、非空的区间到特定值的映射。不会合并相邻的映射
Collections中未包含的集合工具:
- Iterables
- FluentIterable
Lists方法:partition、reverse
集合方法:union、intersection、difference、symmetricDifference、cartesianProduct(返回所有笛卡尔积)、powerSet(所有子集)
Maps方法:
- uniqueIndex(有一组对象,在某个属性上分别有独一无二的值,而希望能够按照这个属性值查找对象)
- index(有一组对象,他们有共同的特定属性,希望按照这个属性的值查询对象,但属性值不一定是独一无二的)
- difference、entriesInCommon、entriesDiffering、entriesOnlyOnLeft、entriesOnlyOnRight
- invertFrom(Miltimap 多个键可以映射到同一个值,invertFrom后也可以将值映射到多个键)
- forMap 把Map包装成SetMultimap
Table
transpose 将table表进行转置
集合创建:
// 普通Collection的创建
List<String> list = Lists.newArrayList();
Set<String> set = Sets.newHashSet();
Map<String, String> map = Maps.newHashMap();
// 不变Collection的创建
ImmutableList<String> iList = ImmutableList.of("a", "b", "c");
ImmutableSet<String> iSet = ImmutableSet.of("e1", "e2");
ImmutableMap<String, String> iMap = ImmutableMap.of("k1", "v1", "k2", "v2");
Multiset<String> set1 = HashMultiset.create();
set1.add("a");
set1.add("2");
set1.add("a");
System.out.println("set1 = " + set1.toString());
//计算出现次数
System.out.println("count= " + set1.count("a"));
//key可以重复
Multimap<String, Integer> multimap = ArrayListMultimap.create();
multimap.put("a", 1);
multimap.put("a", 1);
System.out.println("multimap = " + multimap);
//双向map 键和值都不能重复
BiMap<String, String> biMap = HashBiMap.create();
biMap.put("a", "1");
biMap.put("b", "2");
System.out.println("bimap key " + biMap.get("a"));
System.out.println("bimap value " + biMap.inverse().get("1"));
//Table 比较常用 <row, column ,value>
Table<String, String, Integer> tables = HashBasedTable.create();
tables.put("row1", "column1",1);
tables.put("row2","column2", 2);
System.out.println("the row1 is " + tables.row("row1"));
System.out.println("the row1 cloumn is " + tables.column("column1"));
System.out.println("the value is " + tables.get("row1", "column1"));
扩展工具类
在元素添加到列表时增加特定行为
- Forwarding装饰器:delegate,覆盖这个方法返回被装饰的对象,实现特定行为
- PeekingIterator:事先获取下次next返回的元素
- AbstractIterator:实现自己的Iterator
- AbstractSequentialIerator:表示迭代的另一种方式
集合的过滤
(1)按照条件过滤
ImmutableList<String> names = ImmutableList.of("begin", "code", "Guava", "Java");
Iterable<String> fitered = Iterables.filter(names, Predicates.or(Predicates.equalTo("Guava"), Predicates.equalTo("Java")));
System.out.println(fitered); // [Guava, Java]
(2)自定义过滤条件
//自定义过滤条件 使用自定义回调方法对Map的每个Value进行操作
ImmutableMap<String, Integer> m = ImmutableMap.of("begin", 12, "code", 15);
// Function<F, T> F表示apply()方法input的类型,T表示apply()方法返回类型
Map<String, Integer> m2 = Maps.transformValues(m, new Function<Integer, Integer>() {
public Integer apply(Integer input) {
if(input>12){
return input;
}else{
return input+1;
}
}
});
System.out.println(m2); //{begin=13, code=15}
(3)set的交集、并集、差集
HashSet<Integer> setA = Sets.newHashSet(1, 2, 3, 4, 5);
HashSet<Integer> setB = Sets.newHashSet(4, 5, 6, 7, 8);
Sets.SetView<Integer> union = Sets.union(setA, setB);
System.out.println("union:");
for (Integer integer : union){
System.out.println(integer);//union:12345867
}
Sets.SetView<Integer> difference = Sets.difference(setA, setB);
System.out.println("difference:");
for (Integer integer : difference){
System.out.println(integer); //difference:123
}
Sets.SetView<Integer> intersection = Sets.intersection(setA, setB);
System.out.println("intersection:");
for (Integer integer : intersection){
System.out.println(integer);
}
(4)map的交集、并集、差集
Map<String, Integer> mapA = Maps.newHashMap();
Map<String, Integer> mapB = Maps.newHashMap();
mapA.put("a", 1);
mapA.put("b", 2);
mapA.put("c", 6);
mapB.put("d", 4);
mapB.put("c", 3);
MapDifference<String, Integer> difference1 = Maps.difference(mapA, mapB);
System.out.println("are qual " + difference1.areEqual());
System.out.println("diff " + difference1.entriesDiffering());
System.out.println("left " + difference1.entriesOnlyOnLeft());
System.out.println("right" + difference1.entriesOnlyOnRight());
System.out.println("common" + difference1.entriesInCommon());
字符串操作
(1) 连接器Joiner
将集合转换为特定规则的字符串,核心是Joiner类
list->string
List<String> list = Lists.newArrayList();
list.add("a");
list.add("b");
list.add("c");
String result = Joiner.on(",").join(list);
System.out.println("the string is " + result);
map->String
Map<String, String> map1 = Maps.newHashMap();
map1.put("zhangruizhi", "hehe");
map1.put("zhang", "haha");
String resultMap = Joiner.on(",").withKeyValueSeparator("=").join(map1);
System.out.println("the result map is " + resultMap);
连接器Joiner
Joiner joiner = Joiner.on("; ").skipNulls();
return joiner.join("Harry", null, "Ron", "Hermione");
(2) 拆分器Splitter
将字符串转换为特定规则的集合,核心是Splitter类
string->list,可以忽略空格,空行
String s = "192.168.0.1, 192.168.0.2, 192.168.0.3, 192.168.0.4";
List<String> sList = Splitter.on(",").omitEmptyStrings().trimResults().splitToList(s);
System.out.println("the sList is " + sList);
string->map
String mapS = "zhangruizhi=a, zhang=b";
Map<String, String> sMap = Splitter.on(",").withKeyValueSeparator("=").split(mapS);
System.out.println("the s map is " + sMap);
拆分器Splitter
Splitter.on(',')
.trimResults()
.omitEmptyStrings()
.split("foo,bar,, qux");
字符匹配器CharMatcher
String noControl = CharMatcher.JAVA_ISO_CONTROL.removeFrom(string); //移除control字符
String theDigits = CharMatcher.DIGIT.retainFrom(string); //只保留数字字符
String spaced = CharMatcher.WHITESPACE.trimAndCollapseFrom(string, ' ');
//去除两端的空格,并把中间的连续空格替换成单个空格
String noDigits = CharMatcher.JAVA_DIGIT.replaceFrom(string, "*"); //用*号替换所有数字
String lowerAndDigit = CharMatcher.JAVA_DIGIT.or(CharMatcher.JAVA_LOWER_CASE).retainFrom(string);
// 只保留数字和小写字母
字符集Charsets
大小写格式CaseFormat
CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, "CONSTANT_NAME")); // returns "constantName"
计时工具
Stopwatch stopwatch = Stopwatch.createStarted();
int sum = 0;
for( int i =0; i< 100; i++){
sum+=i;
}
long time = stopwatch.elapsed(TimeUnit.MICROSECONDS);
文件操作
主要是Files类
File file = new File("/test.txt");
List<String> listTest = null;
try {
list = Files.readLines(file, Charsets.UTF_8);
} catch (Exception e) {
}
File from = new File("./test.log");
File to = new File("./newFile.log");
File directory = new File("./.");
try{
Files.copy(from,to); //复制文件
Files.move(from, to); //移动文件
URL url = Resources.getResource("abc.xml"); //获取classpath根下的abc.xml文件url
}catch (IOException ioe){
}
缓存
Guava Cache适用于:
- 愿意消耗一些内存空间来提升速度。
- 你预料到某些键会被查询一次以上。
- 缓存中存放的数据总量不会超出内存容量。
LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
.maximumSize(1000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.removalListener(MY_LISTENER)
.build(
new CacheLoader<Key, Graph>() {
public Graph load(Key key) throws AnyException {
return createExpensiveGraph(key);
}
});
缓存回收:基于容量的回收、定时回收、基于引用的回收、显式清除
Guava 数学运算
- Guava Math针对各种不常见的溢出情况都有充分的测试;对溢出语义,Guava文档也有相应的说明;如果运算的溢出检查不能通过,将导致快速失败;
- Guava Math的性能经过了精心的设计和调优;虽然性能不可避免地依据具体硬件细节而有所差异,但Guava Math的速度通常可以与Apache Commons的MathUtils相比,在某些场景下甚至还有显著提升;
- Guava Math在设计上考虑了可读性和正确的编程习惯;IntMath.log2(x, CEILING) 所表达的含义,即使在快速阅读时也是清晰明确的。而32-Integer.numberOfLeadingZeros(x – 1)对于阅读者来说则不够清晰。
基本使用
Optional
对null值进行快速失败
Optional<T> 表示可能的null的T类型的引用
Optional.of(T) | 创建指定引用的Optional实例,若引用为null则快速失败 |
Optional.absent() | 创建引用缺失的Optional实例 |
Optional.fromNullable(T) | 创建指定引用的Optional实例,若引用为null则表示缺失 |
Preconditions
若干前置条件判断的方法
checkArgument(boolean) | 检查boolean是否为true,用来检查传递给方法的参数。 | IllegalArgumentException |
checkNotNull(T) | 检查value是否为null,该方法直接返回value,因此可以内嵌使用checkNotNull。 | NullPointerException |
checkState(boolean) | 用来检查对象的某些状态。 | IllegalStateException |
checkElementIndex(int index, int size) | 检查index作为索引值对某个列表、字符串或数组是否有效。index>=0 && index<size * | IndexOutOfBoundsException |
checkPositionIndex(int index, int size) | 检查index作为位置值对某个列表、字符串或数组是否有效。index>=0 && index<=size * | IndexOutOfBoundsException |
checkPositionIndexes(int start, int end, int size) | 检查[start, end]表示的位置范围对某个列表、字符串或数组是否有效* | IndexOutOfBoundsException |
参数检查 主要是Preconditions类
String testString = null;
Preconditions.checkArgument(!Strings.isNullOrEmpty(testString), "the testString is null or empty");
String testString1 = null;
Preconditions.checkNotNull(testString1);
Ordering
用来构建复杂的比较器,完成集合排序的功能
创建排序器:
natural() | 对可排序类型做自然排序,如数字按大小,日期按先后排序 |
usingToString() | 按对象的字符串形式做字典排序[lexicographical ordering] |
from(Comparator) | 把给定的Comparator转化为排序器 |
链式调用方法: 后面的方法包装了前面的排序器
reverse() | 获取语义相反的排序器 |
nullsFirst() | 使用当前排序器,但额外把null值排到最前面。 |
nullsLast() | 使用当前排序器,但额外把null值排到最后面。 |
compound(Comparator) | 合成另一个比较器,以处理当前排序器中的相等情况。 |
lexicographical() | 基于处理类型T的排序器,返回该类型的可迭代对象Iterable<T>的排序器。 |
onResultOf(Function) | 对集合中元素调用Function,再按返回值用当前排序器排序。 |
运用排序器:
Throwables:简化异常和错误的传播与检查
Throwables.propagate
参考:
https://www.cnblogs.com/peida/archive/2013/06/08/3120820.html
https://wizardforcel.gitbooks.io/guava-tutorial/content/1.html