guava
目录
【基本工具】
一、optional
针对java开发中null的问题,guava设计了Optional类。虽然util包下也有自带的Optional类,但是Guava对其做了更好的处理。Optional 用来表示可能为null的T类型的引用,两个实现类Present(存在)和Absent(不存在)。
那么Optional究竟有什么用呢,我们来看一下主要的方法:
- Optional.fromNullable(T) 创建指定引用的Optional实例,若引用为null则表示缺失
- boolean isPresent() 如果Optional包含非null的引用(引用存在),返回true
String s1 = null;
String s2 = "1";
Optional opt1 = Optional.fromNullable(s1);
Optional opt2 = Optional.fromNullable(s2);
System.out.println(opt1.isPresent()); // false
System.out.println(opt2.isPresent()); // true
- T get() 返回Optional所包含的引用,若引用缺失,则抛出java.lang.IllegalStateException
- T or(T) 返回Optional所包含的引用,若引用缺失,返回指定的值
- T orNull() 返回Optional所包含的引用,若引用缺失,返回null
// 紧接着上面的例子
System.out.println(opt1.or("0")); // 0
System.out.println(opt1.orNull()); // null
System.out.println(opt2.get()); // 1
System.out.println(opt2.or("0")); // 1
System.out.println(opt2.orNull()); // 1
- Optional.of(T) 创建指定引用的Optional实例,若引用为null则快速失败
Optional.of("0");
Optional.of(null); // NullPointerException
Optional存在的意义是什么?看下官方的解释:
使用Optional除了赋予null语义,增加了可读性,最大的优点在于它是一种傻瓜式的防护。Optional迫使你积极思考引用缺失的情况,因为你必须显式地从Optional获取引用。直接使用null很容易让人忘掉某些情形,尽管FindBugs可以帮助查找null相关的问题,但是我们还是认为它并不能准确地定位问题根源。
如同输入参数,方法的返回值也可能是null。和其他人一样,你绝对很可能会忘记别人写的方法method(a,b)会返回一个null,就好像当你实现method(a,b)时,也很可能忘记输入参数a可以为null。将方法的返回类型指定为Optional,也可以迫使调用者思考返回的引用缺失的情形。
总的来说Optional实际上就是一个提醒,让开发者时刻注意null。
二、前置条件
Guava封装好了几种前置条件的实用方法,能够让判断条件更简单。
每种方法都有3个重载函数:
● 没有额外参数,只抛出异常,无错误信息
● 有一个Object类型的额外参数,通过toString方法输出错误信息
● 有一个String对象和Object数组作为额外参数,String中通过’%s’占位符依次输出数组中的参数值
方法声明 | 描述 | 失败抛出异常 |
---|---|---|
checkArgument(boolean) | 检查boolean是否为true,用于参数检查 | illegalargumentException |
checkState(boolean) | 检查对象的某些状态 | IllegalStateException |
checknotnull(T) | 检查T的实例是否为null,直接返回该实例 | NullPointerException |
checkElementIndex(int index, int size) | 检查索引是否有效(index>=0&&index<size) | IndexOutOfBoundsException |
checkPositionIndex(int index, int size) | 检查位置是否有效(index>=0&&index<=size) | IndexOutOfBoundsException |
checkPositionIndexes(int start, int end, int size) | 检查位置在[start, end]是否有效 | IndexOutOfBoundsException |
有这些前置条件可以省去很多重复的判断代码。
// 直接 static 引入即可
import static com.Google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
checkNotNull(reference, ...);
checkArgument(expression, ...);
checkState(expression, ...);
三、Objects方法
Guava提供的Objects与JDK util包下的Objects有些许相似的地方。
- equal(Object a, Object b) 忽略null的情况,可直接比较,与JDK Objects.equals方法相同。
- hashCode(Object… objects) hash运算,与JDK Objects.hash方法相同。
- toString,Guava的Objects提供了toStringHelper来实现toString方法,目前已过时,个人建议直接使用lombok注解生成。
Objects.toStringHelper("className").add("attr", value).toString();
- 这里值得推荐的是比较器ComparisonChain:
之前实现比较方法是需要自定义实现compare或compareTo方法
public class Student implements Comparable<Student> {
private Double score;
private String name;
private Long number;
@Override
public int compareTo(Student student) {
int compare = score.compareTo(student.score);
if (compare != 0) {
return compare;
}
// 分数相同,比较姓名
compare = name.compareTo(student.name);
if (compare != 0) {
return compare;
}
// 比较学号
return number.compareTo(student.number);
}
}
以上首先是根据学生成绩排序,成绩相同再根据姓名排序,若在相同则根据学号排序,使用ComparisonChain比较的代码如下:
@Override
public int compareTo(Student student) {
return ComparisonChain.start()
.compare(score, student.score)
.compare(name, student.name)
.compare(number, student.number, ordering.natural().nullsLast())
.result();
}
两者相较很明显后者直观明了,ComparisonChain会根据compare的顺序依次比较,直至发现非0的结果,之后的比较会直接忽略。另外compare中的第三个参数还可以定义排序顺序,类Ordering也是由Guava提供,本文第四节会做出介绍。
四、Guava强大的比较器
首先"强大"两字来源于官网的标题,不过个人认为确实强大~~
通过源码可以看出Ordering实际上是Comparator的实例,并且拓展出了链式调用方法,使用起来非常方便。
- 创建排序
● natural() 对排序类型做自然排序
● usingToString() 按对象toString()方法做字典排序
● from(Comparator) 转化排序器
除此外还可以直接继承Ordering:
Ordering<String> ordering = new Ordering<String>() {
@Override
public int compare(String left, String right) {
return left.compareTo(right);
}
};
- 链式调用方法
所谓链式调用就是由给定的排序器衍生出其他排序器
方法|描述
----|----
reverse()|倒叙排序
nullsFirst()|排序中,把null值拍到最前
nullsLast()|排序中,把null值拍到最后
compound(Comparator)|合成比较器,处理当前排序器中的相等情况
lexicographical()|返回按字典迭代的排序器
onResultOf(Function)|对集合调用Function,再按返回值排序
注:Function为Guava的函数式编程,在第五章中会介绍。
第三节中的 Ordering.natural().nullsLast() 就是链式调用,但要注意链式调用应从后往前读,即先调用nullsLast将null元素置后,再调用natural()进行自然排序。
注:用compound方法包装排序器时,就不应遵循从后往前读的原则。为了避免理解上的混乱,请不要把compound写在一长串链式调用的中间,你可以另起一行,在链中最先或最后调用compound。
3. 其他方法
方法 | 描述 | 另请参见 |
---|---|---|
greatestOf(Iterable iterable, int k) | 获取可迭代对象中最大的k个元素。 | leastOf |
isOrdered(Iterable) | 判断可迭代对象是否已按排序器排序:允许有排序值相等的元素。 | isStrictlyOrdered |
sortedCopy(Iterable) | 判断可迭代对象是否已严格按排序器排序:不允许排序值相等的元素。 | immutableSortedCopy |
min(E, E) | 返回两个参数中最小的那个。如果相等,则返回第一个参数。 | max(E, E) |
min(E, E, E, E…) | 返回多个参数中最小的那个。如果有超过一个参数都最小,则返回第一个最小的参数。 | max(E, E, E, E…) |
min(Iterable) | 返回迭代器中最小的元素。如果可迭代对象中没有元素,则抛出NoSuchElementException。 | max(Iterable),min(Iterator),max(Iterator) |
五、 throwables
Guava还提供了简化异常和错误的传播与检查方法,由于实际开发中用到的不多,这里不再介绍,详细可以查看中文文档Google Guava: Throwables
相关阅读
扯淡一下:刚刚换了新工作,新的公司,新的同事,很好的伙伴们,都很喜欢;新的业务,新的技术,新的挑战:开启新的旅程,Fighting! 这阵子一直了解