当前位置:   article > 正文

Google Guava常用工具类入门使用介绍及样例说明_guava工具类

guava工具类

一 概述

工具类将经常用的一些方法进行了封装,遇到相同的场景时不需要重复造轮子,从而大量节省开发人员时间和提高工作效率,Guava就是谷歌发布的高效率的方法的工具包。Guava的优势:

  • API的设计高效简洁,已经被大量使用验证过,证明了它的稳定和可靠
  • 能够节省研发人员的开发时间,能够提高工作效率
  • 代码更加简洁简单,可读性更高
    Guava工程包含了若干被Google的Java项目广泛依赖的核心库,本文将从三个方面来进行介绍:基本工具、集合工具、字符串工具

二 基础工具

1.Optional

Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException)本质上是一个包含有可选值的包装类,这意味着 Optional 类既可以含有对象也可以为空。Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。

Optional 类的引入很好的解决空指针异常。

// Optional<T>表示可能为null的T类型引用,但Optional从不会包含null值引用
Optional<Integer> possible = Optional.of(5);
System.out.println("is present:" + possible.isPresent()); // returns true
System.out.println("possible value:" + possible.get()); // returns 5
  • 1
  • 2
  • 3
  • 4

2.Objects.equals

当一个对象中的字段可以为null时,实现Object.equals方法会很痛苦,因为不得不分别对它们进行null检查,使用Objects.equal帮助你执行null敏感的equals判断,从而避免抛出NullPointerException

// 使用Objects.equal帮助你执行null敏感的equals判断,从而避免抛出NullPointerException
System.out.println(Objects.equal("a", "a")); // returns true
System.out.println(Objects.equal(null, "a")); // returns false
System.out.println(Objects.equal("a", null)); // returns false
System.out.println(Objects.equal(null, null)); // returns true
  • 1
  • 2
  • 3
  • 4
  • 5

3.Objects.hash

Objects.hashCode方法可以快速重写Java对象的hashCode方法,基于对象的指定字段来计算散列值,避免自己手动生成。

@Test
public int test() {
	Person person = new Person("zhao", "si", 51);
	Person pre = new Person("zhang", "fei", 86);
	Person back = new Person("zhang", "fei", 86);
	// Guava的Objects.hashCode(Object...)会对传入的字段序列计算出合理的、顺序敏感的散列值
	// 可以使用Objects.hashCode(field1, field2, …, fieldn)来代替手动计算散列值
	System.out.println("person hash code:" + person.hashCode());// person hash code:-703024680
	System.out.println("pre hash code:" + pre.hashCode());// pre hash code:-320142505
	System.out.println("back hash code:" + back.hashCode());// back hash code:-320142505
}
 
@Override
public int hashCode() {
	return Objects.hashCode(lastName, firstName, zipCode);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

4.MoreObjects.toStringHelper

MoreObjects.toStringHelper可以轻松编写有用的toString方法,主要用于Java对象的字段打印显示。

// 使用 MoreObjects.toStringHelper可以轻松编写有用的toString方法
// Returns "ClassName{x=1}" GuavaTest{x=1}
System.out.println(MoreObjects.toStringHelper(this).add("x", 1));
// Returns "MyObject{x=1}"
System.out.println(MoreObjects.toStringHelper("MyObject").add("x", 1));
  • 1
  • 2
  • 3
  • 4
  • 5

5.ComparisonChain-比较器链

ComparisonChain执行一种懒比较:它执行比较操作直至发现非零的结果,在那之后的比较输入将被忽略。该工具类方便我们快速实现比较的功能。

@Override
public int test() {
	Person pre = new Person("zhang", "fei", 86);
	Person back = new Person("zhang", "fei", 86);
	int compareRes = pre.compareTo(back);
	System.out.println("compare res:" + compareRes); // compare res:0
	System.out.println("equals res:" + pre.equals(back));// equals res:true
	System.out.println("equals res:" + pre.equals(person));// equals res:false
}
@Override
public int compareTo(@NotNull Person o) {
	return ComparisonChain.start().compare(getFirstName(), o.getFirstName())
                .compare(getLastName(), o.getLastName())
                .compare(getZipCode(), o.getZipCode())
                .result();
}       
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

6.Preconditions-前置条件判断

// Preconditions类中提供了若干前置条件判断的实用方法
int i = 5, j = 3;
Preconditions.checkArgument(i >= 0, "Argument was %s but expected nonnegative", i);
Preconditions.checkArgument(i > j, "Expected i < j, but %s > %s", i, j);  
  • 1
  • 2
  • 3
  • 4

三 集合工具

不可变对象有很多优点,包括:

  • 当对象被不可信的库调用时,不可变形式是安全的;
  • 不可变对象被多个线程调用时,不存在竞态条件问题;
  • 不可变集合不需要考虑变化,因此可以节省时间和空间。所有不可变的集合都比它们的可变形式有更好的内存利用率(分析和测试细节);
  • 不可变对象因为有固定不变,可以作为常量来安全使用。

1.ImmutableSet-不可变集合

    ImmutableSet<String> COLOR_NAMES = ImmutableSet.of("red", "orange", "yellow", "green", "blue", "purple");
       
    ImmutableSet<String> set = ImmutableSet.of("a", "b", "c", "a");
    System.out.println(ImmutableSet.copyOf(list));// [a, b, c]
    System.out.println(set.asList());// [a, b, c]
       
    System.out.println(COLOR_NAMES.asList());// [red, orange, yellow, green, blue, purple]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2.ImmutableList-不可变列表

 ImmutableList<String> list = ImmutableList.of("a", "b", "c", "a");
 System.out.println(list.asList());// [a, b, c, a]
  • 1
  • 2

3.HashMultimap-不可变映射

同一个Key可放多个值,值不可以重复

 // 替换Map<K,Set<V>>结构
 HashMultimap<String, String> multimap = HashMultimap.create();
 multimap.put("key1", "value");
 multimap.put("key1", "value1");
 multimap.put("key1", "value");
 System.out.println(multimap.get("key1"));// [value, value1]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

4.ArrayListMultimap

ArrayListMultimap可用于替换Map<K,List<V>>和Map<K,Set<V>>结构,适用于键为单个元素,值为集合的场景,值可以重复

 // 替换Map<K,List<V>>结构
 ArrayListMultimap<String, String> listMultimap = ArrayListMultimap.create();
 listMultimap.put("key", "value-1");
 listMultimap.put("key", "value-2");
 listMultimap.put("key", "value-3");
 System.out.println(listMultimap.get("key"));// [value-1, value-2, value-3]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

5.HashMultiset

HashMultiset可以多添加相等的元素,比较适用于键为元素,值为计数的场景,类似于没有元素顺序限制的ArrayList<E>

 // 1.没有元素顺序限制的ArrayList<E> 2.Map<E, Integer>,键为元素,值为计数
 HashMultiset<String> counts = HashMultiset.create();
 counts.add("alibaba");
 counts.add("ant", 5);
 System.out.println(counts.count("alibaba"));// 1
 System.out.println(counts.count("ant")); // 5
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

例如当我们去统计一个字符串数组当中各个字符串出现的次数,两种实现方式如下,可以看出Guava工具的简洁性。

 	@Test
    public void count(){
        String[] array = {"A", "B", "C","A", "B", "C", "D", "F","D", "F", "G", "U"};
        List<String> strs = Lists.asList("A", array);
        // 1.常规方式实现计数
        HashMap<String,Integer> countHashMap = Maps.newHashMap();
        for (String s : strs) {
            if (java.util.Objects.isNull(countHashMap.get(s))) {
                countHashMap.put(s, 1);
            }else{
                countHashMap.put(s, countHashMap.get(s) + 1);
            }
        }
        // {A=3, B=2, C=2, D=2, U=1, F=2, G=1}
        System.out.println(countHashMap);
        // 2.Guava方式实现计数
        HashMultiset<String> countHashMultiset = HashMultiset.create();
        countHashMultiset.addAll(strs);
        // [A x 3, B x 2, C x 2, D x 2, U, F x 2, G]
        System.out.println(countHashMultiset);
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

6.BiMap-双向映射同步

 // 实现键值对的双向映射需要维护两个单独的map,并保持它们间的同步
 BiMap<String, Integer> userId = HashBiMap.create();
 userId.put("zhan", 2207);
 userId.put("zhao", 3312);
 System.out.println(userId.get("zhao") + ":" + userId.inverse().get(3312));// 3312:zhao
 System.out.println(userId.get("zhan") + ":" + userId.inverse().get(2207));// 2207:zhan
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

7.Table

你可能会遇到使用多个键做索引的时候可能会用类似Map<FirstName, Map<LastName, Person>>的实现方式,这种方式不但很丑陋,而且使用上也不友好。因此Guava提供了Table新结构来解决这种场景。

 Table<String, String, Integer> table = HashBasedTable.create();
 table.put("A", "B", 1);
 table.put("A", "C", 2);
 table.put("B", "D", 3);
 for (Cell<String, String, Integer> cell : table.cellSet()) {
     System.out.println(cell.getRowKey() + " " + cell.getColumnKey() + " " + cell.getValue());
  }
 /* print res:
  * A B 1
  * A C 2
  * B D 3
  */
 Map<String, Map<String, Integer>> map = table.rowMap();
 for (String row : map.keySet()) {
    Map<String, Integer> tmp = map.get(row);
    for (Entry<String, Integer> pair : tmp.entrySet()) {
        System.out.println(row + " " + pair.getKey() + " " + pair.getValue());
    }
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

8.集合初始化方式

开发过程中集合初始化过程是必不可少的,你不会一直都是new一个新的对象吧,试试下面这种方式感觉会更棒。

 /*集合初始化方式*/
 List<String> theseElements = Lists.newArrayList("alpha", "beta", "gamma");
 List<String> exactly = Lists.newArrayListWithCapacity(4);
 List<String> approx = Lists.newArrayListWithExpectedSize(4);
 Set<String> approxSet = Sets.newHashSetWithExpectedSize(4);

 List<Integer> countUp = Ints.asList(1, 2, 3, 4, 5);
 List<Integer> countDown = Lists.reverse(countUp);
 List<List<Integer>> parts = Lists.partition(countUp, 2);
 System.out.println(countDown); // {5, 4, 3, 2, 1}
 System.out.println(parts); //{{1,2}, {3,4}, {5}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

9.求集合交集子集

针对于Set集合结构,可能会存在求两个集合相同元素的场景或者求两个集合的所有组合,这不就是求交集和笛卡尔积嘛,Guava也给我们提供了快速方法可以参考一手

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/天景科技苑/article/detail/828865
推荐阅读
相关标签