web-dev-qa-db-ja.com

Javaプロパティを定義された順序でどのように記述できますか?

プロパティを格納するためにJava.util.Propertiesのstore(Writer、String)メソッドを使用しています。結果のテキストファイルでは、プロパティは不規則な順序で格納されます。

これは私がやっていることです:

Properties properties = createProperties();
properties.store(new FileWriter(file), null);

プロパティがアルファベット順に、またはプロパティが追加された順に書き込まれるようにするにはどうすればよいですか?

「プロパティファイルを手動で作成する」よりも簡単な解決策を期待しています。

28
Steve McLeod

「The New Idiot's」の提案に従って、これはアルファベット順で保存されます。

Properties tmp = new Properties() {
    @Override
    public synchronized Enumeration<Object> keys() {
        return Collections.enumeration(new TreeSet<Object>(super.keySet()));
    }
};
tmp.putAll(properties);
tmp.store(new FileWriter(file), null);
57
Steve McLeod

明確に定義された順序でプロパティファイルを読み書きできる完全な実装については、 https://github.com/etiennestuder/Java-ordered-properties を参照してください。

OrderedProperties properties = new OrderedProperties();
properties.load(new FileInputStream(new File("~/some.properties")));
10
Etienne Studer

TreeSetを使用するのは危険です。 CASE_INSENSITIVE_ORDER文字列「mykey」、「MyKey」、「MYKEY」は同じインデックスになります! (したがって、2つのキーは省略されます)。

代わりにListを使用して、すべてのキーを確実に保持します。

 List<Object> list = new ArrayList<>( super.keySet());
 Comparator<Object> comparator = Comparator.comparing( Object::toString, String.CASE_INSENSITIVE_ORDER );
 Collections.sort( list, comparator );
 return Collections.enumeration( list );
1
Dorian Gray

以前はSteve McLeodの答えがうまくいきましたが、Java 11なので、うまくいきません。

問題はEntrySetの順序付けのように思われたので、次のようにします。

@SuppressWarnings("serial")
private static Properties newOrderedProperties() 
{
    return new Properties() {
        @Override public synchronized Set<Map.Entry<Object, Object>> entrySet() {
            return Collections.synchronizedSet(
                    super.entrySet()
                    .stream()
                    .sorted(Comparator.comparing(e -> e.getKey().toString()))
                    .collect(Collectors.toCollection(LinkedHashSet::new)));
        }
    };
}

これは決して速くないことを警告します。理想的ではないLinkedHashSetの反復を強制しますが、私は提案を受け入れます。

1
CompEng88

大文字と小文字を区別しないでソートしようとすると、Steve McLeodのソリューションが機能しませんでした。

これは私が思いついたものです

Properties newProperties = new Properties() {

    private static final long serialVersionUID = 4112578634029874840L;

    @Override
    public synchronized Enumeration<Object> keys() {
        Comparator<Object> byCaseInsensitiveString = Comparator.comparing(Object::toString,
                        String.CASE_INSENSITIVE_ORDER);

        Supplier<TreeSet<Object>> supplier = () -> new TreeSet<>(byCaseInsensitiveString);

        TreeSet<Object> sortedSet = super.keySet().stream()
                        .collect(Collectors.toCollection(supplier));

        return Collections.enumeration(sortedSet);
    }
 };

    // propertyMap is a simple LinkedHashMap<String,String>
    newProperties.putAll(propertyMap);
    File file = new File(filepath);
    try (FileOutputStream fileOutputStream = new FileOutputStream(file, false)) {
        newProperties.store(fileOutputStream, null);
    }
1
kevcodez