22

オブジェクトがPropertiesあり、他のオブジェクトを追加する必要がある場合がありますProperties

Properties myBasicProps = this.getClass.getResourceAsStream(MY_PROPS_PATH);
...
Properties otherProps = new Properties();
otherProps.load(new StringReader(tempPropsString)); //tempPropsString contains my temporary properties
myBasicProps.putAll(otherProps);

この後並べ替えたいですmyBasicPropsCollections.sort()すべてのキーと値を取得し、それらを並べ替えてから、すべてを新しいオブジェクトに配置する必要はありません。もっと良い方法はありますか?

4

13 に答える 13

22

いいえ、java.util.Properties拡張java.util.Hashtableします。これは、キーまたは値の予測可能な並べ替え順序を定義しません。

すべての値をのようなものにダンプしてみることができjava.util.TreeMapます。これにより、キーに自然な順序が課せられます。

于 2012-04-23T06:42:15.233 に答える
21

あなたがしなければならないのは、プロパティを拡張するクラスを作成することです。ソース:java2s.com

import java.io.FileOutputStream;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Vector;

public class Main{
  public static void main(String[] args) throws Exception {
    SortedProperties sp = new SortedProperties();
    sp.put("B", "value B");
    sp.put("C", "value C");
    sp.put("A", "value A");
    sp.put("D", "value D");
    FileOutputStream fos = new FileOutputStream("sp.props");
    sp.store(fos, "sorted props");
  }

}
class SortedProperties extends Properties {
  public Enumeration keys() {
     Enumeration keysEnum = super.keys();
     Vector<String> keyList = new Vector<String>();
     while(keysEnum.hasMoreElements()){
       keyList.add((String)keysEnum.nextElement());
     }
     Collections.sort(keyList);
     return keyList.elements();
  }

}

わたしにはできる。

于 2013-09-03T08:55:30.800 に答える
13

オーバーライドはJava8keysでうまく機能しますが、Java 9以降、メソッドの新しい実装はメソッドstoreを呼び出さず、メソッドを呼び出しkeysますentrySet

したがって、保存時にJava 8/9/10でソートentrySetするには、オーバーライドする必要もあります。Properties

インラインオーバーライドの例を次に示します。

Properties properties = new Properties() {

    private static final long serialVersionUID = 1L;

    @Override
    public Set<Object> keySet() {
        return Collections.unmodifiableSet(new TreeSet<Object>(super.keySet()));
    }

    @Override
    public Set<Map.Entry<Object, Object>> entrySet() {

        Set<Map.Entry<Object, Object>> set1 = super.entrySet();
        Set<Map.Entry<Object, Object>> set2 = new LinkedHashSet<Map.Entry<Object, Object>>(set1.size());

        Iterator<Map.Entry<Object, Object>> iterator = set1.stream().sorted(new Comparator<Map.Entry<Object, Object>>() {

            @Override
            public int compare(java.util.Map.Entry<Object, Object> o1, java.util.Map.Entry<Object, Object> o2) {
                return o1.getKey().toString().compareTo(o2.getKey().toString());
            }
        }).iterator();

        while (iterator.hasNext())
            set2.add(iterator.next());

        return set2;
    }

    @Override
    public synchronized Enumeration<Object> keys() {
        return Collections.enumeration(new TreeSet<Object>(super.keySet()));
        }
    };
于 2018-09-01T10:37:34.267 に答える
7

Java>8でも機能するソリューション

質問が機能について明示的に言及していないという事実にもかかわらずstore(OutputStream out, String comments)、私はこれ(およびload(InputStream inStream)それぞれ)がの最も興味深い部分であると思いますProperties

プロパティの保存/読み込みに関心がない場合はProperties、一部MapまたはSortedMap実装に置き換えることができます。

Propertiesとの違いは、いくつかの特定のシリアル化ルールを提供する/メソッドMapの存在です 。これらのルールは、Javaバージョン間で変更されていません(変更されません)。例えばstore()load()

  • のようなペアを保存するprop=value
  • Unicodeおよび特殊文字のエスケープルール。
  • オプションのコメントを上に追加

残念ながら、機能の上記の3つの部分はプライベートメソッド内に隠されており、異なる内部データ構造を使用したい拡張または代替実装内で簡単に再利用することはできません(たとえば、プロパティを並べ替えたままにするため)。

したがって、残っているのは、同じ内部構造を維持し、2つのメソッドをオーバーライドするstore()ことです。

注:ソートされたプロパティを取得するために、しばらく前にdanisupr4の実装に従いましたが、java9では機能しませんでした。

TL; DR

以下のコードは、メソッドのみをオーバーライドすることでの完全な機能を維持し、-からのすべてのバージョンでテストされています。 このパブリックメソッドの出力をフィルタリングすると、クラス内の将来のコード変更に対する実装の脆弱性が低くなると思います。Propertiesstore(OutputStream out, String comments)java5java12
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()メソッドの1つだけをオーバーライドしますが、同じ概念が両方に適用されます。

于 2019-05-02T17:17:38.417 に答える
6

@danisupr4が最良の解決策です。

IDEで警告が表示されないように、少し改善します。

public static class MyProperties extends Properties {
    private static final long serialVersionUID = 1L;

    public Enumeration<Object> keys() {
        Enumeration<Object> keysEnum = super.keys();
        Vector<Object> keyList = new Vector<Object>();

        while (keysEnum.hasMoreElements()) {
            keyList.add(keysEnum.nextElement());
        }

        Collections.sort(keyList, new Comparator<Object>() {
            @Override
            public int compare(Object o1, Object o2) {
                return o1.toString().compareTo(o2.toString());
            }
        });

        return keyList.elements();
    }
}
于 2014-07-31T13:11:01.167 に答える
6

TreeMapは最も簡単な方法である必要があります。

Properties myProps = this.getClass.getResourceAsStream(MY_PROPS_PATH);

try {
    myProps.load(new FileInputStream(extraPropertiesFilename));
        //you can load more properties from external file

    Map<String, String> sortedMap = new TreeMap(myProps);

    //output sorted properties (key=value)
    for (String key : sortedMap.keySet()) {
        System.out.println(key + "=" + sortedMap.get(key));
    }

} catch (Exception e) {
    e.printStackTrace();
}
于 2015-11-30T21:10:04.733 に答える
4

キーを並べ替える方がはるかに簡単です。

List<String> keys = new ArrayList<String>()
for(String key : properties.stringPropertyNames()) {
  keys.add(key)
}

Collections.sort(keys);
于 2014-05-21T20:14:02.087 に答える
2

ソートされたプロパティをtxtファイルに保存するためのkeys()メソッドをオーバーライドできます。

//this method downloaded from edu.umd.cs.findbugs.config package
@SuppressWarnings("unchecked")
@Override
public synchronized Enumeration<Object> keys() {
    Set<?> set = keySet();
    return (Enumeration<Object>) sortKeys((Set<String>) set);
}
static public Enumeration<?> sortKeys(Set<String> keySet) {
    List<String> sortedList = new ArrayList<String>();
    sortedList.addAll(keySet);
    Collections.sort(sortedList);
    return Collections.enumeration(sortedList);
}

ソートされたプロパティをxmlファイルに保存するためのstringPropertyNames()メソッドをオーバーライドします。

@Override
public Set<String> stringPropertyNames() {
Set<String> tmpSet = new TreeSet<String>();
for (Object key : keySet())
{
    tmpSet.add(key.toString());
}
    return tmpSet;
}
于 2015-03-05T11:51:05.733 に答える
2

私は次のようにメソッドストアをオーバーライドすることで行いました:

@Override
public void store(Writer writer, String comments) throws IOException {

    this.keySet().stream().map(k -> (String)k).sorted().forEach(k -> {
        try {
            writer.append(String.format("%s=%s\n", k, get(k)));
        } catch (IOException e) {
            e.printStackTrace();
        }
    });

}

以前の答えは私にはうまく合いませんでした。

于 2018-05-23T00:32:25.697 に答える
1

Java 8ではProperties.keys()、プロパティの格納に使用されていましたが、Java 9では、これが変更されてProperties.entrySet()使用されました。

Java 8

private void store0(BufferedWriter bw, String comments, boolean escUnicode)
    throws IOException
{
...
        for (Enumeration<?> e = keys(); e.hasMoreElements();) {

Java 9

private void store0(BufferedWriter bw, String comments, boolean escUnicode)
    throws IOException
{
...
        for (Map.Entry<Object, Object> e : entrySet()) {

私はこのクラスを使用して両方のJavaバージョンを処理します。

public class SortedProperties extends Properties {

    /**
     * constructor
     *
     * @param unsortedProperties
     */
    public SortedProperties(Properties unsortedProperties) {
        putAll(unsortedProperties);
    }

    @Override
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public synchronized Enumeration keys() {
        Enumeration<Object> keysEnum = super.keys();
        Vector<String> keyList = new Vector<String>();
        while (keysEnum.hasMoreElements()) {
            keyList.add((String) keysEnum.nextElement());
        }
        Collections.sort(keyList);
        return keyList.elements();
    }

    @Override
    public Set<java.util.Map.Entry<Object, Object>> entrySet() {
        // use a TreeMap since in java 9 entrySet() instead of keys() is used in store()
        TreeMap<Object, Object> treeMap = new TreeMap<>();
        Set<Map.Entry<Object, Object>> entrySet = super.entrySet();
        for (Map.Entry<Object, Object> entry : entrySet) {
            treeMap.put(entry.getKey(), entry.getValue());
        }
        return Collections.synchronizedSet(treeMap.entrySet());
    }
}
于 2020-02-18T07:35:00.623 に答える
0

smillien62のものに触発された私の解決策:

final Properties properties = new Properties()
{
  private boolean recurse;

  @Override
  public synchronized Set<Map.Entry<Object, Object>> entrySet()
  {
    if (this.recurse)
    {
      return super.entrySet();
    }
    else
    {
      this.recurse = true;
      final TreeMap<Object, Object> treeMap = new TreeMap<>(this);
      final Set<Map.Entry<Object, Object>> entries = treeMap.entrySet();
      this.recurse = false;
      return entries;
    }
  }
};
于 2020-01-01T12:31:10.897 に答える
0

TreeMap(キーを自然な順序で並べ替える)とStringBuilder(sysoutも使用できますが、戻り値をログに記録するのは簡単です)を使用してみてください

public static String getPrettyPrintProps(Properties properties) {
Map<String, String> map = new TreeMap(properties);
StringBuilder sb = new StringBuilder();
map.forEach((k, v) -> sb.append("\n" + k + ":" + v ) );
return  sb.toString();
}
于 2020-04-16T06:06:49.307 に答える
0

どうですか:

    System.getProperties().entrySet().stream()
            .sorted((e1, e2) -> e1.getKey().toString().compareToIgnoreCase(e2.getKey().toString()))
于 2021-03-03T16:01:18.403 に答える