深入解析: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 不可变集合:ImmutableList、ImmutableMap、ImmutableSet
不可变集合一旦创建就不能被修改,这有助于:
- 防止意外修改数据
- 线程安全
- 可作为常量使用
// 创建不可变列表
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 新集合类型:Multimap、Multiset、BiMap
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 集合操作工具:Lists、Maps、Sets
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

浙公网安备 33010602011771号