2

効率的なクエリとポジションのサブセット ビュー (サブリストなど) も可能にする広告掲載オーダー コレクションを探しています。これに対する最も簡単なオプションは、List のリンク リスト アプローチを採用し、ノードをマップ値として埋め込み、クラスのリスト インターフェイスの一部またはすべてを公開することです。

誰かがこれについてオラクルに愚痴をこぼしますか? ソートされたマップとセットに NavigableMap/Set を追加し、はるかに一般的な挿入順序に相当するものを持たない...

編集: LinkedHashSet を提案しないでください - 位置を照会したり、相対的なサブセットを実行したりする方法はありません。

4

2 に答える 2

2

あなたはjava.util.LinkedHashSetのように意味します:

Set インターフェイスのハッシュ テーブルとリンク リストの実装。反復順序は予測可能です。この実装が HashSet と異なる点は、そのすべてのエントリを実行する二重リンク リストを維持することです。このリンクされたリストは、要素がセットに挿入された順序 (挿入順序) である反復順序を定義します。要素がセットに再挿入されても、挿入順序は影響を受けないことに注意してください。(呼び出しの直前に s.contains(e) が true を返すときに s.add(e) が呼び出されると、要素 e はセット s に再挿入されます。)

于 2012-08-16T23:34:42.717 に答える
0

edit2: 新しい最終バージョンこれは、機能がわずかに調整されたセットのみのバージョンです (2 つに分割され、「マップの開始」として null を受け入れなくなりました)、おそらくバグが少なくなります。

public class LinkedSet<E> implements Set<E> {

private LinkedHashMap<E, Integer> m = new LinkedHashMap<E, Integer>();
private int monoticallyIncreasing;

/**
 * Returns true if the value target was added before (exclusive)
 * limitElem in insertion order.
 *
 * If target or limit are not present on the set this method returns false
 *
 * @param limitElem a E that may be a element of the set or not.
 * @return if target was added before limit (can be reset by removing and
 * re-adding the target, that changes iteration order).
 */
public boolean containsBefore(E target, E limitElem) {
    if (isEmpty()) {
        return false;
    }

    Integer targetN = m.get(target);
    if (targetN == null) {
        return false;
    }

    Integer highN = m.get(limitElem);
    if (highN == null) {
        return false;
    }
    return targetN < highN;
}

/**
 * Returns true if the value target was added after (exclusive)
 * previousElem in insertion order.
 *
 * If target or previous are not present on the set this method returns false
 *
 * @param previousElem a E that may be a element of the set or not.
 * @return if target was added before previous (can be reset by removing and
 * re-adding the target, that changes iteration order).
 */
public boolean containsAfter(E target, E previousElem) {
    if (isEmpty()) {
        return false;
    }

    Integer targetN = m.get(target);
    if (targetN == null) {
        return false;
    }

    Integer low = m.get(previousElem);
    if (low == null) {
        return false;
    }
    return low < targetN;
}

@Override
public boolean add(E e) {
    Integer pos = m.get(e);
    if (pos == null) {
        m.put(e, monoticallyIncreasing++);
        return true;
    }
    return false;
}

@Override
public int size() {
    return m.size();
}

@Override
public boolean isEmpty() {
    return m.isEmpty();
}

@Override
public boolean contains(Object o) {
    return m.containsKey(o);
}

@Override
public Object[] toArray() {
    Object[] result = new Object[size()];
    int i = 0;
    for (E e : this) {
        result[i++] = e;
    }
    return result;
}

@Override
@SuppressWarnings("unchecked")
public <T> T[] toArray(T[] a) {
    int size = size();
    if (a.length < size) {
        a = (T[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);
    }
    int i = 0;
    Object[] result = a;
    for (E e : this) {
        result[i++] = e;
    }
    if (a.length > size) {
        //peculiar toArray contract where it doesn't care about the rest
        a[size] = null;
    }
    return a;
}

@Override
public boolean remove(Object o) {
    return m.remove(o) != null;
}

@Override
public boolean addAll(Collection<? extends E> c) {
    boolean changed = false;
    for (E e : c) {
        changed |= add(e);
    }
    return changed;
}

@Override
public boolean containsAll(Collection<?> c) {
    return m.keySet().containsAll(c);
}

@Override
public boolean retainAll(Collection<?> c) {
    return m.keySet().retainAll(c);
}

@Override
public boolean removeAll(Collection<?> c) {
    return m.keySet().removeAll(c);
}

@Override
public void clear() {
    m.clear();
}

@Override
public Iterator<E> iterator() {
    return m.keySet().iterator();
}
}
于 2012-08-17T10:13:20.457 に答える