web-dev-qa-db-ja.com

Java.util.Propertiesオブジェクトのコピーを作成するにはどうすればよいですか?

次のフィールドとコンストラクターがあります。

_private final Properties properties;

public PropertiesExpander(Properties properties) {
    this.properties = properties;
}
_

コンストラクター内のすべての変更可能なコレクションのコピーを作成することをお勧めします。浅い独立したコピーを作成したい。どうすればそれを達成できますか?

私の最初のアイデアはputAll()メソッドを使うことでした:

_private final Properties properties = new Properties();

public PropertiesExpander(Properties properties) {
    this.properties.putAll(properties);
}
_

それを行うためのより単純で、よりパフォーマンスの高い、またはより慣用的な方法はありますか?多分それのためのいくつかのユーティリティがグアバまたはアパッチコモンズにありますか?

17
Michal Kordas

Propertiesを使い続ける必要がある場合は、putAll()を使用すると便利です。 O(number of elements)で実行され、オーバーヘッドはほとんどありません。 Properties から継承するため、必要でない限り、パフォーマンス上の理由からHashtableを使用しないことをお勧めします。また、Propertiesは実際にはどのインターフェースにも準拠していないため、使用しないでください。抽象クラスであるDictionaryのみです。これにより、オプションが制限されます。参照: 「インターフェイスへのプログラム」とはどういう意味ですか?

Java 2プラットフォームv1.2以降、このクラスは、Mapインターフェースを実装するために改良され、Javaコレクションフレームワークのメンバーになりました。新しいコレクションの実装、Hashtableが同期されます。スレッドセーフな実装が必要ない場合は、HashMapの代わりに Hashtable を使用することをお勧めします。スレッドセーフな高度に並行する実装が必要な場合は、 Hashtableの代わりに ConcurrentHashMap を使用することをお勧めします。

何をするにしても、clone()は使用しないでください。安全ではなく、パフォーマンスも低下します。参照: Java:なぜクローン()が防御コピーに使用されるべきではないのですか?


GuavaとApache-commonsについて質問するために質問を編集しました。純粋に防御的なコピーで不変の場合、 Map<String, String> map = ImmutableMap.copyOf(properties) の使用をお勧めします。注:繰り返しになりますが、これは実際のPropertiesオブジェクトを使用しません。必要がない限り、Hashtableは推奨されないためです。から ウィキ

コレクションを変更する予定がない場合、またはコレクションが一定のままであると予想される場合は、それを防御的に不変のコレクションにコピーすることをお勧めします。

重要:Guavaの不変コレクションの実装はそれぞれ、null値を拒否します。 Googleの内部コードベースを徹底的に調査したところ、コレクションでnull要素が許可されるのは約5%の時間であり、他の95%のケースはnullで高速に失敗することで最も効果的でした。 null値を使用する必要がある場合は、nullを許可するコレクション実装でCollections.unmodifiableListおよびそのフレンドを使用することを検討してください。より詳細な提案はここにあります。

14
durron597

これを試して:

Properties newProps = new Properties();
properties.forEach((key, value) -> {
    newProps.setProperty((String) key, (String) value);
});
3

プロパティはCloneableを実装しているため、必要に応じて次のようにできます。

this.properties = (Properties) properties.clone();

これをクラスに追加してください

protected Object clone() throws CloneNotSupportedException {
    return super.clone();
}

または、クローンの使用が心配な場合は、クラスもシリアライズ可能を実装しているので、これを行うことができます。

import org.Apache.commons.lang.SerializationUtils;

this.properties = SerializationUtils.clone(properties);

プロパティ

クローン可能

2
Pumphouse

または、「長い」方法でそれを行うことができます。

    Iterator i = properties.keySet().iterator();
    while(i.hasNext()){
        this.properties.put(i.next(), properties.get(i));
    }

イテレーターは、プロパティーと同じJava.utilパッケージからのものであるため、外部の依存関係はありません。

チェックされていない型に関するコンパイラの警告が気になる場合は、これを次のように変更できます(プロパティキーが文字列であると想定)。

    Iterator<Object> i = properties.keySet().iterator();
    while(i.hasNext()){
        this.properties.put(i.next().toString(), properties.get(i));
    }
1
Scott Schechter

以下のプログラムは、あるプロパティファイルを別のプロパティファイルにコピーし、重複も削除します。ソースプロパティファイルには重複するプロパティがある場合がありますが、重複するプロパティなしで新しいファイルが作成されます。

import Java.io.FileInputStream;
import Java.io.FileOutputStream;
import Java.io.IOException;
import Java.io.InputStream;
import Java.io.OutputStream;
import Java.util.Properties;
import Java.util.Set;

public class App2 {

    public static void main(String[] args) {

        try (InputStream input = new FileInputStream("config.properties")) {

            Properties prop = new Properties();

            // load a properties file
            prop.load(input);

            writeToNewProperties(prop);
        } catch (IOException ex) {
            ex.printStackTrace();
        }

    }

    private static void writeToNewProperties(Properties prop) {
        Properties outPutProp = new Properties();
        // get the property value and print it out
        Set<String> stringPropertyNames = prop.stringPropertyNames();
        for (String propertyName : stringPropertyNames) {
            outPutProp.put(propertyName, prop.get(propertyName));
        }

        try (OutputStream output = new FileOutputStream("out-config.properties")) {
            // save properties to project root folder
            outPutProp.store(output, null);
            System.out.println(outPutProp);
        } catch (IOException io) {
            io.printStackTrace();
        }
    }

}
0
Sudhakar