基础工具类

基础的工具类有很多,我经常使用的有如下一些,先总结下经常使用的,没有使用过的,以后慢慢补充吧。

防御型编程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排序,以前做法:

  1. Person实现Comparable接口
  2. 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。可以方便实现这个功能。

使用方式:

  1. RateLimiter limiter = RateLimiter.create(3); 创建一个1s释放3个许可的速率限制器
  2. 在需要使用速率限制的地方使用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拉取数据的时候,就通过这个类设置了速率限制。

results matching ""

    No results matching ""