4

私はこのように見える方法を持っています:

void foo (List<String> list, ...) {
  ...
  for (String s : list) { // this is the only place where `list` is used
    ...
  }
  ...
}

List<String> listに置き換えるとまったく同じコードが機能しますがString[] list、スパゲッティコードを避けるために、単一のメソッドを保持し、配列で呼び出す必要がある場合は、次のaようにしますfoo(Arrays.asList(a))

これが正しい方法なのだろうか。

具体的には、

  • のオーバーヘッドはArrays.asList()何ですか?
  • forループと同じように、配列とリストの両方を受け入れるメソッドを作成する方法はありますか?

ありがとう!

4

5 に答える 5

6

Arrays.asList()オーバーヘッドが小さい。Listとの両方に1つのメソッドを実装する実際の方法はありませんarrays

ただし、次のことができます。

void foo (List<String> list, ...) {
  ...
  for (String s : list) { // this is the only place where *list* is used
    ...
  }
  ...
}

void foo (String[] arr, ...) {
  if ( arr != null ) {
      foo(Arrays.asList(arr),...);
  }
}
于 2012-06-05T16:15:20.110 に答える
2

openjdkのソースコードから、Arrays.asList

public static <T> List<T> asList(T... a) {
   return new ArrayList<>(a);
}

さらに:

ArrayList(E[] array) {
   if (array==null)
      throw new NullPointerException();
   a = array;
}

つまり、基本的にすべてが割り当てで発生するため、オーバーヘッドは無視できるはずです。

于 2012-06-05T16:19:04.943 に答える
1

オーバーヘッドは、配列をリストに変換することです。これを行う方法は実装に依存し、コントラクトを実行するだけで済みます。

IMO実行時のオーバーヘッドの可能性が心配な場合は、2つのメソッドを作成する必要があります。これがJavaの性質です。メソッドには型シグネチャがあり、従う必要があります。

于 2012-06-05T16:15:59.083 に答える
1

これは避けてください。リスト、セット、マップを使用して許可します(Joshua Blochが教えてくれたように)。両方の「コレクションタイプ」をマージする方法はありません。

別の方法は、グアバ(Iterators / Iteratables)を使用することです。したがって、コレクションの深いコピーがなくても、コレクションを反復処理できます。

于 2012-06-05T16:16:15.977 に答える
1

良い質問。

これは非常に一般的なケースであり、多くの場合、2つの別々のメソッドを作成することで処理されます。ただし、コードの複製は本当に悪い考えであり、コードを複製していることに気付いたときはいつでも、コードをより適切に因数分解する機会を探し始める必要があります。(あなたが今しているように!)

ここで、のソースを調べると、プレーン配列の単なる薄いラッパーであるプライベート内部クラスのインスタンスを再実行し、関連するすべてのメソッド呼び出しをそれに委任しjava.util.Arraysていることがわかります。(これは、データ構造の投影またはビューとして知られています。)したがって、発生するオーバーヘッドは重要ではありません(パフォーマンスの最後のビットをすべて抽出しようとしている場合を除く)。私の意見では、心配せずにこの方法を使用する必要があります。パフォーマンスについて。Arrays.asListArrays.ArrayList


私が個人的に使用している解決策は次のとおりです。

RichIterable私の個人的なユーティリティで名前が付けられたクラスがあります。名前が示すように、クラスはラップオーバーしIterable、まだ存在しないいくつかの追加の便利なメソッドを提供します。RichIterableこのクラスには、配列からを作成するファクトリメソッドもあります。これがクラスの定義です。

public class RichIterable<A> implements Iterable<A> {
  private Iterable<A> xs;

  private RichIterable(Iterable<A> xs) {
    this.xs = xs;
  }

  public static <A> RichIterable<A> from(Iterable<A> xs) {
    if (xs instanceof RichIterable) {
      return (RichIterable<A>) xs;
    } else {
      return new RichIterable<A>(xs);
    }
  }

  public static <A> RichIterable<A> from(final Enumeration<A> xs) {
    Iterable<A> iterable = new Iterable<A>() {
      @Override
      public Iterator<A> iterator() {
        return new Iterator<A>() {
          @Override
          public boolean hasNext() {
            return xs.hasMoreElements();
          }

          @Override
          public A next() {
            return xs.nextElement();
          }

          @Override
          public void remove() {
            throw new UnsupportedOperationException(
              "Cannot remove an element from an enumeration.");
          }
        };
      }
    };
    return RichIterable.from(iterable);
  }

  public static <A> RichIterable<A> from(final A[] xs) {
    Iterable<A> iterable = new Iterable<A>() {
      @Override
      public Iterator<A> iterator() {
        return new Iterator<A>() {
          private int i = 0;

          @Override
          public boolean hasNext() {
            return i < xs.length;
          }

          @Override
          public A next() {
            A x = xs[i];
            i++;
            return x;
          }

          @Override
          public void remove() {
            throw new UnsupportedOperationException(
              "Cannot remove an element from an array.");
          }
        };
      }
    };
    return RichIterable.from(iterable);
  }

  public boolean isEmpty() {
    if (xs instanceof Collection) {
      return ((Collection) xs).isEmpty();
    }
    for (A x : xs) {
      return false;
    }
    return true;
  }

  public int size() {
    if (xs instanceof Collection) {
      return ((Collection) xs).size();
    }
    int size = 0;
    for (A x : xs) {
      size++;
    }
    return size;
  }

  public ArrayList<A> toArrayList() {
    ArrayList<A> ys = new ArrayList<A>();
    for (A x : xs) {
      ys.add(x);
    }
    return ys;
  }

  public <B> RichIterable<B> map(F1<A, B> f) {
    List<B> ys = new ArrayList<B>();
    for (A x : xs) {
      ys.add(f.apply(x));
    }
    return RichIterable.from(ys);
  }

  public RichIterable<A> filter(F1<A, Boolean> pred) {
    List<A> ys = new ArrayList<A>();
    Arrays.asList();
    for (A x : xs) {
      if (pred.apply(x)) {
        ys.add(x);
      }
    }
    return RichIterable.from(ys);
  }

  public boolean exists(F1<A, Boolean> pred) {
    for (A x : xs) {
      if (pred.apply(x)) {
        return true;
      }
    }
    return false;
  }

  public boolean forall(F1<A, Boolean> pred) {
    for (A x : xs) {
      if (!pred.apply(x)) {
        return false;
      }
    }
    return true;
  }

  public Maybe<A> find(F1<A, Boolean> pred) {
    for (A x : xs) {
      if (pred.apply(x)) {
        return Just.of(x);
      }
    }
    return Nothing.value();
  }

  public String mkString(String beg, String sep, String end) {
    Iterator<A> i = xs.iterator();
    if (!i.hasNext()) {
      return beg + end;
    }
    StringBuilder sb = new StringBuilder();
    sb.append(beg);
    while (true) {
      A e = i.next();
      sb.append(e.toString());
      if (!i.hasNext()) {
        return sb.append(end).toString();
      }
      sb.append(sep);
    }
  }

  public String mkString(String sep) {
    return mkString("", sep, "");
  }

  public String mkString() {
    return this.mkString(", ");
  }

  public Iterable<A> getRaw() {
    return xs;
  }

  @Override
  public Iterator<A> iterator() {
    return xs.iterator();
  }
}
于 2012-06-05T16:37:28.800 に答える