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");
    }
}
相关推荐
谢亮_vipxieliang17 天前
ValidX vs Google Guava Preconditions:验证 vs 断言
java·spring boot·后端·spring cloud·hibernate·guava
吴声子夜歌20 天前
Guava——散列
java·guava
吴声子夜歌20 天前
Guava——并发(二)
java·网络·guava
吴声子夜歌20 天前
Guava——事件总线
java·网络·guava
吴声子夜歌20 天前
Guava——并发(一)
java·guava
吴声子夜歌20 天前
Guava——反射
java·开发语言·guava
吴声子夜歌20 天前
Guava——基本工具(二)
windows·python·guava
吴声子夜歌21 天前
Guava——基本工具(一)
windows·guava
吴声子夜歌21 天前
Guava——集合(二)
java·guava
吴声子夜歌21 天前
Guava——缓存
缓存·guava