誰かがObjective-Cに精通している場合NSOrderedSet
、Setとして機能すると呼ばれるコレクションがあり、その項目にはArrayの項目としてアクセスできます。
Javaでこのようなものはありますか?
と呼ばれるコレクションがあると聞いたことがありますがLinkedHashMap
、セットのようなコレクションは見つかりませんでした。
誰かがObjective-Cに精通している場合NSOrderedSet
、Setとして機能すると呼ばれるコレクションがあり、その項目にはArrayの項目としてアクセスできます。
Javaでこのようなものはありますか?
と呼ばれるコレクションがあると聞いたことがありますがLinkedHashMap
、セットのようなコレクションは見つかりませんでした。
回答:
LinkedHashSetクラスを見てください。
予測可能な反復順序を備えた、Setインターフェイスのハッシュテーブルとリンクリストの実装。この実装は、すべてのエントリで実行される二重リンクリストを維持するという点でHashSetとは異なります。このリンクされたリストは、要素がセットに挿入された順序(挿入順序)である反復順序を定義します。要素がセットに再挿入されても、挿入順序は影響を受けないことに注意してください。(s.contains(e)が呼び出しの直前にtrueを返すときにs.add(e)が呼び出された場合、要素eはセットsに再挿入されます。)
LinkedHashMap
ているように見えますが、どういうわけかわかりません。
LinkedHashSet
要素がどのインデックスにあるかを把握できる関数はありません。
すべてのセットにはiterator()があります。通常のHashSetの反復子は非常にランダムです。TreeSetはソート順でそれを行い、LinkedHashSet反復子は挿入順で反復します。
ただし、LinkedHashSetの要素を置き換えることはできません。1つを削除して別の要素を追加できますが、新しい要素は元の要素の代わりにはなりません。LinkedHashMapでは、既存のキーの値を置き換えても、値は元の順序のままです。
また、特定の位置に挿入することはできません。
おそらく、重複の挿入を避けるために、明示的なチェックを含むArrayListを使用する方がよいでしょう。
LinkedHashSet
を行うべき縫い目です。返信ありがとう
見てみましょうJavaの標準APIドキュメントを。のすぐ隣LinkedHashMap
にがありLinkedHashSet
ます。ただし、これらの順序は挿入順序であり、要素の自然な順序ではないことに注意してください。そして、その順序でのみ反復でき、ランダムアクセスはできません(反復ステップを数えることを除く)。
およびSortedSet
によって実装されたインターフェイスもあります。どちらも要素の自然順序またはでの反復を許可しますが、ランダムアクセスまたは挿入順序は許可しません。TreeSet
ConcurrentSkipListSet
Comparator
インデックスによる効率的なアクセスと設定基準の効率的な実装の両方が可能なデータ構造の場合、スキップリストが必要になりますが、Java標準APIにはその機能を備えた実装はありませんが、簡単に見つけることができます。インターネット上で。
ConcurrentSkipListMap
およびConcurrentSkipListSet
。どちらも自然順またはコンパレータに基づいてソートを維持します。それらがあなたが議論するランダムアクセスまたはエントリーの順序を提供するかどうかはわかりません。
TreeSet
注文しました。
http://docs.oracle.com/javase/6/docs/api/java/util/TreeSet.html
java.util.TreeSet
その実装を使用してみてくださいSortedSet
。
ドキュメントを引用するには:
「要素は、使用されるコンストラクターに応じて、自然な順序を使用して、またはセットの作成時に提供されるコンパレーターによって順序付けられます。」
add、remove、containsには時間コストlog(n)があることに注意してください。
セットのコンテンツに配列としてアクセスする場合は、次のように変換できます。
YourType[] array = someSet.toArray(new YourType[yourSet.size()]);
この配列は、TreeSetと同じ基準で(自然またはコンパレーターによって)ソートされます。多くの場合、これはArrays.sort()を実行する代わりに利点があります。
c
とその要素a
:私は同じ順番でそれらを取得したいコレクションのI反復として、c
、a
など
スキップリストの安価な実装について話している場合、大きなOの観点から、この操作のコストはどのくらいなのでしょうか。
YourType [] array = someSet.toArray(new YourType [yourSet.size()]);
つまり、常に配列全体の作成に行き詰まっているので、O(n)です。
java.util.Arrays#copyOf
size()
と、基になるセットのメソッドによって異なります。反復は通常O(n)
、サイズは通常、それO(1)
がConcurrentSkipListSet
どこにあるかを除いてですO(n)
。
indexed-tree-mapプロジェクトのIndexedTreeSetは、この機能を提供します(インデックスによるリストのようなアクセス権を持つ順序付け/ソートされたセット)。
Google Guavaのような双方向マップBiMap
からユーティリティを取得することもできます
を使用するBiMap
と、整数(ランダムインデックスアクセス用)を他のオブジェクトタイプにかなり効率的にマップできます。BiMap
sは1対1なので、指定された整数には最大で1つの要素が関連付けられ、要素には1つの整数が関連付けられます。それは巧み2つのによって支えられていますHashTable
、それはほぼ倍のメモリを使用していますので、インスタンスが、それはカスタムより多くの方が効率的ですList
ので、加工限り、contains()
一定の時間です(アイテムは、それがすでに存在するかどうかを確認するために追加されたときに呼び出されました)等平行フレンドリーな操作HashSet
のは、一方List
の実装では、LOT遅いです。
同様の問題がありました。順序付けされたセットはまったく必要ありませんでしたが、高速なindexOf
/のリストがもっと必要でしたcontains
。そこには何も見つからなかったので、自分で実装しました。これがコードで、との両方Set
を実装していますが、List
すべての一括リスト操作がArrayList
バージョンほど高速であるとは限りません。
免責事項:テストされていません
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
import java.util.Collection;
import java.util.Comparator;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import static java.util.Objects.requireNonNull;
/**
* An ArrayList that keeps an index of its content so that contains()/indexOf() are fast. Duplicate entries are
* ignored as most other java Set's do.
*/
public class IndexedArraySet<E> extends ArrayList<E> implements Set<E> {
public IndexedArraySet() { super(); }
public IndexedArraySet(Iterable<E> c) {
super();
addAll(c);
}
private HashMap<E, Integer> indexMap = new HashMap<>();
private void reindex() {
indexMap.clear();
int idx = 0;
for (E item: this) {
addToIndex(item, idx++);
}
}
private E addToIndex(E e, int idx) {
indexMap.putIfAbsent(requireNonNull(e), idx);
return e;
}
@Override
public boolean add(E e) {
if(indexMap.putIfAbsent(requireNonNull(e), size()) != null) return false;
super.add(e);
return true;
}
@Override
public boolean addAll(Collection<? extends E> c) {
return addAll((Iterable<? extends E>) c);
}
public boolean addAll(Iterable<? extends E> c) {
boolean rv = false;
for (E item: c) {
rv |= add(item);
}
return rv;
}
@Override
public boolean contains(Object e) {
return indexMap.containsKey(e);
}
@Override
public int indexOf(Object e) {
if (e == null) return -1;
Integer i = indexMap.get(e);
return (i == null) ? -1 : i;
}
@Override
public int lastIndexOf(Object e) {
return indexOf(e);
}
@Override @SuppressWarnings("unchecked")
public Object clone() {
IndexedArraySet clone = (IndexedArraySet) super.clone();
clone.indexMap = (HashMap) indexMap.clone();
return clone;
}
@Override
public void add(int idx, E e) {
if(indexMap.putIfAbsent(requireNonNull(e), -1) != null) return;
super.add(idx, e);
reindex();
}
@Override
public boolean remove(Object e) {
boolean rv;
try { rv = super.remove(e); }
finally { reindex(); }
return rv;
}
@Override
public void clear() {
super.clear();
indexMap.clear();
}
@Override
public boolean addAll(int idx, Collection<? extends E> c) {
boolean rv;
try {
for(E item : c) {
// check uniqueness
addToIndex(item, -1);
}
rv = super.addAll(idx, c);
} finally {
reindex();
}
return rv;
}
@Override
public boolean removeAll(Collection<?> c) {
boolean rv;
try { rv = super.removeAll(c); }
finally { reindex(); }
return rv;
}
@Override
public boolean retainAll(Collection<?> c) {
boolean rv;
try { rv = super.retainAll(c); }
finally { reindex(); }
return rv;
}
@Override
public boolean removeIf(Predicate<? super E> filter) {
boolean rv;
try { rv = super.removeIf(filter); }
finally { reindex(); }
return rv;
}
@Override
public void replaceAll(final UnaryOperator<E> operator) {
indexMap.clear();
try {
int duplicates = 0;
for (int i = 0; i < size(); i++) {
E newval = requireNonNull(operator.apply(this.get(i)));
if(indexMap.putIfAbsent(newval, i-duplicates) == null) {
super.set(i-duplicates, newval);
} else {
duplicates++;
}
}
removeRange(size()-duplicates, size());
} catch (Exception ex) {
// If there's an exception the indexMap will be inconsistent
reindex();
throw ex;
}
}
@Override
public void sort(Comparator<? super E> c) {
try { super.sort(c); }
finally { reindex(); }
}
}