Google Guava实战

Guava不仅仅是一个工具库,更是Google工程师多年经验的结晶。它让Java代码变得优雅、简洁、高效。

Spring、MyBatis等顶级框架使用的工具库

  • 配置管理 → ImmutableMap

  • 错误码映射 → BiMap

  • 文章标签 → Multimap

  • 批量处理 → Lists.partition

  • 字符串操作 → Splitter + Joiner

添加Maven依赖

复制代码
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>32.1.3-jre</version>
</dependency>

Multimap不是线程安全的

复制代码
// 多线程环境直接使用
Multimap<String, String> map = ArrayListMultimap.create();
// 需要同步包装
Multimap<String, String> syncMap = 
    Multimaps.synchronizedMultimap(ArrayListMultimap.create());

BiMap值必须唯一

复制代码
BiMap<String, Integer> map = HashBiMap.create();
map.put("A", 1);
map.put("B", 1);  //  抛出IllegalArgumentException
// 使用forcePut强制替换
map.forcePut("B", 1);  // A被移除,B映射到1

代码量对比

|----------|---------|-----------|---------|
| 场景 | JDK代码行数 | Guava代码行数 | 减少比例 |
| 不可变Map创建 | 7行 | 3行 | 57% |
| 字符串分割处理 | 7行 | 1行 | 86% |
| 双向映射查找 | 15行 | 2行 | 87% |
| 列表批量分割 | 10行 | 1行 | 90% |

实战案例二:动态SQL生成

复制代码
public classSqlBuilder{
    private static final Joiner COMMA_JOINER = Joiner.on(", ");

    public String buildInsert(String table, Map<String, Object> data) {
        List<String> columns = new ArrayList<>(data.keySet());
        List<String> placeholders = Collections.nCopies(columns.size(), "?");
returnString.format(
"INSERT INTO %s (%s) VALUES (%s)",
            table,
            COMMA_JOINER.join(columns),
            COMMA_JOINER.join(placeholders)
        );
    }
}

// 使用
Map<String, Object> data = new LinkedHashMap<>();
data.put("name", "Alice");
data.put("age", 25);
data.put("email", "alice@example.com");
String sql = builder.buildInsert("users", data);
// INSERT INTO users (name, age, email) VALUES (?, ?, ?)

实战案例三:构建URL

复制代码
publicclassUrlBuilder {
privatestatic final Joiner.MapJoiner QUERY_JOINER =Joiner.on('&').withKeyValueSeparator('=');

private String baseUrl;
private Map<String, String> params = new LinkedHashMap<>();

publicUrlBuilder(String baseUrl) {
this.baseUrl = baseUrl;
    }

public UrlBuilder addParam(String key, String value) {
if (value != null) {
params.put(key, value);
        }
returnthis;
    }

public String build() {
if (params.isEmpty()) return baseUrl;
return baseUrl + "?" + QUERY_JOINER.join(params);
    }
}

// 使用
String url = new UrlBuilder("https://api.example.com/search")
    .addParam("q", "guava")
    .addParam("page", "1")
    .addParam("size", "20")
    .build();
// https://api.example.com/search?q=guava&page=1&size=20

案例一:CSV文件处理

复制代码
publicclassCsvProcessor {
privatestatic final Splitter CSV_SPLITTER = Splitter.on(',').trimResults().omitEmptyStrings();
privatestatic final Joiner CSV_JOINER = Joiner.on(',').useForNull("");
// 解析CSV行
public List<String> parseLine(String line) {
return CSV_SPLITTER.splitToList(line);
    }
// 生成CSV行
public String buildLine(List<String> fields) {
return CSV_JOINER.join(fields);
    }
}

案例二:配置文件管理

复制代码
publicclassConfigManager {
privatestatic final Splitter.MapSplitter CONFIG_SPLITTER =
        Splitter.on('\n').trimResults() .omitEmptyStrings()
            .withKeyValueSeparator('=');
public ImmutableMap<String, String> loadConfig(String content) {
// 过滤注释行
        String cleaned = Splitter.on('\n')
            .splitToStream(content)
            .filter(line -> !line.trim().startsWith("#"))
            .collect(Collectors.joining("\n"));
return ImmutableMap.copyOf(CONFIG_SPLITTER.split(cleaned));
    }
}

案例三:批量任务处理

复制代码
publicclassTaskProcessor {
privatestatic final int BATCH_SIZE =100;
publicvoidprocessTasks(List<Task> tasks) {
// 分批处理
        Lists.partition(tasks, BATCH_SIZE).forEach(batch -> {
// 生成批次ID
            String batchId = Joiner.on("-").join(
"batch",
                System.currentTimeMillis(),
                batch.size()
            );
// 处理每批任务
            processBatch(batchId, batch);
        });
    }
}

限制分割次数:

复制代码
Stringstr = "key:value:extra:data";
List<String> parts = Splitter.on(':').limit(2).splitToList(str);
// 结果:["key", "value:extra:data"]

固定长度分割:

复制代码
String str = "123456789012";
List<String> parts = Splitter.fixedLength(3).splitToList(str);
// 结果:["123", "456", "789", "012"]

正则表达式分割:

复制代码
String log = "2024-01-15   10:30:45   ERROR";
List<String> parts = Splitter.onPattern("\\s+").splitToList(log);
// 结果:["2024-01-15", "10:30:45", "ERROR"]

问题一:无法处理空字符串

复制代码
"a,,b".split(",")  // 结果:["a", "", "b"] - 包含空字符串

问题二:无法去除空格

复制代码
"a, b , c".split(",")  // 结果:["a", " b ", " c "] - 保留空格

Guava的完美解决:

复制代码
Splitter.on(',')
.trimResults()        // 自动去除空格
.omitEmptyStrings()   // 自动忽略空字符串
.splitToList("a, ,b,,c");
// 结果:["a", "b", "c"] - 完美!

实战案例一:URL参数解析

复制代码
public classUrlParamParser{
    private static final Splitter.MapSplitter PARSER =  Splitter.on('&') .trimResults().withKeyValueSeparator('=');

    public Map<String, String> parse(String url) {
        int index = url.indexOf('?');
if (index == -1) return Collections.emptyMap();
String query = url.substring(index + 1);
return PARSER.split(query);
    }
}

// 使用
String url = "https://api.com/search?keyword=guava&page=1&size=20";
Map<String, String> params = parser.parse(url);
// 结果:{keyword=guava, page=1, size=20}

实战案例二:日志解析

复制代码
publicclassLogParser {
privatestatic final Splitter SPLITTER = 
        Splitter.onPattern("\\s+").limit(4);

public LogEntry parse(String log) {
// "2025-11-15 12:33:17 ERROR User not found"
        List<String> parts = SPLITTER.splitToList(log);
returnnew LogEntry(
            parts.get(0),  // 日期
            parts.get(1),  // 时间
            parts.get(2),  // 级别
            parts.get(3)   // 消息(剩余部分)
        );
    }
}

Lists.partition:批量处理的利器

场景:需要将10000条数据分批插入数据库,每批100条

复制代码
publicclassBatchProcessor{
privatestaticfinal int BATCH_SIZE = 100;

public void batchInsert(List<User> users) {
// 自动分割为每批100条
List<List<User>> batches = Lists.partition(users, BATCH_SIZE);
for (List<User> batch : batches) {
            userDao.batchInsert(batch);
// 控制插入速度,避免数据库压力
            sleep(100);
        }
    }
}

Lists.partition:批量处理的利器

场景:需要将10000条数据分批插入数据库,每批100条

复制代码
publicclassBatchProcessor{
privatestaticfinal int BATCH_SIZE = 100;

public void batchInsert(List<User> users) {
// 自动分割为每批100条
List<List<User>> batches = Lists.partition(users, BATCH_SIZE);
for (List<User> batch : batches) {
            userDao.batchInsert(batch);
// 控制插入速度,避免数据库压力
            sleep(100);
        }
    }
}

BiMap:双向查找的神器

痛点:你是否经常需要根据value反查key?传统Map需要遍历,效率低下。

BiMap的魔法:

复制代码
BiMap<String, Integer> userMap = HashBiMap.create();
userMap.put("Alice", 10001);
userMap.put("Bob", 10002);
// 正向查找
Integer id = userMap.get("Alice");  // 10001
// 反向查找(重点来了!)
String name = userMap.inverse().get(10002);  // "Bob"

生产案例:错误码双向映射

复制代码
publicclassErrorCodeManager {
privatestatic final BiMap<String, Integer> ERROR_CODES = HashBiMap.create();

static {
        ERROR_CODES.put("USER_NOT_FOUND", 2000);
        ERROR_CODES.put("INVALID_PASSWORD", 2001);
        ERROR_CODES.put("PERMISSION_DENIED", 2002);
    }

// 根据错误名获取错误码
publicstatic Integer getCode(String errorName) {
return ERROR_CODES.get(errorName);
    }

// 根据错误码获取错误名(传统Map做不到!)
publicstatic String getName(Integer errorCode) {
return ERROR_CODES.inverse().get(errorCode);
    }
}

实战案例:HTTP状态码管理

复制代码
publicclassHttpStatusManager {
// 线程安全的状态码映射
privatestaticfinal ImmutableMap<Integer, String> STATUS_MAP =
        ImmutableMap.<Integer, String>builder()
            .put(200, "OK")
            .put(201, "Created")
            .put(400, "Bad Request")
            .put(401, "Unauthorized")
            .put(404, "Not Found")
            .put(500, "Internal Server Error")
            .build();
publicstatic String getMessage(int code){
return STATUS_MAP.getOrDefault(code, "Unknown Status");
    }
}
相关推荐
xdpcxq102911 小时前
Spring AOP + Guava RateLimiter 用注解实现优雅限流
spring·wpf·guava
程序员乐只4 天前
基于Python+Django+SSM热门旅游景点推荐系统(源码+LW+调试文档+讲解等)/热门旅游地推荐平台/旅游景点推荐软件/热门景点推荐系统/旅游推荐系统/旅游景点热门推荐
spring boot·spring·tomcat·hibernate·java-zookeeper·guava·java-consul
沛沛老爹1 个月前
2025年java总结:缝缝补补又一年?
java·开发语言·人工智能·python·guava·总结·web转型ai
PacosonSWJTU1 个月前
Guava缓存使用入门
java·缓存·guava
invicinble1 个月前
Google Guava工具类机制
guava
写代码的小阿帆1 个月前
Java本地缓存技术——Guava、Caffeine
java·缓存·guava
weixin_515069661 个月前
1.guava-retrying 重试框架
java·框架·guava·java常用api
山河亦问安1 个月前
令牌桶算法的限流组件实现
guava