1. 简介

在本篇教程中,我们将聚焦于如何将两个或多个 Java 的 Properties 对象合并为一个。

我们会介绍三种不同的实现方式:
✅ 首先是使用迭代的方式;
✅ 接着是使用 putAll() 方法;
✅ 最后,使用 Java 8 的 Stream API 来实现更现代化的写法。

如果你还不太熟悉 Java Properties 的基本使用,可以先看看我们这篇 入门文章

2. Properties 使用回顾

在开始合并操作之前,我们快速回顾一下 Properties 的核心概念。

Properties 通常用于定义应用的配置项,它以键值对的形式存储数据,且键和值都必须是字符串类型。

在 Java 中,我们通过 java.util.Properties 类来管理这些键值对。⚠️ 需要注意的是,Properties 类继承自 Hashtable

如果你对 Hashtable 还不熟悉,可以阅读我们的 这篇文章

2.1. 创建 Properties 示例

为了方便演示,我们采用程序化的方式创建 Properties:

private Properties propertiesA() {
    Properties properties = new Properties();
    properties.setProperty("application.name", "my-app");
    properties.setProperty("application.version", "1.0");
    return properties;
}

上面这段代码创建了一个 Properties 对象,并通过 setProperty() 方法设置了两个配置项。
⚠️ 注意:虽然 setProperty() 内部调用了 Hashtableput() 方法,但它确保了键和值都是字符串类型。

不推荐直接使用 put() 方法,因为它允许插入非字符串类型的键或值,这会破坏 Properties 的语义。

3. 方式一:使用迭代合并 Properties

我们先来看一个通过迭代合并多个 Properties 的方式:

private Properties mergePropertiesByIteratingKeySet(Properties... properties) {
    Properties mergedProperties = new Properties();
    for (Properties property : properties) {
        Set<String> propertyNames = property.stringPropertyNames();
        for (String name : propertyNames) {
            String propertyValue = property.getProperty(name);
            mergedProperties.setProperty(name, propertyValue);
        }
    }
    return mergedProperties;
}

步骤解析:

  1. 创建一个新的 Properties 对象用于存放合并后的结果;
  2. 遍历传入的所有 Properties 对象;
  3. 使用 stringPropertyNames() 获取每个对象中所有键名;
  4. 遍历这些键名,获取对应的值;
  5. 将键值对放入合并后的对象中。

✅ 这种方式虽然啰嗦,但逻辑清晰,适合需要精细控制的场景。

4. 方式二:使用 putAll() 方法

接下来我们使用 putAll() 方法来合并 Properties:

private Properties mergePropertiesByUsingPutAll(Properties... properties) {
    Properties mergedProperties = new Properties();
    for (Properties property : properties) {
        mergedProperties.putAll(property);
    }
    return mergedProperties;
}

和前面类似,我们创建一个目标 Properties 对象,然后依次调用 putAll() 方法将每个 Properties 对象中的键值对复制进去。

⚠️ 注意:putAll() 是从 Hashtable 继承而来的方法,它会把另一个 Map 中的所有映射拷贝到当前对象中。

❌ 同样,不推荐直接使用 putAll() 来处理非字符串类型的 Map,因为这可能导致类型不一致的问题。

5. 方式三:使用 Stream API 合并

最后,我们使用 Java 8 的 Stream API 来实现更优雅的合并方式:

private Properties mergePropertiesByUsingStreamApi(Properties... properties) {
    return Stream.of(properties)
        .collect(Properties::new, Map::putAll, Map::putAll);
}

这里我们使用了 Stream.of() 将多个 Properties 转换为流,然后通过 collect() 方法将它们归约为一个 Properties 对象。

三个参数说明如下:

  • 第一个参数是 Supplier,用于创建新的结果容器(这里是 new Properties());
  • 第二个参数是累加器(accumulator),用于将元素合并到结果容器中(这里是 Map::putAll);
  • 第三个参数是组合器(combiner),用于并行流中合并多个结果容器(这里也是 Map::putAll)。

✅ 这种方式简洁高效,适合追求代码风格的场景。

如果你对 Stream API 还不熟悉,可以看看我们这篇 入门指南

6. 总结

本篇教程我们介绍了三种合并 Properties 对象的方式:

方式 特点
迭代合并 逻辑清晰,适合自定义控制
putAll() 方法 简洁,但要注意类型安全
Stream API 现代化写法,代码简洁优雅

所有示例代码都可以在我们的 GitHub 仓库 中找到。


原始标题:Merging java.util.Properties Objects | Baeldung