好问题。
这是一种非常常见的情况,通常通过编写两个单独的方法来处理。然而,重复代码确实是一个坏主意,每当你发现自己在重复代码时,你应该开始寻找机会来更好地分解你的代码。(正如你现在所做的那样!)
现在,如果您查看 的源代码java.util.Arrays
,您会注意到它Arrays.asList
重新运行了一个私有内部类的实例,该实例Arrays.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();
}
}