10

Map<String, String>を取得し、その値に含まれるすべてのエントリを削除したいとしましょうfoo。最適化/メモリなどの観点から、それを行う最良の方法は何ですか? 以下の 4 つsysoは同じ結果、つまり を出力しています{n2=bar}

public static void main(String[] args) {

    Map<String, String> in = new HashMap<String, String>();
    in.put("n1", "foo");
    in.put("n2", "bar");
    in.put("n3", "foobar");

    // 1- create a new object with the returned Map
    Map<String, String> in1 = new HashMap<String, String>(in);
    Map<String, String> out1 = methodThatReturns(in1);
    System.out.println(out1);

    // 2- overwrite the initial Map with the returned one 
    Map<String, String> in2 = new HashMap<String, String>(in);
    in2 = methodThatReturns(in2);
    System.out.println(in2);

    // 3- use the clear/putAll methods
    Map<String, String> in3 = new HashMap<String, String>(in);
    methodThatClearsAndReadds(in3);
    System.out.println(in3);

    // 4- use an iterator to remove elements
    Map<String, String> in4 = new HashMap<String, String>(in);
    methodThatRemoves(in4);
    System.out.println(in4);

}

public static Map<String, String> methodThatReturns(Map<String, String> in) {
    Map<String, String> out = new HashMap<String, String>();
    for(Entry<String, String> entry : in.entrySet()) {
        if(!entry.getValue().contains("foo")) {
            out.put(entry.getKey(), entry.getValue());
        }
    }
    return out;
}

public static void methodThatClearsAndReadds(Map<String, String> in) {
    Map<String, String> out = new HashMap<String, String>();
    for(Entry<String, String> entry : in.entrySet()) {
        if(!entry.getValue().contains("foo")) {
            out.put(entry.getKey(), entry.getValue());
        }
    }
    in.clear();
    in.putAll(out);
}

public static void methodThatRemoves(Map<String, String> in) {
    for(Iterator<Entry<String, String>> it = in.entrySet().iterator(); it.hasNext();) {
        if(it.next().getValue().contains("foo")) {
            it.remove();
        }
    }
}
4

4 に答える 4

4

最良の方法は、次のmethodThatRemoves理由によるものです。

  1. メモリ消費に関しては、新しいマップを作成しないため、メモリ オーバーヘッドが追加されません。
  2. CPU の使用に関して: イテレータは、次の呼び出しまたは現在の要素の削除に対して O(1) の複雑さを持っています。
于 2012-06-12T10:13:15.457 に答える
2

methodThatRemovesの最も効率的な方法です。

  • メモリをほとんど使用しない
  • (軽量) イテレータ以外のオブジェクトを作成しません
  • 非常に高速です (マップ ルックアップを使用しません)。

ただし、変更できないマップがあるか、元のマップを保持する必要がある場合を除き、最初にコピーを作成することはありません。

于 2012-06-12T10:23:22.050 に答える
1

中間のマップを作成せず、メソッドを使用しないため、私にとっては--methodThatRemovesを使用したものがIterator最適ですput

ちなみに、最初のもの:複雑さがO(1)であるmethodThatReturnsため、より高速になる可能put性がありますが、最悪の場合、removeはO(n)ですが、Mapの2つの異なるインスタンスがあるため、より多くのメモリを使用します。

于 2012-06-12T10:16:21.757 に答える
0

methodThatRemovesあなたはループ操作を実行し、「foo」の等価性をチェックしているだけなので、私は個人的に行きます。他の人は、オブジェクトマップの作成とマップのクリア/プット操作と同様にそれを行います。したがって、明らかに1つのメソッドが少なくなります。

また、メモリ使用量を減らしたい場合は、1 つ以上のエントリを削除するためだけに余分な HashMap を作成しない方がよいでしょう。これは、マップを反復するための余分な計算を気にしないことを前提としています。

もっと深く掘り下げたい場合は、プロファイラーなどを使用してこれを評価する必要があります。

于 2012-06-12T10:12:22.333 に答える