深入解析:Google Guava:现代Java编程的秘密武器

1. Guava入门基础

1.1 什么是Google Guava

Google Guava是由Google开发并开源的一个Java核心库,它提供了许多JDK没有的功能,帮助开发者编写更简洁、更安全、更高效的代码。

Guava的核心目标包括:

  • 提供实用的集合类型和工具类
  • 增强I/O功能
  • 实用的并发工具
  • 常用的字符串处理功能
  • 缓存实现和其他有用的工具

1.2 Guava的发展历程与版本演进

Guava最初源于Google内部的"Google Collections Library",于2010年开源并更名为Guava。Guava遵循语义化版本控制,定期发布新版本,持续添加新功能和改进现有功能。

主要里程碑:

  • 2010年:首次发布为开源项目
  • 持续更新:每季度发布新版本
  • 功能扩展:从单纯的集合库发展为综合性工具库

1.3 为什么选择Guava

使用Guava的主要优势:

提高开发效率

// 不使用Guava的传统写法
List<String> list = new ArrayList<>();
  list.add("apple");
  list.add("banana");
  list.add("orange");
  // 使用Guava的简洁写法
  List<String> list = Lists.newArrayList("apple", "banana", "orange");

减少样板代码

// 传统方式检查null
if (name != null && !name.isEmpty()) {

// 处理name
}
// 使用Guava的Strings工具
if (!Strings.isNullOrEmpty(name)) {

// 处理name
}

增强代码安全性

// 创建不可变集合,防止意外修改
ImmutableList<String> immutableList = ImmutableList.of("a", "b", "c");
  // immutableList.add("d"); // 编译时报错

1.4 环境搭建与依赖配置

在Maven项目中添加Guava依赖:

<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>32.1.3-jre</version>
</dependency>

在Gradle项目中添加依赖:

implementation 'com.google.guava:guava:32.1.3-jre'

简单的使用示例:

import com.google.common.collect.Lists;
import com.google.common.base.Strings;
public class GuavaExample {

public static void main(String[] args) {

// 使用Guava创建列表
List<String> fruits = Lists.newArrayList("apple", "banana", "orange");
  // 使用Guava字符串工具
  String name = "  Lingma  ";
  if (!Strings.isNullOrEmpty(name)) {
  
  System.out.println("Hello, " + name.trim());
  }
  }
  }

2. 集合工具类详解

2.1 不可变集合:ImmutableListImmutableMapImmutableSet

不可变集合一旦创建就不能被修改,这有助于:

  • 防止意外修改数据
  • 线程安全
  • 可作为常量使用
// 创建不可变列表
ImmutableList<String> immutableList = ImmutableList.of("apple", "banana", "orange");
  ImmutableList<String> copiedList = ImmutableList.copyOf(Arrays.asList("one", "two", "three"));
    // 创建不可变映射
    ImmutableMap<String, Integer> immutableMap = ImmutableMap.of(
      "apple", 1,
      "banana", 2,
      "orange", 3
      );
      // 使用builder模式创建复杂不可变集合
      ImmutableMap<String, Integer> builtMap = ImmutableMap.<String, Integer>builder()
        .put("key1", 1)
        .put("key2", 2)
        .put("key3", 3)
        .build();
        // 尝试修改会抛出UnsupportedOperationException异常
        try {
        
        immutableList.add("grape");
        } catch (UnsupportedOperationException e) {
        
        System.out.println("Cannot modify immutable collection");
        }

2.2 新集合类型:MultimapMultisetBiMap

Guava提供了多种新的集合类型来解决特定问题:

// Multimap:一个键可以对应多个值
Multimap<String, String> multimap = ArrayListMultimap.create();
  multimap.put("fruit", "apple");
  multimap.put("fruit", "banana");
  multimap.put("vegetable", "carrot");
  multimap.put("vegetable", "broccoli");
  System.out.println(multimap.get("fruit")); // [apple, banana]
  // Multiset:可以统计元素出现次数的集合
  Multiset<String> multiset = HashMultiset.create();
    multiset.add("apple");
    multiset.add("banana");
    multiset.add("apple");
    multiset.add("orange");
    multiset.add("apple");
    System.out.println(multiset.count("apple")); // 3
    System.out.println(multiset.elementSet()); // [apple, banana, orange]
    // BiMap:双向映射,键和值都唯一
    BiMap<String, Integer> biMap = HashBiMap.create();
      biMap.put("one", 1);
      biMap.put("two", 2);
      biMap.put("three", 3);
      System.out.println(biMap.get("one")); // 1
      System.out.println(biMap.inverse().get(2)); // two

2.3 集合操作工具:ListsMapsSets

Guava提供了丰富的静态工具方法来操作集合:

// Lists工具类
List<Integer> numbers = Lists.newArrayList(1, 2, 3, 4, 5);
  List<List<Integer>> partitions = Lists.partition(numbers, 2); // [[1, 2], [3, 4], [5]]
    // 创建笛卡尔积
    List<String> colors = Lists.newArrayList("red", "blue");
      List<String> shapes = Lists.newArrayList("circle", "square");
        List<List<String>> cartesianProduct = Lists.cartesianProduct(colors, shapes);
          // [[red, circle], [red, square], [blue, circle], [blue, square]]
          // Maps工具类
          Map<String, String> map1 = Maps.newHashMap();
            map1.put("key1", "value1");
            map1.put("key2", "value2");
            // 创建带默认值的映射
            Map<String, Integer> defaultMap = Maps.newHashMap();
              Integer value = Maps.safeGet(defaultMap, "nonexistent", 0); // 返回默认值0
              // Sets工具类
              Set<Integer> set1 = Sets.newHashSet(1, 2, 3);
                Set<Integer> set2 = Sets.newHashSet(3, 4, 5);
                  Set<Integer> union = Sets.union(set1, set2); // {1, 2, 3, 4, 5}
                    Set<Integer> intersection = Sets.intersection(set1, set2); // {3}
                      Set<Integer> difference = Sets.difference(set1, set2); // {1, 2}

2.4 集合工厂方法与创建器模式

Guava提供了多种创建集合的方式:

// 工厂方法创建集合
List<String> list = Lists.newArrayList("a", "b", "c");
  Set<Integer> set = Sets.newHashSet(1, 2, 3);
    Map<String, Integer> map = Maps.newHashMap();
      // 使用Builder模式创建复杂集合
      ImmutableList.Builder<String> builder = ImmutableList.builder();
        builder.add("first")
        .add("second")
        .addAll(Arrays.asList("third", "fourth"))
        .add("fifth");
        ImmutableList<String> result = builder.build();
          // 创建容量预设的集合
          List<String> preSizedList = Lists.newArrayListWithExpectedSize(100);
            Set<Integer> preSizedSet = Sets.newHashSetWithExpectedSize(50);

3. 函数式编程支持

3.1 Function接口与转换操作

Function接口用于将一种类型的对象转换为另一种类型:

import com.google.common.base.Function;
import com.google.common.collect.Collections2;
// 定义转换函数
Function<String, Integer> stringLengthFunction = new Function<String, Integer>() {
  
  @Override
  public Integer apply(String input) {
  
  return input.length();
  }
  };
  // 使用转换函数
  List<String> words = Arrays.asList("hello", "world", "java", "guava");
    Collection<Integer> lengths = Collections2.transform(words, stringLengthFunction);
      System.out.println(lengths); // [5, 5, 4, 5]
      // 使用Lambda表达式(Java 8+)
      Function<String, String> upperCaseFunction = String::toUpperCase;
        Collection<String> upperWords = Collections2.transform(words, upperCaseFunction);
          System.out.println(upperWords); // [HELLO, WORLD, JAVA, GUAVA]

3.2 Predicate接口与过滤操作

Predicate接口用于判断对象是否满足某种条件:

import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
// 定义谓词
Predicate<String> longWordPredicate = new Predicate<String>() {
  
  @Override
  public boolean apply(String input) {
  
  return input.length() > 4;
  }
  };
  // 使用过滤器
  List<String> words = Arrays.asList("hello", "hi", "world", "java", "go");
    Collection<String> filteredWords = Collections2.filter(words, longWordPredicate);
      System.out.println(filteredWords); // [hello, world]
      // 组合谓词
      Predicate<String> shortWordPredicate = new Predicate<String>() {
        
        @Override
        public boolean apply(String input) {
        
        return input.length() < 5;
        }
        };
        // AND组合
        Predicate<String> andPredicate = Predicates.and(longWordPredicate, shortWordPredicate);
          // OR组合
          Predicate<String> orPredicate = Predicates.or(longWordPredicate, shortWordPredicate);
            // NOT组合
            Predicate<String> notPredicate = Predicates.not(longWordPredicate);
              // 使用Lambda表达式
              Predicate<String> lambdaPredicate = s -> s.startsWith("h");
                Collection<String> startsWithH = Collections2.filter(words, lambdaPredicate);
                  System.out.println(startsWithH); // [hello, hi]

3.3 Optional类:避免空指针异常

Optional用于优雅地处理可能为空的值:

import com.google.common.base.Optional;
// 创建Optional实例
Optional<String> presentOptional = Optional.of("Hello");
  Optional<String> absentOptional = Optional.absent();
    Optional<String> fromNullableOptional = Optional.fromNullable(null);
      // 检查值是否存在
      if (presentOptional.isPresent()) {
      
      System.out.println("Value: " + presentOptional.get());
      }
      // 提供默认值
      String valueOrDefault = absentOptional.or("default");
      System.out.println(valueOrDefault); // default
      // 使用orNull获取可能为null的值
      String nullableValue = fromNullableOptional.orNull();
      System.out.println(nullableValue); // null
      // 转换Optional中的值
      Optional<Integer> lengthOptional = presentOptional.transform(String::length);
        System.out.println(lengthOptional.get()); // 5
        // 实际应用场景
        public Optional<String> findUserEmail(Long userId) {
          
          // 模拟数据库查询
          if (userId == 1L) {
          
          return Optional.of("user@example.com");
          } else {
          
          return Optional.absent();
          }
          }
          // 使用Optional
          Optional<String> email = findUserEmail(1L);
            if (email.isPresent()) {
            
            System.out.println("Email: " + email.get());
            } else {
            
            System.out.println("User not found");
            }

3.4 Fluent API设计模式实践

Fluent API让代码更加流畅易读:

import com.google.common.collect.Ordering;
// Ordering示例
List<String> words = Arrays.asList("banana", "apple", "cherry", "date");
  // 链式调用排序
  Ordering<String> byLengthOrdering = Ordering.natural()
    .onResultOf((String str) -> str.length())
    .compound(Ordering.natural());
    List<String> sortedWords = byLengthOrdering.sortedCopy(words);
      System.out.println(sortedWords); // [date, apple, banana, cherry]
      // 复杂排序示例
      List<Person> persons = Arrays.asList(
        new Person("Alice", 25),
        new Person("Bob", 30),
        new Person("Charlie", 25)
        );
        Ordering<Person> personOrdering = Ordering.natural()
          .onResultOf((Person p) -> p.getAge())
          .compound(Ordering.natural().onResultOf((Person p) -> p.getName()));
          List<Person> sortedPersons = personOrdering.sortedCopy(persons);

4. 字符串处理利器

4.1 Strings工具类的使用

Strings工具类提供了许多实用的字符串处理方法:

import com.google.common.base.Strings;
// 检查字符串是否为空或null
System.out.println(Strings.isNullOrEmpty(null)); // true
System.out.println(Strings.isNullOrEmpty("")); // true
System.out.println(Strings.isNullOrEmpty(" ")); // false
// 填充字符串
String paddedLeft = Strings.padStart("7", 3, '0');
System.out.println(paddedLeft); // "007"
String paddedRight = Strings.padEnd("7", 3, '0');
System.out.println(paddedRight); // "700"
// 重复字符串
String repeated = Strings.repeat("abc", 3);
System.out.println(repeated); // "abcabcabc"
// 获取公共前缀
String commonPrefix = Strings.commonPrefix("hello", "help");
System.out
posted @ 2026-01-26 19:49  yangykaifa  阅读(1)  评论(0)    收藏  举报