2

この特定の質問に対する直接的な答えが見つからなかったので...クラスを想定します:

class MyClass {
    private final Set<String> tags;

    MyClass(Set<String> initialTags) {
        this.tags = ???(initialtags);
    }
}

セットの正確な実装を気にせず、最小限のオーバーヘッドでコピーが必要なだけなので、基本的には initialTags の内部状態の直接コピーが必要です。cloneSet はインターフェイスなので、使用できません。これは可能ですか、またはnew HashSet<String>(tags);タイプについて決定する必要があるようなものを使用する必要がありますか?

前提: セット項目タイプは不変に制限されています。呼び出し元が壊れた Set 実装を渡さないinitialTagsことを信頼できます。また、このクラスで内部的に使用するのに十分なパフォーマンスが得られることを信頼できます。

リフレクションとclone()を試してみようと思っているのですが、これはちょっと汚いような気がします...

4

3 に答える 3

4

Guava はそのための方法を提供します。

  /**
   * Returns an immutable set containing the given elements, in order. Repeated
   * occurrences of an element (according to {@link Object#equals}) after the
   * first are ignored. This method iterates over {@code elements} at most once.
   *
   * <p>Note that if {@code s} is a {@code Set<String>}, then {@code
   * ImmutableSet.copyOf(s)} returns an {@code ImmutableSet<String>} containing
   * each of the strings in {@code s}, while {@code ImmutableSet.of(s)} returns
   * a {@code ImmutableSet<Set<String>>} containing one element (the given set
   * itself).
   *
   * <p>Despite the method name, this method attempts to avoid actually copying
   * the data when it is safe to do so. The exact circumstances under which a
   * copy will or will not be performed are undocumented and subject to change.
   *
   * @throws NullPointerException if any of {@code elements} is null
   */
  public static <E> ImmutableSet<E> copyOf(Iterable<? extends E> elements) {
    return (elements instanceof Collection)
        ? copyOf(Collections2.cast(elements))
        : copyOf(elements.iterator());
  }
于 2012-11-02T09:39:09.773 に答える
1

initialTags の予想されるサイズに応じて、異なる実装を好む場合があります。以下のコードは、 の場合はコンストラクター ベースのコピーの方が速いことを示していますi is < 100000が、 の場合はクローンの方が高速i > 1000000です。本当に使用したい場合は、(6)よく知られている具体的な実装(その実装)のどれがそれであるかを判断するためにcloneいつでも使用できますが、それを超える保証はありません。isinstancecloneableinitialTags

static Set<String> byCloning(HashSet<String> initialTags) {

    return (Set<String>) initialTags.clone();
}

static Set<String> byConstructor(Set<String> initialTags) {

    return new HashSet<String>(initialTags);
}

public static void main(String[] args) {

    int N = Integer.parseInt(args[0]);

    HashSet<String> mySet = new HashSet<String>();
    for (int n = 0 ; n < N ; n++) mySet.add(Integer.toString(n));

    long start = System.currentTimeMillis();
    byCloning(mySet);
    long end = System.currentTimeMillis();
    System.out.println(" time take in milli seconds for cloning = " + (end-start) );

    start = System.currentTimeMillis();
    byConstructor(mySet);
    end = System.currentTimeMillis();
    System.out.println(" time take in milli seconds by constructor = " + (end-start) );
}
于 2012-11-02T10:05:10.370 に答える
0

セットに必要なアクセスの種類に基づいてタイプを決定するか、Collections.unmodifiableSet ()を使用してみてください。

class MyClass {
    private final Set<String> tags;

    MyClass(Set<String> initialTags) {
        this.tags = Collections.unmodifiableSet(initialTags);
    }
}
于 2012-11-02T09:31:57.443 に答える