JavaにおけるHashMap
、LinkedHashMap
、およびTreeMap
の違いは何ですか? 3つすべてにkeySet
とvalues
があるので、出力に違いはありません。 Hashtable
sとは何ですか?
Map m1 = new HashMap();
m1.put("map", "HashMap");
m1.put("schildt", "Java2");
m1.put("mathew", "Hyden");
m1.put("schildt", "Java2s");
print(m1.keySet());
print(m1.values());
SortedMap sm = new TreeMap();
sm.put("map", "TreeMap");
sm.put("schildt", "Java2");
sm.put("mathew", "Hyden");
sm.put("schildt", "Java2s");
print(sm.keySet());
print(sm.values());
LinkedHashMap lm = new LinkedHashMap();
lm.put("map", "LinkedHashMap");
lm.put("schildt", "Java2");
lm.put("mathew", "Hyden");
lm.put("schildt", "Java2s");
print(lm.keySet());
print(lm.values());
3つのクラスすべてがMap
インターフェースを実装し、ほとんど同じ機能を提供します。最も重要な違いは、エントリを反復処理する順序です。
HashMap
は、繰り返しの順序について絶対に保証しません。新しい要素が追加されると、完全に変更される可能性があります(そして変更される予定もあります)。TreeMap
は、それらのcompareTo()
メソッド(または外部から提供されたComparator
)に従って、キーの "自然な順序"に従って繰り返します。さらに、このソート順に依存するメソッドを含む SortedMap
インターフェースを実装しています。LinkedHashMap
はエントリーがマップに入れられた順番で繰り返します"Hashtable" はハッシュベースのマップの総称です。 Java APIのコンテキストでは、Hashtable
は、コレクションフレームワークが存在する前のJava 1.1の時代からの時代遅れのクラスです。そのAPIは機能を複製する廃止されたメソッドで雑然としていて、そのメソッドは同期されているので(これはもう使用すべきではありません)(これはパフォーマンスを低下させる可能性があり、一般に無用です)。 Hashtableの代わりに ConcurrentHashMap を使用します。
私は視覚的な表現を好みます:
╔══════════════╦═════════════════════╦═══════════════════╦═════════════════════╗
║ Property ║ HashMap ║ TreeMap ║ LinkedHashMap ║
╠══════════════╬═════════════════════╬═══════════════════╬═════════════════════╣
║ Iteration ║ no guarantee order ║ sorted according ║ ║
║ Order ║ will remain constant║ to the natural ║ insertion-order ║
║ ║ over time ║ ordering ║ ║
╠══════════════╬═════════════════════╬═══════════════════╬═════════════════════╣
║ Get/put ║ ║ ║ ║
║ remove ║ O(1) ║ O(log(n)) ║ O(1) ║
║ containsKey ║ ║ ║ ║
╠══════════════╬═════════════════════╬═══════════════════╬═════════════════════╣
║ ║ ║ NavigableMap ║ ║
║ Interfaces ║ Map ║ Map ║ Map ║
║ ║ ║ SortedMap ║ ║
╠══════════════╬═════════════════════╬═══════════════════╬═════════════════════╣
║ ║ ║ ║ ║
║ Null ║ allowed ║ only values ║ allowed ║
║ values/keys ║ ║ ║ ║
╠══════════════╬═════════════════════╩═══════════════════╩═════════════════════╣
║ ║ Fail-fast behavior of an iterator cannot be guaranteed ║
║ Fail-fast ║ impossible to make any hard guarantees in the presence of ║
║ behavior ║ unsynchronized concurrent modification ║
╠══════════════╬═════════════════════╦═══════════════════╦═════════════════════╣
║ ║ ║ ║ ║
║Implementation║ buckets ║ Red-Black Tree ║ double-linked ║
║ ║ ║ ║ buckets ║
╠══════════════╬═════════════════════╩═══════════════════╩═════════════════════╣
║ Is ║ ║
║ synchronized ║ implementation is not synchronized ║
╚══════════════╩═══════════════════════════════════════════════════════════════╝
3つすべてが一意のキーから値へのマッピングを表しているため、 Map インターフェイスを実装しています。
HashMapは ハッシュ のキーに基づくマップです。 O(1) get/put操作をサポートしています。これが機能するには、キーは hashCode()
とequals()
の一貫した実装を持たなければなりません。
LinkedHashMapはHashMapと非常によく似ていますが、アイテムが追加(またはアクセス)される順序に意識を追加するため、繰り返し順序は挿入順序(または構築パラメーターによってはアクセス順序)と同じです。
TreeMapはツリーベースのマッピングです。そのput/get操作にはO(log n)時間がかかります。アイテムには、ComparableまたはComparatorのいずれかを使用した比較メカニズムが必要です。繰り返しの順序はこのメカニズムによって決まります。
次の図で、各クラスがクラス階層のどこにあるかを確認してください( 大きい方 )。 TreeMapはSortedMap
とNavigableMap
を実装しますが、HashMap
は実装しません。
HashTable
は廃止されており、対応するConcurrentHashMap
クラスを使用する必要があります。
私がそれぞれの地図をいつ使うかについての、私自身の地図の経験からのちょっとしたインプット。
removeEldestEntry()
メソッドをオーバーライドしてCacheオブジェクトを作成するための優れた出発点にもなります。これにより、定義したいくつかの基準を使用してデータを期限切れにすることができるCacheオブジェクトを作成できます。3つのクラスHashMap
、TreeMap
およびLinkedHashMap
はすべてJava.util.Map
インターフェースを実装し、固有キーから値へのマッピングを表します。
HashMap
はキーに基づく値を含みます。
それは唯一の要素を含みます。
1つのnullキーと複数のnull値があります。
順序なしを維持します。
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable
LinkedHashMap
はキーに基づく値を含みます。HashMapが代わりに挿入順序を維持するのと同じです。 //下記のクラスの減速度を参照
public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>
TreeMap
はキーに基づく値を含みます。 NavigableMapインターフェースを実装し、AbstractMapクラスを拡張します。HashMap
が代わりに昇順を維持するのと同じです(キーの自然な順序でソートされます)。
public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Cloneable, Serializable
それはレガシークラスです。
public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable, Serializable
HashMapは繰り返しの順序については絶対に保証しません。新しい要素が追加されると、完全に変更される可能性があります(そして変更される予定もあります)。 TreeMapは、compareTo()メソッド(または外部から提供されたComparator)に従って、キーの「自然順序付け」に従って反復します。さらに、このソート順に依存するメソッドを含むSortedMapインターフェースを実装しています。 LinkedHashMapはエントリがマップに入れられた順番で繰り返します。
パフォーマンスの変化を見てください。
ソートマップの実装であるツリーマップ。 Naturalの順序付けのため、put、get、およびcontainsKey操作の複雑さはO(log n)です。
@Amit:SortedMap
はインターフェースですが、TreeMap
はSortedMap
インターフェースを実装するクラスです。それはもしSortedMap
がその実装者にするように頼むプロトコルに従うならば意味します。木は検索木として実装されない限り、木はどんな種類の木でもあり得るのであなたに順序付けされたデータを与えることができません。そのため、TreeMapをソート順のように機能させるために、SortedMapを実装しています(Binary Search Tree - BST、AVLやR-B TreeのようなBST、さらにはTernary Search Treeなど)。
public class TreeMap<K,V>
extends AbstractMap<K,V>
implements SortedMap<K,V>, Cloneable, Serializable
NUT-Shellの場合HashMap
:O(1)のデータを並べ替えません。
TreeMap
:O(log N)、2を基数とするデータを順序付けされたキーとともに与える
LinkedHashMap
:ツリーに挿入される方法でデータを格納するためのリンクリスト(indexed-SkipListと考えてください)機能を持つハッシュテーブルです。 LRUの実装に最も適しています(最低使用頻度)。
以下はHashMapとTreeMapの主な違いです
HashMapは順序を維持しません。つまり、HashMapは、最初に挿入された要素が最初に印刷されるという保証はありません。TreeSetと同様に、TreeMap要素も要素の自然順序付けに従って並べ替えられます。
内部HashMap実装はHashingを使用し、TreeMapは内部的に赤黒ツリー実装を使用します。
HashMapは1つのnullキーと多くのnull値を格納できます。TreeMapにはnullキーを含めることはできませんが、多くのnull値を含めることができます。
HashMapは、getやputなどの基本操作、つまりO(1)に対して一定の時間パフォーマンスを発揮します。Oracleのドキュメントによると、TreeMapはgetおよびputメソッドに対してlog(n)の時間コストを保証します。
HashMapのパフォーマンス時間は、ほとんどの操作でログ時間TreeMapに対して一定であるため、HashMapはTreeMapよりはるかに高速です。
HashMapは比較にequals()メソッドを使用し、TreeMapは順序を維持するためにcompareTo()メソッドを使用します。
HashMapはMapインターフェースを実装し、TreeMapはNavigableMapインターフェースを実装します。
これらは同じインターフェースの異なる実装です。各実装には、長所と短所(高速挿入、低速検索)、またはその逆があります。
詳細については、 TreeMap 、 HashMap 、 LinkedHashMap のjavadocを参照してください。
ハッシュマップ:
LinkedHashMap:
TreeMap:
ハッシュマップは挿入順序を保存しません。
例ハッシュマップ
1 3
5 9
4 6
7 15
3 10
それを保存することができます
4 6
5 9
3 10
1 3
7 15
リンクハッシュマップは挿入順序を保持します。
例です。
キーを挿入している場合
1 3
5 9
4 6
7 15
3 10
それはとして保存されます
1 3
5 9
4 6
7 15
3 10
挿入するのと同じです。
ツリーマップは値をキーの昇順に格納します。例です。
キーを挿入している場合
1 3
5 9
4 6
7 15
3 10
それはとして保存されます
1 3
3 10
4 6
5 9
7 15
すべてがキー - >値マップとキーを反復処理する方法を提供します。これらのクラス間の最も重要な違いは、時間保証とキーの順序です。
以下の関数に空のTreeMap、HashMap、およびLinkedHashMapを渡したとします。
void insertAndPrint(AbstractMap<Integer, String> map) {
int[] array= {1, -1, 0};
for (int x : array) {
map.put(x, Integer.toString(x));
}
for (int k: map.keySet()) {
System.out.print(k + ", ");
}
}
それぞれの出力は以下の結果のようになります。
HashMapの場合、出力は私自身のテストでは{0、1、-1}でしたが、順序は任意です。注文に関する保証はありません。
ツリーマップ、出力は{-1、0、1}
LinkedList、出力は{1、-1、0}でした
ハッシュマップ
にはヌルキーを1つ含めることができます。
HashMapは順序を維持しません。
ツリーマップ
TreeMapにはnullキーを含めることはできません。
TreeMapは昇順を維持します。
LinkedHashMap
LinkedHashMapを使用して、Mapにキーが挿入される挿入順序を維持したり、キーがアクセスされるアクセス順序を維持したりすることができます。
例 ::
1)HashMap map = new HashMap();
map.put(null, "Kamran");
map.put(2, "ALi");
map.put(5, "From");
map.put(4, "Dir");`enter code here`
map.put(3, "Lower");
for (Map.Entry m : map.entrySet()) {
System.out.println(m.getKey() + " " + m.getValue());
}
2)TreeMapマップ= new TreeMap();
map.put(1, "Kamran");
map.put(2, "ALi");
map.put(5, "From");
map.put(4, "Dir");
map.put(3, "Lower");
for (Map.Entry m : map.entrySet()) {
System.out.println(m.getKey() + " " + m.getValue());
}
3)LinkedHashMap map = new LinkedHashMap();
map.put(1, "Kamran");
map.put(2, "ALi");
map.put(5, "From");
map.put(4, "Dir");
map.put(3, "Lower");
for (Map.Entry m : map.entrySet()) {
System.out.println(m.getKey() + " " + m.getValue());
}