35

値の順序が重要なプロパティ ファイルがあります。プロパティ ファイルを繰り返し処理し、元のファイルの順序に基づいて値を出力できるようにしたいと考えています。

ただし、Properties ファイルは、挿入順序を維持しない Map によってサポートされているため、間違っている場合は訂正してください。イテレータは値を間違った順序で返します

これが私が使用しているコードです

Enumeration names = propfile.propertyNames();
while (names.hasMoreElements()) {
    String name = (String) names.nextElement();
    //do stuff
}

独自のカスタム ファイル パーサーを作成する以外に、プロパティを元に戻す方法はありますか?

4

15 に答える 15

67

拡張し、 と の両方をjava.util.Propertiesオーバーライドします。put()keys()

import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Properties;
import java.util.HashMap;

public class LinkedProperties extends Properties {
    private final HashSet<Object> keys = new LinkedHashSet<Object>();

    public LinkedProperties() {
    }

    public Iterable<Object> orderedKeys() {
        return Collections.list(keys());
    }

    public Enumeration<Object> keys() {
        return Collections.<Object>enumeration(keys);
    }

    public Object put(Object key, Object value) {
        keys.add(key);
        return super.put(key, value);
    }
}
于 2010-05-13T15:32:20.460 に答える
11

いいえ - マップは本質的に「順不同」です。

オーバーライドされた独自のサブクラスを作成することできますが、実装固有になる可能性があります...悪いカプセル化の代表的な例です。私が最後に拡張バージョンを書いたとき (約 10 年前!)、それは恐ろしいものであり、実装の詳細に間違いなく敏感でした。PropertiessetPropertyputPropertiesProperties

于 2009-08-21T14:45:37.110 に答える
7

プロパティ名を変更できる場合は、数値またはその他の並べ替え可能な接頭辞を前に付けてから、Properties KeySet を並べ替えることができます。

于 2009-08-21T15:00:02.640 に答える
6

上記の Dominique Laurent のソリューションは、私にとってはうまく機能します。また、次のメソッド オーバーライドを追加しました。

public Set<String> stringPropertyNames() {
    Set<String> set = new LinkedHashSet<String>();

    for (Object key : this.keys) {
        set.add((String)key);
    }

    return set;
}

おそらく最も効率的ではありませんが、サーブレットのライフサイクルで一度だけ実行されます。

ありがとうドミニク!

于 2011-02-16T19:23:43.033 に答える
5

Apache Commons Configurationがうまくいくかもしれません。私はこれを自分でテストしていませんが、ソースを確認したところ、AbstractFileConfiguration クラスの LinkedList によってプロパティ キーがサポートされているようです。

public Iterator getKeys()
{
    reload();
    List keyList = new LinkedList();
    enterNoReload();
    try
    {
        for (Iterator it = super.getKeys(); it.hasNext();)
        {
            keyList.add(it.next());
        }

        return keyList.iterator();
    }
    finally
    {
        exitNoReload();
    }
}
于 2009-08-21T15:30:22.560 に答える
3
Map<String, String> mapFile = new LinkedHashMap<String, String>();
ResourceBundle bundle = ResourceBundle.getBundle(fileName);
TreeSet<String> keySet = new TreeSet<String>(bundle.keySet());
for(String key : keySet){
    System.out.println(key+" "+bundle.getString(key));
    mapFile.put(key, bundle.getString(key));
}

これにより、プロパティ ファイルの順序が保持されます

于 2016-04-18T10:29:10.757 に答える
3

完全性のために...

public class LinkedProperties extends Properties {

    private final LinkedHashSet<Object> keys = new LinkedHashSet<Object>();

    @Override
    public Enumeration<?> propertyNames() {
        return Collections.enumeration(keys);
    }

    @Override
    public synchronized Enumeration<Object> elements() {
        return Collections.enumeration(keys);
    }

    public Enumeration<Object> keys() {
        return Collections.enumeration(keys);
    }

    public Object put(Object key, Object value) {
        keys.add(key);
        return super.put(key, value);
    }

    @Override
    public synchronized Object remove(Object key) {
        keys.remove(key);
        return super.remove(key);
    }

    @Override
    public synchronized void clear() {
        keys.clear();
        super.clear();
    }
}

定義によるセットは挿入順序を維持しないため、セットを返すメソッドをオーバーライドする必要はないと思います

于 2013-02-14T12:36:18.690 に答える
3

もう 1 つ有名な YAEOOJP ( Yet Another Example Of Ordered Java Properties ) をこのスレッドに追加します。これは、プロパティにフィードできるデフォルトプロパティを気にする人は誰もいないようだからです。

@see http://docs.oracle.com/javase/tutorial/essential/environment/properties.html

それは私のクラスです: 10 16 % はあらゆる状況に対応していませんが、今のところ私の限られた愚かな目的には問題ありません。より大きな善が利益を得ることができるように、修正のためのさらなるコメントを歓迎します。

import java.util.Collections;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

/**
 * Remember javadocs  >:o
 */
public class LinkedProperties extends Properties {

    protected LinkedProperties linkedDefaults;
    protected Set<Object> linkedKeys = new LinkedHashSet<>();

    public LinkedProperties() { super(); }

    public LinkedProperties(LinkedProperties defaultProps) {
        super(defaultProps); // super.defaults = defaultProps;
        this.linkedDefaults = defaultProps;
    }

    @Override
    public synchronized Enumeration<?> propertyNames() {
        return keys();
    }

    @Override
    public Enumeration<Object> keys() {
        Set<Object> allKeys = new LinkedHashSet<>();
        if (null != defaults) {
            allKeys.addAll(linkedDefaults.linkedKeys);
        }
        allKeys.addAll(this.linkedKeys);
        return Collections.enumeration(allKeys);
    }

    @Override
    public synchronized Object put(Object key, Object value) {
        linkedKeys.add(key);
        return super.put(key, value);
    }

    @Override
    public synchronized Object remove(Object key) {
        linkedKeys.remove(key);
        return super.remove(key);
    }

    @Override
    public synchronized void putAll(Map<?, ?> values) {
        for (Object key : values.keySet()) {
            linkedKeys.add(key);
        }
        super.putAll(values);
    }

    @Override
    public synchronized void clear() {
        super.clear();
        linkedKeys.clear();
    }

    private static final long serialVersionUID = 0xC00L;
}
于 2015-04-17T08:16:23.613 に答える
2

プロパティを XML としてエクスポートする場合は、keySet() もオーバーライドする必要があります。

public Set<Object> keySet() { return keys; }

于 2010-08-18T20:34:48.653 に答える
2

私が見ているように、Propertiesは に縛られすぎていHashtableます。の順に読むことをお勧めしLinkedHashMapます。そのためには、 をキー/値コンテナーとして無視してObject put(Object key, Object value)、単一のメソッド をオーバーライドするだけで済みます。Properties

public class InOrderPropertiesLoader<T extends Map<String, String>> {

    private final T map;

    private final Properties properties = new Properties() {
        public Object put(Object key, Object value) {
            map.put((String) key, (String) value);
            return null;
        }

    };

    public InOrderPropertiesLoader(T map) {
        this.map = map;
    }

    public synchronized T load(InputStream inStream) throws IOException {
        properties.load(inStream);

        return map;
    }
}

使用法:

LinkedHashMap<String, String> props = new LinkedHashMap<>();
try (InputStream inputStream = new FileInputStream(file)) {
    new InOrderPropertiesLoader<>(props).load(inputStream);
}
于 2016-08-11T15:26:11.043 に答える