List、Setのパフォーマンス、メモリ割り当て、使いやすさの比較を知りたいです。
オブジェクトのリストで一意性を維持する必要がない場合、挿入順序を維持する必要もありません。ArrayListとSortedSet/HashSetを同じように使用できますか? list/setでなく、Collectionsクラスを直接使用するのは良いでしょうか?
追伸また、Javaが提供する特定の関数をリストしたり設定したりする必要もありません。配列の代わりにリスト/セットを使用しているのは、追加のプログラミング作業なしで動的に成長できるからです。
順序を気にせず、要素を削除しない場合、実際には、このデータ構造内で要素を見つける必要があるかどうか、およびそれらのルックアップをどれだけ速くするかが重要になります。
HashSet
の値で要素を見つけることはO(1)
です。 ArrayList
では、O(n)
です。
コンテナを使用して一意のオブジェクトの束を格納し、最後に(任意の順序で)繰り返し処理する場合は、ArrayList
の方が簡単で経済的であるため、おそらくより良い選択です。
HashSet
は、同じ数の要素に対してArrayList
の約5.5倍のメモリを消費し(どちらもまだ線形ですが)、反復が大幅に遅くなります(同じ漸近性ではありますが)。簡単なGoogle検索では、HashSet
の反復がArrayList
に対して2〜3倍遅くなることが示唆されています。
contains
の一意性やパフォーマンスを気にしない場合は、ArrayList
を使用します。
要素を追加するだけで、後でそれらを反復する場合、最善の方法は、置換する配列に最も近いArrayList
です。 LinkedList
またはSet
実装よりもメモリ効率が高く、挿入、反復、ランダムアクセスが高速です。
リストとセットを検索して比較すると、下線のハッシュアルゴリズムによりセットの方が優れています。
リストの場合、最悪の場合、containsは最後まで検索します。 Setの場合、ハッシュとバケットのため、サブセットのみを検索します。
ユースケースの例:ArrayListおよびHashSetに1〜100_000の整数を追加します。 ArrayListおよびHashSetの各整数を検索します。
セットには9ミリ秒かかりますが、リストには16232秒かかります。
private static void compareSetvsList(){
List<Integer> list = new ArrayList<>() ;
Set<Integer> set = new HashSet<>() ;
System.out.println("Setting values in list and set .... ");
int counter = 100_000 ;
for(int i =0 ; i< counter ; i++){
list.add(i);
set.add(i);
}
System.out.println("Checking time .... ");
long l1 = System.currentTimeMillis();
for(int i =0 ; i< counter ; i++) list.contains(i);
long l2 = System.currentTimeMillis();
System.out.println(" time taken for list : "+ (l2-l1));
for(int i =0 ; i< counter ; i++)set.contains(i);
long l3 = System.currentTimeMillis();
System.out.println(" time taken for set : "+ (l3-l2));
// for 10000 time taken for list : 123 time taken for set : 4
// for 100000 time taken for list : 16232 time taken for set : 9
// for 1000000 time taken for list : hung time taken for set : 26
}
.contains(T)
を頻繁に使用する必要がある場合は、HashSet
を使用します。
例:
private static final HashSet<String> KEYWORDS = Stream.of(new String[]{"if", "do", "for", "try", "while", "break", "return"}).collect(Collectors.toCollection(HashSet::new));
public boolean isKeyword(String str) {
return KEYWORDS.contains(str);
}
collectionに一意の要素を含める必要がない場合は、特別なニーズがない限り、単にArrayList
を使用します。
collectionに一意の要素のみを含める必要がある場合は、特別なニーズがない限りHashSet
を使用します。
SortedSet
(およびその実装者TreeSet
)については、JavaDocに従って:
要素の全体的な順序付けをさらに提供するセット。要素は、自然な順序を使用して、またはソートセットの作成時に通常提供されるコンパレータによって順序付けられます。
つまり、通常は必要ないset
で要素を常に順序付けする必要がある、非常に特定のユースケースを対象としています。