解决方案也适用于 java > 8
尽管问题没有明确提及store(OutputStream out, String comments)
功能,但我发现这(和load(InputStream inStream)
分别)是Properties
.
如果我们对存储/加载属性不感兴趣,我们可以Properties
用一些Map
或SortedMap
实现来替换。
不同之Properties
处在于/方法Map
的存在 提供了一些特定的序列化规则。这些规则没有(也不会)在 java 版本之间发生变化。例如store()
load()
- 存储对像
prop=value
- Unicode 和特殊字符的转义规则。
- 在顶部添加可选注释
不幸的是,上述 3 部分功能隐藏在私有方法中,并且不能在希望使用不同内部数据结构的扩展或替代实现中轻松重用(例如,用于保持属性排序)。
所以剩下的就是保持相同的内部结构并覆盖这两种store()
方法。
注意:为了获得排序的属性,前段时间我遵循了 danisupr4实现,但在java9 上它坏了。
TL;博士
下面的代码通过覆盖 only方法维护了完整的功能,并使用-的所有版本进行了测试。
我相信过滤这个公共方法的输出可以使实现对类中未来的代码更改不那么脆弱。Properties
store(OutputStream out, String comments)
java5
java12
java.util.Properties
class SortedStoreProperties extends Properties {
@Override
public void store(OutputStream out, String comments) throws IOException {
Properties sortedProps = new Properties() {
@Override
public Set<Map.Entry<Object, Object>> entrySet() {
/*
* Using comparator to avoid the following exception on jdk >=9:
* java.lang.ClassCastException: java.base/java.util.concurrent.ConcurrentHashMap$MapEntry cannot be cast to java.base/java.lang.Comparable
*/
Set<Map.Entry<Object, Object>> sortedSet = new TreeSet<Map.Entry<Object, Object>>(new Comparator<Map.Entry<Object, Object>>() {
@Override
public int compare(Map.Entry<Object, Object> o1, Map.Entry<Object, Object> o2) {
return o1.getKey().toString().compareTo(o2.getKey().toString());
}
}
);
sortedSet.addAll(super.entrySet());
return sortedSet;
}
@Override
public Set<Object> keySet() {
return new TreeSet<Object>(super.keySet());
}
@Override
public synchronized Enumeration<Object> keys() {
return Collections.enumeration(new TreeSet<Object>(super.keySet()));
}
};
sortedProps.putAll(this);
sortedProps.store(out, comments);
}
}
注意:根据谁调用store()
,最好不要覆盖现有方法而是创建一个新方法:例如storeSorted()
.
此外,为简单起见,我仅覆盖其中一种store()
方法,但相同的概念适用于两者。