web-dev-qa-db-ja.com

Java HashMap.clear()およびremove()メモリは有効ですか?

次のHashMap.clear()コードを考えてください:

_ /**
 * Removes all of the mappings from this map.
 * The map will be empty after this call returns.
 */
public void clear() {
    modCount++;
    Entry[] tab = table;
    for (int i = 0; i < tab.length; i++)
        tab[i] = null;
    size = 0;
}
_

tableオブジェクトの内部配列(Entry)は決して縮小されないようです。したがって、10000個の要素をマップに追加し、map.clear()を呼び出した後、その内部配列には10000個のnullが保持されます。だから、私の質問は、JVMはこの何もない配列をどのように処理するのですか?したがって、HashMapメモリは効果的ですか?

41

clear()は、HashMapを再利用する場合にのみ呼び出されるという考え方です。オブジェクトの再利用は、以前に使用したのと同じ理由でのみ行う必要があります。そのため、エントリの数がほぼ同じになる可能性があります。 Mapの無駄な縮小とサイズ変更を避けるために、clear()が呼び出されたときに容量は同じに保たれます。

Mapのデータを破棄するだけであれば、clear()を呼び出す必要はありません(実際はそうすべきではありません)が、単にMap自体。その場合、最終的にガベージコレクションされます。

62
Joachim Sauer

ソースコードを見るHashMapは縮小しないように見えます。 resizeメソッドは、必要なときにサイズを2倍にするために呼び出されますが、ala ArrayList.trimToSize() のようなものは何もありません。

HashMapを劇的に頻繁に増減するような方法で使用している場合は、clear()を呼び出す代わりに、新しいHashMapを作成するだけでよい場合があります。

10

あなたは正しいですが、配列を増やすことははるかに費用のかかる操作であることを考えると、HashMapが「ユーザーが配列を増やしたら、後でこのサイズの配列が必要になる可能性がある」と考えるのは不合理ではありませんアレイを減らす代わりに、後で再度高価に拡張しなければならないリスクを冒す代わりに。それは私が推測するヒューリスティックです-あなたも他の方法を支持することができます。

4
Konerak

考慮すべきもう1つのことは、tableの各要素が単なる参照であることです。これらのエントリをnullに設定すると、Map内のアイテムから参照が削除され、ガベージコレクション用に解放されます。したがって、メモリをまったく解放していないようには見えません。

ただし、Map自体によって使用されているメモリさえも解放する必要がある場合は、Joachim Sauerの提案に従って解放する必要があります。

4
danben