guava学习笔记
API通过教程查阅,记录实践范例
教程
https://www.yiibai.com/guava
https://ifeve.com/google-guava/
http://www.ibloger.net/article/3294.html
基础
Optional类:使用和避免null
https://www.yiibai.com/guava/guava_optional_class.html
目前未发现与Java.util.Optional的不同
api
例子
public class GuavaTester {
public static void main(String args[]){
Integer value1 = null;
Integer value2 = new Integer(10);
//Optional.fromNullable - allows null.
Optional<Integer> a = Optional.fromNullable(value1);
//Optional.of - throws NullPointerException if null
Optional<Integer> b = Optional.of(value2);
}
public Integer sum(Optional<Integer> a, Optional<Integer> b){
//Optional.isPresent - checks the value is present or not
System.out.println("First parameter is present: " + a.isPresent());
//Optional.or - returns value if present otherwise returns or-value
Integer value1 = a.or(new Integer(0));
//Optional.get - gets the value, value should be present
Integer value2 = b.get();
}
}
Preconditions:前置条件,优雅的参数检查
API中的每个方法都有三个变种:
没有额外参数:抛出的异常中没有错误消息。
有一个Object对象作为额外参数:抛出的异常使用Object.toString() 作为错误消息。
有一个String对象作为额外参数,并且有一组任意数量的附加Object对象:这个变种处理异常消息的方式有点类似printf,但考虑GWT的兼容性和效率,只支持%s指示符。
相比Apache Commons提供的类似方法,我们把Guava中的Preconditions作为首选。一些理由:
- 在静态导入后,Guava方法非常清楚明晰。checkNotNull清楚地描述做了什么,会抛出什么异常;
- checkNotNull直接返回检查的参数,让你可以在构造函数中保持字段的单行赋值风格:this.field = checkNotNull(field)
- 简单的、参数可变的printf风格异常信息。鉴于这个优点,在JDK7已经引入Objects.requireNonNull的情况下,我们仍然建议你使用checkNotNull。
API
例子
public static void main(String args[]){
try {
System.out.println(guavaTester.sqrt(-3.0));
}catch(IllegalArgumentException e){
// Illegal Argument passed: Negative value -3.0.
System.out.println(e.getMessage());
}
try {
System.out.println(guavaTester.sum(null,3));
}catch(NullPointerException e){
// Illegal Argument passed: First parameter is Null.
System.out.println(e.getMessage());
}
try {
System.out.println(guavaTester.getValue(6));
}catch(IndexOutOfBoundsException e){
// Illegal Argument passed: Invalid index. (6) must be less than size (5)
System.out.println(e.getMessage());
}
}
public double sqrt(double input) throws IllegalArgumentException {
Preconditions.checkArgument(input > 0.0,
"Illegal Argument passed: Negative value %s.", input);
return Math.sqrt(input);
}
public 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;
}
public int getValue(int input){
int[] data = {1,2,3,4,5};
Preconditions.checkElementIndex(input,data.length,
"Illegal Argument passed: Invalid index.");
return 0;
}
Validate:common包里的优雅前置检查
例子
违反就会抛出validate api方法中指定的异常
import org.apache.commons.lang3.Validate;
Validate.notEmpty(columns, "columns is empty");
Validate.notBlank(string, "string is empty");
Validate.notNull(other, "other BaseCommand is null");
Validate.isInstanceOf(BigDecimal.class, concreteValue);
Validate.isTrue(entitySchema.getEntityId() != 0, "entityId is 0");
noNullElements(array, "array contains null")
// 其他API
// validState
// matchesPattern
// ……
Ordering:流畅风格比较器
http://www.ibloger.net/article/3300.html
排序器 Ordering 是 Guava版 Comparator 的实现,Ordering 实例就是一个特殊的 Comparator 实例。Ordering 把很多基于 Comparator 的静态方法(如 Collections.max)包装为自己的实例方法(非静态方法),并且提供了链式调用方法,来定制和增强现有的比较器。
Objects:通用Object方法
http://ifeve.com/google-guava-commonobjectutilities/
// equals方法
Objects.equal("a", "a"); // returns true
Objects.equal(null, "a"); // returns false
Objects.equal("a", null); // returns false
Objects.equal(null, null); // returns true
// hashCode方法
Objects.hashCode("a","b","c")
// toString
// Returns "ClassName{x=1}"
Objects.toStringHelper(this).add("x", 1).toString();
// Returns "MyObject{x=1}"
Objects.toStringHelper("MyObject").add("x", 1).toString();
// compare
public int compareTo(Foo that) {
return ComparisonChain.start()
.compare(this.aString, that.aString)
.compare(this.anInt, that.anInt)
.compare(this.anEnum, that.anEnum, Ordering.natural().nullsLast())
.result();
}
StopWatch:时间监测工具
IDE配置:
http://www.ibloger.net/article/3304.html
https://www.jianshu.com/p/13bda7d606cc :IDEA搭配StopWatch监测性能
用于debug中打印方法时间消耗
stopWatch示例
http://www.ibloger.net/article/3304.html
API
例子
@Test
public void test1() throws Exception {
String orderNo = "12345678";
logger.info("订单 [{}] 开始处理", orderNo);
Stopwatch stopwatch = Stopwatch.createStarted();
TimeUnit.SECONDS.sleep(1); // 1秒处理时间
logger.info("订单 [{}] 处理完成,耗时 [{}]", orderNo, stopwatch.stop());
}
@Test
public void test2() throws Exception {
// 创建stopwatch并开始计时
Stopwatch stopwatch = Stopwatch.createStarted();
Thread.sleep(1980);
// 以秒打印从计时开始至现在的所用时间,向下取整
System.out.println(stopwatch.elapsed(TimeUnit.SECONDS)); // 1
// 停止计时
stopwatch.stop();
System.out.println(stopwatch.elapsed(TimeUnit.SECONDS)); // 1
// 再次计时
stopwatch.start();
Thread.sleep(100);
System.out.println(stopwatch.elapsed(TimeUnit.SECONDS)); // 2
// 重置并开始
stopwatch.reset().start();
Thread.sleep(1030);
// 检查是否运行
System.out.println(stopwatch.isRunning()); // true
long millis = stopwatch.elapsed(TimeUnit.MILLISECONDS); // 1034
System.out.println(millis);
// 打印
System.out.println(stopwatch.toString()); // 1.034 s
}
容器集合
Multiset:无序(不保证顺序)的可重复集合
http://www.ibloger.net/article/3306.html
public static void main(String args[]){
// 创建 multiset 集合
Multiset<String> multiset = HashMultiset.create();
multiset.add("a");
multiset.add("b");
multiset.add("c");
multiset.add("d");
multiset.add("a");
multiset.add("b");
multiset.add("c");
multiset.add("b");
multiset.add("b");
multiset.add("b");
// 个数
System.out.println("Occurrence of 'b' : " + multiset.count("b"));
System.out.println("Total Size : " + multiset.size());
// 遍历
Set<String> set = multiset.elementSet();
System.out.print("Set [");
for (String s : set) {
System.out.print(s);
}
System.out.println("]");
// 使用迭代器
Iterator<String> iterator = multiset.iterator();
System.out.print("MultiSet [");
while (iterator.hasNext()) {
System.out.print(iterator.next());
}
System.out.println("]");
// 不同元素的个数
System.out.println("MultiSet [");
for (Multiset.Entry<String> entry : multiset.entrySet()) {
System.out.println(" Element: " + entry.getElement() + ", Occurrence(s): " + entry.getCount());
}
System.out.println("]");
// 删除元素
multiset.remove("b", 2);
// 查找元素
System.out.println("Occurence of 'b' : " + multiset.count("b"));
}
// 输出
Occurrence of 'b' : 5
Total Size : 10
Set [abcd]
MultiSet [aabbbbbccd]
MultiSet [
Element: a, Occurrence(s): 2
Element: b, Occurrence(s): 5
Element: c, Occurrence(s): 2
Element: d, Occurrence(s): 1
]
Occurence of 'b' : 3
Bimap:双向关联的数据结构
package com.example.guava.collect;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import org.junit.Test;
public class BimapTest{
@Test
public void test1(){
BiMap<String, String> upperToSmall = HashBiMap.create();
upperToSmall.put("A", "a");
upperToSmall.put("B", "b");
upperToSmall.put("C", "c");
upperToSmall.forcePut("D","c");
System.out.println(upperToSmall.get("D")); // c
BiMap<String, String> smallToUpper = upperToSmall.inverse();
System.out.println(smallToUpper.get("c")); // D
smallToUpper.put("E","e");
System.out.println(upperToSmall); // {A=a, B=b, D=c, e=E}
System.out.println(smallToUpper); // {a=A, b=B, c=D, E=e}
}
}
Table:Map<FirstName, Map<LastName, Person>>
http://www.ibloger.net/article/3308.html
public class TableTest extends TestCase {
/**
* 双键的 Map --> Table --> rowKey+columnKye+value
*/
@Test
public void test1() {
Table<Object, Object, Object> table = HashBasedTable.create();
table.put("jack", "java", 98);
table.put("jack", "php", 65);
table.put("jack", "ui", 80);
table.put("jack", "mysql", 86);
// 遍历
Set<Table.Cell<Object, Object, Object>> cells = table.cellSet();
cells.forEach(c -> System.out.println(c.getRowKey() + "-" + c.getColumnKey() + " : " + c.getValue()));
/**
* 执行结果
*
* jack-java : 98
* jack-php : 65
* jack-ui : 80
* jack-mysql : 86
*/
}
public void test2() {
//Table<R,C,V> == Map<R,Map<C,V>>
/*
* Company: IBM, Microsoft, TCS
* IBM -> {101:Mahesh, 102:Ramesh, 103:Suresh}
* Microsoft -> {101:Sohan, 102:Mohan, 103:Rohan }
* TCS -> {101:Ram, 102: Shyam, 103: Sunil }
*
* */
Table<String, String, String> table = HashBasedTable.create();
// 使用员工详细信息初始化表
table.put("IBM", "101", "Mahesh");
table.put("IBM", "102", "Ramesh");
table.put("IBM", "103", "Suresh");
table.put("Microsoft", "111", "Sohan");
table.put("Microsoft", "112", "Mohan");
table.put("Microsoft", "113", "Rohan");
table.put("TCS", "121", "Ram");
table.put("TCS", "122", "Shyam");
table.put("TCS", "123", "Sunil");
// 获取与IBM对应的Map
Map<String, String> ibmMap = table.row("IBM");
System.out.println("IBM员工名单");
for (Map.Entry<String, String> entry : ibmMap.entrySet()) {
System.out.println("Emp Id: " + entry.getKey() + ", Name: " + entry.getValue());
}
System.out.println();
// 获取表格的所有唯一键
Set<String> employers = table.rowKeySet();
System.out.print("Employers: ");
employers.forEach(e -> System.out.print(e + " "));
System.out.println("\n");
// 得到一个对应102的Map
Map<String, String> EmployerMap = table.column("102");
for (Map.Entry<String, String> entry : EmployerMap.entrySet()) {
System.out.println("Employer: " + entry.getKey() + ", Name: " + entry.getValue());
}
}
public void test3() {
Table<String, Integer, Integer> table = HashBasedTable.create();
table.put("A", 1, 100);
table.put("A", 2, 101);
table.put("B", 1, 200);
table.put("B", 2, 201);
/**
* contains(Object rowKey, Object columnKey):
* Table中是否存在指定rowKey和columnKey的映射关系
*/
boolean containsA3 = table.contains("A", 3); // false
boolean containColumn2 = table.containsColumn(2); // true
boolean containsRowA = table.containsRow("A"); // true
boolean contains201 = table.containsValue(201); // true
/**
* remove(Object rowKey, Object columnKey):
* 删除Table中指定行列值的映射关系
*/
table.remove("A", 2);
/**
* get(Object rowKey, Object columnKey):
* 获取Table中指定行列值的映射关系
*/
table.get("B", 2);
/**
* column(C columnKey):返回指定columnKey下的所有rowKey与value映射
*/
Map<String, Integer> columnMap = table.column(2);
/**
* row(R rowKey):返回指定rowKey下的所有columnKey与value映射
*/
Map<Integer, Integer> rowMap = table.row("B");
/**
* 返回以Table.Cell<R, C, V>为元素的Set集合
* 类似于Map.entrySet
*/
Set<Table.Cell<String, Integer, Integer>> cells = table.cellSet();
for (Table.Cell<String, Integer, Integer> cell : cells) {
//获取cell的行值rowKey
cell.getRowKey();
//获取cell的列值columnKey
cell.getColumnKey();
//获取cell的值value
cell.getValue();
}
}
}