随笔 - 301  文章 - 2  评论 - 16  阅读 - 34万

Google Guava 基本工具

google-guava被誉为是JAVA里面的瑞士军刀。能简化我们的代码,让我们的代码易写、易读、易于维护。而且它能提高我们的工作效率,让我们从大量重复的底层代码中脱身。

Google Guava maven引入

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>27.1-jre</version>
</dependency>

  

一 使用和避免null

       guava里面的Optional类可以很方便的帮助我们来应对null的情况。但是我个人觉得完全我们可以用Java8里面的Optional类来替代它。所以这里我们直接简单说下Java8里面Optional类的使用。Java8为啥要推出Optional这个类的主要目的就是Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException) —— 每个 Java 程序员都非常了解的异常。使用Optional除了赋予null语义,增加了可读性,最大的优点在于它是一种傻瓜式的防护。Optional迫使你积极思考引用缺失的情况,因为你必须显式地从Optional获取引用。直接使用null很容易让人忘掉某些情形。

Optional类本质上,这是一个包含有可选值的包装类,这意味着 Optional 类既可以含有对象也可以为空。

JAVA8 里面Optional类的介绍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
public final class Optional<T> {
 
    /**
     * 创建一个Optional对象,并且Optional对应的value为null
     */
    public static<T> Optional<T> empty();
 
    /**
     * 创建一个Optional对象,Optional对应的value就是参数
     * 而且这里有一个要求,value不能为null,否则NullPointerException
     */
    public static <T> Optional<T> of(T value);
 
    /**
     * 创建一个Optional对象,Optional对应的value就是参数
     * 和of的唯一区别就是value为null的时候不会有异常抛出
     */
    public static <T> Optional<T> ofNullable(T value);
 
    /**
     * 获取Optional对应的value,如果value为null,则抛出NoSuchElementException异常
     *
     */
    public T get();
 
    /**
     * 判断Optional对应的value是否为null
     */
    public boolean isPresent();
 
    /**
     * 如果Optional对应的value是null的时候,会执行consumer的accept方法
     */
    public void ifPresent(Consumer<? super T> consumer);
 
    /**
     * 如果Optional对应的value满足predicate的条件,则返回当前Optional对象
     * 否则返回一个Optional并且他的value为null
     */
    public Optional<T> filter(Predicate<? super T> predicate);
 
    /**
     * 通过mapper对Optional的value做转换。
     * Function先转换成对象,再转换成Optional
     */
    public<U> Optional<U> map(Function<? super T, ? extends U> mapper);
 
    /**
     * 通过mapper对Optional的value做转换。
     * Function直接转换成Optional
     */
    public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper);
 
    /**
     * 如果Optional对应的value是null的时候就用other替换value
     */
    public T orElse(T other);
 
    /**
     * 如果Optional对应的value是null的时候就用other.get()的返回值替换value
     */
    public T orElseGet(Supplier<? extends T> other);
 
    /**
     * 如果Optional对应的value是null的时候返回exceptionSupplier设置的异常
     */
    public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X;
}

二 前置条件判断

       Guava在Preconditions类中提供了若干前置条件判断的实用方法。让方法调用的前置条件判断更简单。比如我们经常需要判断参数的合法性。

Preconditions api介绍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
public final class Preconditions {
 
    /**
     * 用来检查对象是否满足条件,不满足条件则抛出IllegalArgumentException异常
     * (如果expression为false代表不满足条件)
     */
    public static void checkArgument(boolean expression);
 
    /**
     * 不满足条件则抛出IllegalArgumentException异常
     * 可以自定义异常描述信息
     */
    public static void checkArgument(boolean expression, @Nullable Object errorMessage);
 
    /**
     * 不满足条件则抛出IllegalArgumentException异常
     * 可以自定义异常描述信息,自定义异常描述的规则也很简单,只不过是多了一个消息模板
     * 会先去errorMessageTemplate里面按顺序找到%s,
     * 如果找到了就把errorMessageArgs里面的每个值转换为String依次代入进去
     * 否则直接把errorMessageArgs的值依次放在errorMessageTemplate的末尾,类似errorMessageTemplate[errorMessageArgs[0],errorMessageArgs[1]]
     *
     */
    public static void checkArgument(boolean expression,
                                     @Nullable String errorMessageTemplate,
                                     Object @Nullable ... errorMessageArgs);
 
    /**
     * 其他的一些checkArgument函数也仅仅是上面函数的一个变种,这里我们就不一一列出来了,都很简单
     */
 
    /**
     * 用来检查对象的某些状态,不满足状态则抛出IllegalStateException异常
     */
    public static void checkState(boolean expression);
 
    /**
     * 其他的一些checkState函数和checkArgument函数类似,都是在定义异常详情。不一一列出
     */
 
    /**
     * 用来检查对象是否为null,如果为空则抛出NullPointerException异常,否则返回该对象
     */
    public static <T extends @NonNull Object> T checkNotNull(T reference);
 
    /**
     * 其他的一些checkNotNull函数和checkArgument函数类似,都是在定义异常详情。不一一列出
     */
 
    /**
     * 检查index作为索引值对某个列表、字符串或数组是否有效。index>=0 && index<size,讲白了就是检验下标是否有效
     * 如果不满足判断添加则抛出IndexOutOfBoundsException异常
     * 返回index
     */
    public static int checkElementIndex(int index, int size);
    public static int checkElementIndex(int index, int size, @Nullable String desc);
 
    /**
     * 不满足条件的情况下帮我们组装描述信息
     */
    private static String badElementIndex(int index, int size, @Nullable String desc);
 
    /**
     * 检查index作为位置值对某个列表、字符串或数组是否有效。index>=0 && index<=size
     * 返回index
     */
    public static int checkPositionIndex(int index, int size);
    public static int checkPositionIndex(int index, int size, @Nullable String desc);
 
    /**
     * 不满足条件的情况下帮我们组装描述信息
     */
    private static String badPositionIndex(int index, int size, @Nullable String desc)
 
    /**
     * 检查[start, end]表示的位置范围对某个列表、字符串或数组是否有效
     * 如果不满足判断(start < 0 || end < start || end > size)则抛出IndexOutOfBoundsException异常
     */
    public static void checkPositionIndexes(int start, int end, int size);
 
    /**
     * 不满足条件的情况下帮我们组装描述信息
     */
    private static String badPositionIndexes(int start, int end, int size);
}

  

三 对象常见方法

       简化对象(Object)一些常见方法的实现,让我的代码更加的简练。如hashCode()、toString()、compare()方法等。guava里面针对对象的常见方法有两个重要的类Objects和ComparisonChain类。接下来我们分别对他们做一个简单的讲解。

3.1 Objects

       guava里面的Objects类里面的方法用Java7里面的Objects类都能实现。所以这里我们就直接讲Java7里面的Objects类。Objects类里面的方法非常的简单,相信大家都用过。这里咱们就简单的列出来一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
public final class Objects {
 
    /**
     * 判断两个对象是否相等(比较的是对象在内存中的地址是否相同,只有引用同一块地址的时候)
     * 即使有一个是NULL也可以做比较
     *
     * Objects.equal("a", "a"); // returns true
     * Objects.equal(null, "a"); // returns false
     * Objects.equal("a", null); // returns false
     * Objects.equal(null, null); // returns true
     */
    public static boolean equals(Object a, Object b);
 
    /**
     * 此方法的功能比较强大,不仅可以比较数值是否相同,而且还可以比较两个对象中的内容是否相同
     */
    public static boolean deepEquals(Object a, Object b);
 
    /**
     * 两个方法都是获取对象的hash code值的
     */
    public static int hashCode(Object o);
    public static int hash(Object... values);
 
    /**
     * 获取对象对应的String
     */
    public static String toString(Object o);
 
    /**
     * 获取对象的String,当对象是null的时候可以设置一个默认的String
     */
    public static String toString(Object o, String nullDefault);
 
    /**
     * 比较两个对象的大小
     */
    public static <T> int compare(T a, T b, Comparator<? super T> c);
 
    /**
     * 强制对象不能为null,否则抛出NullPointerException异常
     */
    public static <T> T requireNonNull(T obj);
    public static <T> T requireNonNull(T obj, String message);
    public static <T> T requireNonNull(T obj, Supplier<String> messageSupplier);
 
    /**
     * 判断对象是否为null
     */
    public static boolean isNull(Object obj);
 
    /**
     * 判断对象是否不为null
     */
    public static boolean nonNull(Object obj);
}

  

3.2 ComparisonChain

       在平常的代码过程中,我们经常要对两个对象做比较,Java中提供了compare/compareTo,我们需要实现一个比较器[Comparator],或者直接实现Comparable接口,不过当 对象的属性很多的时候,我们需要写大量的if else代码,代码不够优雅,Guava为我们简化了这一点,我们可以使用ComparisonChain类来优雅的实现对象之间的比较。我们直接用一个简单的实例代码来说明下ComparisonChain优势在哪里。

使用ComparisonChain之前的代码


复制代码
class Person implements Comparable<Person> {
  private String lastName;
  private String firstName;
  private int zipCode;

  public int compareTo(Person other) {
    int cmp = lastName.compareTo(other.lastName);
    if (cmp != 0) {
      return cmp;
    }
    cmp = firstName.compareTo(other.firstName);
    if (cmp != 0) {
      return cmp;
    }
    return Integer.compare(zipCode, other.zipCode);
  }
}
复制代码

使用ComparisonChain之后的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Person implements Comparable<Person> {
    private String lastName;
    private String firstName;
    private int zipCode;
 
    public int compareTo(Person other) {
 
        return ComparisonChain.start()
                .compare(this.lastName, other.lastName)
                .compare(this.firstName, other.firstName)
                .compare(this.zipCode, other.zipCode)
                .result();
    }
}

  

   上面两个代码相比,使用ComparisonChain之后我们代码一下子就简单了不少,逻辑也清晰了不少吧。无非就是依次比较了lastName,firstName,zipCode而已。

       关于ComparisonChain里面的代码实现,非常的简单。我们就不列出来了,大伙可以到源码里面去看下(有的时候源码才是最讲道理的地方)。

四 排序

       Guava给我们提供了强大的”流畅风格比较器”。排序器[Ordering类]是Guava流畅风格比较器[Comparator]的实现,它可以用来为构建复杂的比较器,以完成集合排序的功能。从实现上说,Ordering实例就是一个特殊的Comparator实例。Ordering把很多基于Comparator的静态方法(如Collections.max)包装为自己的实例方法(非静态方法),并且提供了链式调用方法,来定制和增强现有的比较器。

Ordering api

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
public abstract class Ordering<T> implements Comparator<T> {
 
    /**
     * 对可排序类型做自然排序,如数字按大小,日期按先后排序的排序器 -- NaturalOrdering
     */
    public static <C extends Comparable> Ordering<C> natural();
 
    /**
     * 把给定的Comparator转化为排序器
     */
    public static <T> Ordering<T> from(Comparator<T> comparator);
    public static <T> Ordering<T> from(Ordering<T> ordering);
 
    /**
     * 指明这几个东西的顺序,只排它们。如果没有指明是排序不了的 -- ExplicitOrdering
     * 举个例子,比如我们通过指定一个顺序 1、2、3、4、5、6、7、8、9、10
     * 这个时候要是想排序 7、8 就会根据给定的顺序排序
     */
    public static <T> Ordering<T> explicit(List<T> valuesInOrder);
    public static <T> Ordering<T> explicit(T leastValue, T... remainingValuesInOrder);
 
    /**
     * 所有需要排序的都是相等的排序器(我没发现他的应用场景) -- AllEqualOrdering
     */
    public static Ordering<Object> allEqual();
 
    /**
     * 按对象的字符串形式做字典排序的排序器 -- UsingToStringOrdering
     */
    public static Ordering<Object> usingToString();
 
    /**
     * 随意排序器 -- ArbitraryOrdering
     */
    public static Ordering<Object> arbitrary();
 
    /**
     * 将当前排序器置反(顺序反) -- ReverseOrdering
     */
    public <S extends T> Ordering<S> reverse();
 
    /**
     * 使用当前排序器,但额外把null值排到最前面 -- NullsFirstOrdering
     */
    public <S extends T> Ordering<S> nullsFirst();
 
    /**
     * 使用当前排序器,但额外把null值排到最后面 -- NullsLastOrdering
     */
    public <S extends T> Ordering<S> nullsLast();
 
    /**
     * 对集合中元素调用Function,再按返回值用当前排序器排序 -- ByFunctionOrdering
     */
    public <F> Ordering<F> onResultOf(Function<F, ? extends T> function);
 
    /**
     * 对Map.Entry的对象的key排序 -- ByFunctionOrdering
     */
    <T2 extends T> Ordering<Map.Entry<T2, ?>> onKeys();
 
    /**
     * 合成另一个比较器,以处理当前排序器中的相等情况
     */
    public <U extends T> Ordering<U> compound(Comparator<? super U> secondaryComparator);
    public static <T> Ordering<T> compound(Iterable<? extends Comparator<? super T>> comparators);
 
    /**
     * 返回最小的一个对象
     */
    public <E extends T> E min(Iterator<E> iterator);
    public <E extends T> E min(Iterable<E> iterable);
    public <E extends T> E min(@Nullable E a, @Nullable E b);
    public <E extends T> E min(@Nullable E a, @Nullable E b, @Nullable E c, E... rest);
 
    /**
     * 返回最大的一个对象
     */
    public <E extends T> E max(Iterator<E> iterator);
    public <E extends T> E max(Iterable<E> iterable);
    public <E extends T> E max(@Nullable E a, @Nullable E b);
    public <E extends T> E max(@Nullable E a, @Nullable E b, @Nullable E c, E... rest);
 
    /**
     * 获取可迭代对象中最小的k个元素
     */
    public <E extends T> List<E> leastOf(Iterable<E> iterable, int k);
    public <E extends T> List<E> leastOf(Iterator<E> iterator, int k);
 
    /**
     * 获取可迭代对象中最大的k个元素
     */
    public <E extends T> List<E> greatestOf(Iterable<E> iterable, int k);
    public <E extends T> List<E> greatestOf(Iterator<E> iterator, int k);
 
    /**
     * 对可迭代对象排序
     */
    public <E extends T> List<E> sortedCopy(Iterable<E> elements);
 
    /**
     * 对可迭代对象排序,会生成一个ImmutableList不可变集合
     */
    public <E extends T> ImmutableList<E> immutableSortedCopy(Iterable<E> elements);
 
    /**
     * 判断可迭代对象是否已按排序器排序:允许有排序值相等的元素,迭代后的第一个的每个元素是大于或等于在它之前
     */
    public boolean isOrdered(Iterable<? extends T> iterable);
 
    /**
     * 判断可迭代对象是否已按排序器排序:不允许有排序值相等的元素,迭代后的第一个的每个元素是大于在它之前
     */
    public boolean isStrictlyOrdered(Iterable<? extends T> iterable);
 
}

   Ordering的几个简单使用实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Test
 public void ordering() {
     List<String> list = Lists.newArrayList();
     list.add("a");
     list.add("c");
     list.add("b");
 
     // 对可排序类型做自然排序,如数字按大小,日期按先后排序的排序器
     Ordering<String> naturalOrdering = Ordering.natural();
     List<String> naturalRetList = naturalOrdering.sortedCopy(list);
     naturalRetList.forEach(System.out::println);
     System.out.println("---------------");
 
     // 把一个比较器转换成Ordering
     Ordering<String> fromComparatorOrdering = Ordering.from(String::compareTo);
     List<String> fromComparatorList = fromComparatorOrdering.sortedCopy(list);
     fromComparatorList.forEach(System.out::println);
 
     // 获取最小的一个对象
     String mimValue = naturalOrdering.min(list);
 }

  

五 Throwables

       guava提供的Throwables类里面的一些方法,可以很方便的简化异常和错误的传播与检查。

Throwables api

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
public final class Throwables {
 
    /**
     * 1. throwable参数为null的时候抛出NullPointerException异常
     * 2. throwable参数不为null的时候,Throwable类型为 X 的时候,异常继续往上抛出
     */
    public static <X extends Throwable> void throwIfInstanceOf(
            Throwable throwable, Class<X> declaredType) throws X;
 
    /**
     * throwable参数不为null的时候,Throwable类型为 X 的时候,异常抛出
     */
    public static <X extends Throwable> void propagateIfInstanceOf(
            @Nullable Throwable throwable, Class<X> declaredType) throws X;
 
    /**
     * throwable类型为Error或RuntimeException才抛出
     */
    public static void throwIfUnchecked(Throwable throwable);
 
    /**
     * throwable类型为Error或RuntimeException才抛出
     */
    public static void propagateIfPossible(@Nullable Throwable throwable);
 
    /**
     * throwable类型为X, Error或RuntimeException才抛出
     */
    public static <X extends Throwable> void propagateIfPossible(
            @Nullable Throwable throwable, Class<X> declaredType) throws X;
 
    /**
     * throwable类型为X1, X2, Error或RuntimeException才抛出
     */
    public static <X1 extends Throwable, X2 extends Throwable> void propagateIfPossible(
            @Nullable Throwable throwable, Class<X1> declaredType1, Class<X2> declaredType2)
            throws X1, X2;
 
    /**
     * 如果Throwable是Error或RuntimeException,直接抛出;否则把Throwable包装成RuntimeException抛出。返回类型是RuntimeException
     */
    public static RuntimeException propagate(Throwable throwable);
 
    /**
     * 返回异常最里面的原因 -- 方便我们查找原因
     */
    public static Throwable getRootCause(Throwable throwable);
 
    /**
     * 获取一个Throwable的原因链的列表
     */
    public static List<Throwable> getCausalChain(Throwable throwable);
 
    /**
     * 返回包含toString()的结果字符串,随后完整抛出,递归的堆栈跟踪
     */
    public static String getStackTraceAsString(Throwable throwable);
 
}
posted on   Code2020  阅读(300)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示

目录导航