基础工具类
基础的工具类有很多,我经常使用的有如下一些,先总结下经常使用的,没有使用过的,以后慢慢补充吧。
防御型编程Preconditions
防御性编程通常用来检测方法的参数的正确性,在方法的开始就对参数一定的断言,如果断言失败,就抛出异常,从而导致快速失败,guava中Preconditions类用来完成这样的检测工作。
private int sum(Integer v1, Integer v2) {
Preconditions.checkNotNull(v1, "Illegal Argument passed: first parameter is null.");
Preconditions.checkNotNull(v2, "Illegal Argument passed: second parameter is null");
return v1 + v2;
}
private double sqrt(double i) {
Preconditions.checkArgument(i >= 0, "input value must more than or equal 0: %s", i);
return Math.sqrt(i);
}
Preconditions类中很多的方法功能都是一样的,第一个参数提供一个断言,第二个参数是断言失败的情况下,抛出的异常信息。可以根据不同的场合选择不同的方法名。个人感觉一个checkArgument就足够了。
基础工具类-字符串处理
字符串处理最常用的操作:split和join。
split操作
对应这样的字符串"a , , b ,c"按逗号分隔后结果中可能有空格,且String类的split方法只能返回分隔后的数组。而Guava对split操作提供了更多更清晰语义的方法。
@Test
public void test4() {
List<String> list = Splitter.on(",").omitEmptyStrings().trimResults().splitToList(",,a, b,c,,d,,");
System.out.println(list.toString());
List<String> list2 = Splitter.on(",").omitEmptyStrings().limit(3).trimResults().splitToList(",,a, b,c,,d,,");
System.out.println(list2.toString());
}
[a, b, c, d]
[a, b, c,,d,,]
- omitEmptyStrings: 忽略split后的空字符串
- trimResults: trim一下结果
- splitToList: 返回一个List而不是数组
- limit: 返回的结果集size限制为3,只split前两个,后面就不split了而作为一个整体作为第三个元素
join操作
join可以看出split的反操作,是将一个List或数组用一个分隔符连接起来。当List中有null时,可以选中忽略或其他意义的字符代替。
/**
* 演示普通的字符串连接,同时可以看出join方法不具有记忆性
*/
@Test
public void test1()
{
Joiner joiner = Joiner.on(",").skipNulls();
String result = joiner.join("a", 1, null, 'c');
System.out.println(result);
String[] names = new String[]{"zhangsan", "lisi", "wangwu"};
System.out.println(joiner.join(names));
}
a,1,c
zhangsan,lisi,wangwu
基础工具类-排序
Guava提供了非常方便的Comparator,对于大多数情况下,我们不需要自己实现排序的比较器。guava提供的比较器实例是Ordering类,这个类实现了Comparator接口。
class Person {
int age;
String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
setter,getter...
}
要对Person对象列表按age排序,以前做法:
- Person实现Comparable接口
- Collections.sort(list, personAgeComparator);
Guava让我们在大部分情况下都不需要自己实现比较器---Ordering.natural()
获得Person按age的比较器
Ordering<Person> personAgeOrdering = Ordering.natural().nullsFirst().onResultOf(new Function<Person, Integer>() {
@Override
public Integer apply(Person input) {
return input.age;
}
});
Collections.sort(list, personAgeOrdering);
Ordering类的natural能按:
- 数字:自然排序
- 字符串:字典序
- 日期:先后顺序
- 其他没测试过
Collections.sort(list, personAgeOrdering.reverse());//倒序
其他方法:
Ordering实例还有一些其他的方法:
sortedCopy:先拷贝参数中的list,然后做排序
isOrdered:判断一个list是否有序
isStrictlyOrdered:判断是否严格有序,不能有相同元素
max:取一个list中的最大值
min:取一个list中的最小值
greatestOf(list, 2):返回一个list中最大的前2个元素
leastOf(list, 2):返回一个list中最小的2个元素
基础工具类-速率限制
有时候需要对某些服务的请求速率做人为的控制,Guava提供了RateLimiter。可以方便实现这个功能。
使用方式:
RateLimiter limiter = RateLimiter.create(3);
创建一个1s释放3个许可的速率限制器- 在需要使用速率限制的地方使用
limiter.acquire();
@Test
public void test34() throws InterruptedException {
RateLimiter limiter = RateLimiter.create(3);
for (int i = 0; i < 10; i++) {
limiter.acquire(1);
System.out.println(i);
}
}
RateLimite释放许可的过程支持预热。
RateLimiter limiter = RateLimiter.create(10, 5, TimeUnit.SECONDS); 每秒释放10个许可,但是5s内逐渐增加到10个
/**
* 演示速率限制器的预热过程,预热时间是5,单位秒
* 运行的效果是由4、6、7、8、10渐渐增加到每s放10个
*/
@Test
public void test35() {
RateLimiter limiter = RateLimiter.create(10, 5, TimeUnit.SECONDS);
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
for (; ; ) {
limiter.acquire();
System.out.println(df.format(new Date()));
}
}
- 注:许可不可累加,如在3s内没有acquire,并不是会累积3个许可在其中。
之前在导入晒一晒数据的时候,就使用过速率限制,因为晒一晒的数据是通过Http直接拉线上服务器的数据,然后通过解析JSON格式的数据,再导入到社区的。为了不给线上服务器太大的压力,通过Http拉取数据的时候,就通过这个类设置了速率限制。