Guava工具包使用
Google Guava是一个强大的Java工具库,提供了集合、缓存、字符串处理、并发工具等实用功能。本文详细介绍Guava工具包的使用方法和最佳实践。
📋 目录
🎯 一、Maven依赖
1.1 添加依赖
xml
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>32.1.3-jre</version>
</dependency>🎯 二、集合工具
2.1 Lists工具类
创建List:
java
// 创建可变List
List<String> list1 = Lists.newArrayList("a", "b", "c");
List<Integer> list2 = Lists.newArrayList(1, 2, 3);
// 创建指定容量的List
List<String> list3 = Lists.newArrayListWithCapacity(100);
// 创建LinkedList
List<String> list4 = Lists.newLinkedList();
// 反转List
List<String> reversed = Lists.reverse(list1);List分片:
java
List<Integer> numbers = Lists.newArrayList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 将List分成大小为3的子列表
List<List<Integer>> partitions = Lists.partition(numbers, 3);
// 结果:[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
// 转换List
List<String> strings = Lists.transform(numbers, n -> "Number: " + n);字符串转List:
java
// 从字符序列创建List
List<Character> chars = Lists.charactersOf("Hello");
// 结果:[H, e, l, l, o]2.2 Maps工具类
创建Map:
java
// 创建HashMap
Map<String, Integer> map1 = Maps.newHashMap();
// 创建LinkedHashMap
Map<String, Integer> map2 = Maps.newLinkedHashMap();
// 创建TreeMap
Map<String, Integer> map3 = Maps.newTreeMap();
// 创建ConcurrentHashMap
Map<String, Integer> map4 = Maps.newConcurrentMap();Map转换:
java
Map<String, String> map = Maps.newHashMap();
map.put("key1", "value1");
map.put("key2", "value2");
// 转换Map的Key
Map<String, String> keyTransformed = Maps.transformKeys(map, k -> k.toUpperCase());
// 结果:{KEY1=value1, KEY2=value2}
// 转换Map的Value
Map<String, String> valueTransformed = Maps.transformValues(map, v -> v.toUpperCase());
// 结果:{key1=VALUE1, key2=VALUE2}
// 转换Entry
Map<String, Integer> entryTransformed = Maps.transformEntries(
map,
(k, v) -> k.length() + v.length()
);Map差异:
java
Map<String, Integer> map1 = ImmutableMap.of("a", 1, "b", 2, "c", 3);
Map<String, Integer> map2 = ImmutableMap.of("b", 2, "c", 4, "d", 5);
// 获取两个Map的差异
MapDifference<String, Integer> diff = Maps.difference(map1, map2);
// 只在左边存在的条目
Map<String, Integer> onlyLeft = diff.entriesOnlyOnLeft();
// 结果:{a=1}
// 只在右边存在的条目
Map<String, Integer> onlyRight = diff.entriesOnlyOnRight();
// 结果:{d=5}
// 键相同但值不同的条目
Map<String, MapDifference.ValueDifference<Integer>> diffValues = diff.entriesDiffering();
// 结果:{c=(3, 4)}
// 键值都相同的条目
Map<String, Integer> common = diff.entriesInCommon();
// 结果:{b=2}Map过滤:
java
Map<String, Integer> map = ImmutableMap.of("a", 1, "b", 2, "c", 3, "d", 4);
// 过滤Map
Map<String, Integer> filtered = Maps.filterKeys(map, k -> k.startsWith("a"));
// 结果:{a=1}
Map<String, Integer> filtered2 = Maps.filterValues(map, v -> v > 2);
// 结果:{c=3, d=4}
Map<String, Integer> filtered3 = Maps.filterEntries(map, e -> e.getValue() % 2 == 0);
// 结果:{b=2, d=4}2.3 Sets工具类
创建Set:
java
// 创建HashSet
Set<String> set1 = Sets.newHashSet("a", "b", "c");
// 创建LinkedHashSet
Set<String> set2 = Sets.newLinkedHashSet();
// 创建TreeSet
Set<String> set3 = Sets.newTreeSet();
// 创建ConcurrentHashSet
Set<String> set4 = Sets.newConcurrentHashSet();Set运算:
java
Set<Integer> set1 = Sets.newHashSet(1, 2, 3, 4, 5);
Set<Integer> set2 = Sets.newHashSet(4, 5, 6, 7, 8);
// 并集
Set<Integer> union = Sets.union(set1, set2);
// 结果:[1, 2, 3, 4, 5, 6, 7, 8]
// 交集
Set<Integer> intersection = Sets.intersection(set1, set2);
// 结果:[4, 5]
// 差集(在set1中但不在set2中)
Set<Integer> difference = Sets.difference(set1, set2);
// 结果:[1, 2, 3]
// 对称差集(在任一集合中但不在两个集合的交集中)
Set<Integer> symmetricDifference = Sets.symmetricDifference(set1, set2);
// 结果:[1, 2, 3, 6, 7, 8]幂集:
java
Set<String> set = Sets.newHashSet("a", "b", "c");
// 获取所有子集
Set<Set<String>> powerSet = Sets.powerSet(set);
// 结果:包含8个子集(2^3)
// [[], [a], [b], [c], [a, b], [a, c], [b, c], [a, b, c]]笛卡尔积:
java
Set<Integer> set1 = Sets.newHashSet(1, 2);
Set<String> set2 = Sets.newHashSet("a", "b");
// 笛卡尔积
Set<List<Object>> cartesianProduct = Sets.cartesianProduct(set1, set2);
// 结果:[[1, a], [1, b], [2, a], [2, b]]2.4 Immutable集合
不可变集合创建:
java
// 不可变List
ImmutableList<String> immutableList = ImmutableList.of("a", "b", "c");
ImmutableList<String> list = ImmutableList.<String>builder()
.add("a")
.add("b")
.addAll(anotherList)
.build();
// 不可变Set
ImmutableSet<String> immutableSet = ImmutableSet.of("a", "b", "c");
// 不可变Map
ImmutableMap<String, Integer> immutableMap = ImmutableMap.of("a", 1, "b", 2);
ImmutableMap<String, Integer> map = ImmutableMap.<String, Integer>builder()
.put("a", 1)
.put("b", 2)
.build();
// 从现有集合创建
List<String> list = Arrays.asList("a", "b", "c");
ImmutableList<String> immutable = ImmutableList.copyOf(list);不可变集合的优势:
- 线程安全
- 防止意外修改
- 性能优化
- 作为常量使用
🎯 三、缓存工具
3.1 CacheBuilder
创建缓存:
java
// 基本缓存
Cache<String, String> cache = CacheBuilder.newBuilder()
.maximumSize(1000) // 最大缓存条目数
.expireAfterWrite(10, TimeUnit.MINUTES) // 写入后10分钟过期
.expireAfterAccess(5, TimeUnit.MINUTES) // 访问后5分钟过期
.removalListener(new RemovalListener<String, String>() {
@Override
public void onRemoval(RemovalNotification<String, String> notification) {
System.out.println("缓存被移除: " + notification.getKey());
}
})
.build();
// 放入缓存
cache.put("key1", "value1");
// 获取缓存
String value = cache.getIfPresent("key1");
// 获取或计算
String value2 = cache.get("key2", () -> computeValue("key2"));LoadingCache:
java
// 带加载器的缓存
LoadingCache<String, String> loadingCache = CacheBuilder.newBuilder()
.maximumSize(1000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.build(new CacheLoader<String, String>() {
@Override
public String load(String key) {
// 当缓存中不存在时,自动加载
return fetchDataFromDatabase(key);
}
});
// 自动加载
String value = loadingCache.get("key1");
// 批量加载
Map<String, String> values = loadingCache.getAll(Arrays.asList("key1", "key2", "key3"));缓存配置示例:
java
// 带权重和弱引用的缓存
Cache<String, byte[]> cache = CacheBuilder.newBuilder()
.maximumWeight(10000) // 最大权重
.weigher((key, value) -> value.length) // 权重计算
.weakKeys() // 弱引用Key
.weakValues() // 弱引用Value
.recordStats() // 记录统计信息
.build();
// 获取统计信息
CacheStats stats = cache.stats();
System.out.println("命中率: " + stats.hitRate());
System.out.println("平均加载时间: " + stats.averageLoadPenalty());🎯 四、字符串工具
4.1 Joiner
字符串拼接:
java
// 使用分隔符拼接
List<String> list = Arrays.asList("a", "b", "c", null, "d");
String joined = Joiner.on(",").skipNulls().join(list);
// 结果:"a,b,c,d"
// 用null替换
String joined2 = Joiner.on(",").useForNull("NULL").join(list);
// 结果:"a,b,c,NULL,d"
// 拼接Map
Map<String, Integer> map = ImmutableMap.of("a", 1, "b", 2);
String mapJoined = Joiner.on(",").withKeyValueSeparator("=").join(map);
// 结果:"a=1,b=2"
// 追加到StringBuilder
StringBuilder sb = new StringBuilder("前缀:");
Joiner.on(",").appendTo(sb, list);
// 结果:"前缀:a,b,c,d"4.2 Splitter
字符串分割:
java
// 基本分割
String str = "a,b,c,d";
List<String> list = Splitter.on(",").splitToList(str);
// 结果:[a, b, c, d]
// 分割并去除空白
String str2 = "a, b, c , d";
List<String> list2 = Splitter.on(",").trimResults().splitToList(str2);
// 结果:[a, b, c, d]
// 移除空字符串
String str3 = "a,,b,,c";
List<String> list3 = Splitter.on(",").omitEmptyStrings().splitToList(str3);
// 结果:[a, b, c]
// 限制分割次数
String str4 = "a,b,c,d,e";
List<String> list4 = Splitter.on(",").limit(3).splitToList(str4);
// 结果:[a, b, c,d,e]
// 正则表达式分割
String str5 = "a b c d";
List<String> list5 = Splitter.onPattern("\\s+").splitToList(str5);
// 结果:[a, b, c, d]
// 固定长度分割
String str6 = "abcdefghij";
List<String> list6 = Splitter.fixedLength(3).splitToList(str6);
// 结果:[abc, def, ghi, j]4.3 Strings工具类
字符串判断和操作:
java
// 判断是否为空或null
Strings.isNullOrEmpty(""); // true
Strings.isNullOrEmpty(null); // true
Strings.isNullOrEmpty("hello"); // false
// 空字符串替换为null
String result = Strings.emptyToNull(""); // null
String result2 = Strings.emptyToNull("a"); // "a"
// null替换为空字符串
String result3 = Strings.nullToEmpty(null); // ""
String result4 = Strings.nullToEmpty("a"); // "a"
// 获取公共前缀
String prefix = Strings.commonPrefix("abc", "abd"); // "ab"
// 获取公共后缀
String suffix = Strings.commonSuffix("abc", "dbc"); // "bc"
// 重复字符串
String repeated = Strings.repeat("abc", 3); // "abcabcabc"
// 填充字符串
String padded = Strings.padStart("123", 5, '0'); // "00123"
String padded2 = Strings.padEnd("123", 5, '0'); // "12300"
// 补齐到指定长度
String truncated = Strings.truncate("hello world", 5); // "hello"🎯 五、并发工具
5.1 ListenableFuture
可监听的Future:
java
// 创建ListeningExecutorService
ListeningExecutorService executor = MoreExecutors.listeningDecorator(
Executors.newFixedThreadPool(10)
);
// 提交任务并返回ListenableFuture
ListenableFuture<String> future = executor.submit(() -> {
Thread.sleep(1000);
return "Result";
});
// 添加回调
Futures.addCallback(future, new FutureCallback<String>() {
@Override
public void onSuccess(String result) {
System.out.println("成功: " + result);
}
@Override
public void onFailure(Throwable t) {
System.out.println("失败: " + t.getMessage());
}
}, executor);
// 转换Future
ListenableFuture<Integer> lengthFuture = Futures.transform(
future,
String::length,
executor
);
// 组合多个Future
ListenableFuture<String> future1 = executor.submit(() -> "Hello");
ListenableFuture<String> future2 = executor.submit(() -> "World");
ListenableFuture<String> combined = Futures.transformAsync(
future1,
result1 -> Futures.transform(future2, result2 -> result1 + " " + result2, executor),
executor
);5.2 RateLimiter
限流器:
java
// 创建限流器(每秒允许2个请求)
RateLimiter rateLimiter = RateLimiter.create(2.0);
// 获取许可(阻塞)
rateLimiter.acquire(); // 等待获取许可
// 尝试获取许可(非阻塞)
if (rateLimiter.tryAcquire()) {
// 获取成功,执行操作
} else {
// 获取失败,拒绝请求
}
// 尝试获取许可(带超时)
if (rateLimiter.tryAcquire(5, TimeUnit.SECONDS)) {
// 5秒内获取成功
}
// 获取多个许可
rateLimiter.acquire(5); // 获取5个许可
// 动态调整速率
rateLimiter.setRate(10.0); // 调整为每秒10个限流器示例:
java
// API限流示例
public class ApiLimiter {
private final RateLimiter rateLimiter = RateLimiter.create(100.0); // 每秒100个请求
public void handleRequest() {
if (rateLimiter.tryAcquire()) {
// 处理请求
processRequest();
} else {
// 限流,拒绝请求
throw new RateLimitException("请求过于频繁");
}
}
}🎯 六、IO工具
6.1 Files工具类
文件操作:
java
// 读取文件所有行
List<String> lines = Files.readLines(new File("data.txt"), Charsets.UTF_8);
// 逐行读取(流式)
Files.asCharSource(new File("data.txt"), Charsets.UTF_8)
.lines()
.forEach(line -> System.out.println(line));
// 写入文件
Files.asCharSink(new File("output.txt"), Charsets.UTF_8, FileWriteMode.APPEND)
.write("Hello World");
// 复制文件
Files.copy(new File("source.txt"), new File("dest.txt"));
// 移动文件
Files.move(new File("old.txt"), new File("new.txt"));
// 文件比较
boolean equal = Files.equal(file1, file2);
// 计算文件Hash
HashCode hash = Files.asByteSource(new File("file.txt")).hash(Hashing.md5());
// 读取文件为字节
byte[] bytes = Files.asByteSource(new File("file.txt")).read();
// 写入字节到文件
Files.asByteSink(new File("file.txt")).write(bytes);6.2 CharSource和CharSink
字符源和字符接收器:
java
// 从字符串创建CharSource
CharSource source = CharSource.wrap("Hello World");
// 从文件创建
CharSource fileSource = Files.asCharSource(new File("file.txt"), Charsets.UTF_8);
// 合并多个CharSource
CharSource combined = CharSource.concat(source1, source2, source3);
// 读取内容
String content = source.read();
// 读取第一行
String firstLine = source.readFirstLine();
// 写入到CharSink
CharSink sink = Files.asCharSink(new File("output.txt"), Charsets.UTF_8);
sink.write("Content");🎯 七、其他实用工具
7.1 Preconditions
前置条件检查:
java
// 检查参数不为null
String name = Preconditions.checkNotNull(param, "参数不能为null");
// 检查参数不为null(带格式消息)
String name2 = Preconditions.checkNotNull(
param,
"参数%s不能为null",
"name"
);
// 检查表达式为true
Preconditions.checkArgument(count > 0, "count必须大于0");
Preconditions.checkArgument(
count > 0,
"count必须大于0,当前值: %s",
count
);
// 检查状态
Preconditions.checkState(isValid, "状态无效");
// 检查索引
Preconditions.checkElementIndex(index, list.size());
Preconditions.checkPositionIndex(index, list.size());
// 检查位置范围
Preconditions.checkPositionIndexes(start, end, list.size());7.2 Optional使用
Optional增强:
java
import com.google.common.base.Optional;
// 创建Optional
Optional<String> optional = Optional.of("value");
Optional<String> absent = Optional.absent();
Optional<String> fromNullable = Optional.fromNullable(null);
// 判断是否存在
if (optional.isPresent()) {
// 处理值
}
// 获取值或默认值
String value = optional.or("default");
// 获取值或抛出异常
String value2 = optional.or(IllegalStateException::new);
// 转换Optional
Optional<Integer> length = optional.transform(String::length);
// 多个Optional组合
Optional<String> opt1 = Optional.of("Hello");
Optional<String> opt2 = Optional.of("World");
Optional<String> combined = opt1.flatMap(s1 ->
opt2.transform(s2 -> s1 + " " + s2)
);7.3 Stopwatch
计时器:
java
// 创建计时器
Stopwatch stopwatch = Stopwatch.createStarted();
// 执行操作
doSomething();
// 停止计时
stopwatch.stop();
// 获取经过的时间
long elapsed = stopwatch.elapsed(TimeUnit.MILLISECONDS);
System.out.println("耗时: " + elapsed + "ms");
// 重置计时器
stopwatch.reset();
stopwatch.start();
// 检查是否正在运行
if (stopwatch.isRunning()) {
// 计时器正在运行
}7.4 Range
范围操作:
java
// 创建范围
Range<Integer> range1 = Range.closed(1, 10); // [1, 10]
Range<Integer> range2 = Range.open(1, 10); // (1, 10)
Range<Integer> range3 = Range.closedOpen(1, 10); // [1, 10)
Range<Integer> range4 = Range.openClosed(1, 10); // (1, 10]
// 无界范围
Range<Integer> range5 = Range.atLeast(5); // [5, +∞)
Range<Integer> range6 = Range.atMost(10); // (-∞, 10]
Range<Integer> range7 = Range.all(); // (-∞, +∞)
// 范围操作
boolean contains = range1.contains(5); // true
boolean isEmpty = range1.isEmpty(); // false
Integer lower = range1.lowerEndpoint(); // 1
Integer upper = range1.upperEndpoint(); // 10
// 范围交集
Range<Integer> intersection = range1.intersection(range2);
// 范围并集
RangeSet<Integer> rangeSet = TreeRangeSet.create();
rangeSet.add(range1);
rangeSet.add(range2);
// 检查范围是否连接
boolean connected = range1.isConnected(range2);7.5 Hashing
哈希工具:
java
// MD5哈希
HashCode md5 = Hashing.md5().hashString("hello", Charsets.UTF_8);
String md5Hex = md5.toString();
// SHA256哈希
HashCode sha256 = Hashing.sha256().hashString("hello", Charsets.UTF_8);
// 一致性哈希
HashFunction hashFunction = Hashing.murmur3_128();
int bucket = Hashing.consistentHash(hashFunction.hashString("key", Charsets.UTF_8), 10);
// 计算文件哈希
File file = new File("data.txt");
HashCode fileHash = Files.asByteSource(file).hash(Hashing.md5());📖 学习资源
官方文档
视频教程
✅ 学习检查清单
- [ ] 已掌握集合工具的使用方法
- [ ] 已掌握缓存工具的使用
- [ ] 已掌握字符串工具的使用
- [ ] 已了解并发工具的使用
- [ ] 已掌握IO工具的使用
- [ ] 已熟悉其他实用工具
上一章节:代码规范概览
下一章节:Apache Commons使用
返回目录:代码规范