Java 如何编写一个既适用于列表又适用于数组的方法?
我有一个方法如下所示:Java 如何编写一个既适用于列表又适用于数组的方法?,java,arrays,list,Java,Arrays,List,我有一个方法如下所示: void foo (List<String> list, ...) { ... for (String s : list) { // this is the only place where `list` is used ... } ... } void foo(列表,…){ ... 对于(字符串s:list){//这是唯一使用'list'的地方 ... } ... } 如果我用String[]List替换List,同样的代码也会起
void foo (List<String> list, ...) {
...
for (String s : list) { // this is the only place where `list` is used
...
}
...
}
void foo(列表,…){
...
对于(字符串s:list){//这是唯一使用'list'的地方
...
}
...
}
如果我用String[]List
替换List
,同样的代码也会起作用,但是,为了避免意大利面代码,我保留了单一的方法,当我需要在数组a
上调用它时,我会这样做:foo(Arrays.asList(a))
我不知道这是不是正确的方法
具体来说,
数组.asList()的开销是多少
- 有没有一种方法可以编写一个同时接受数组和列表的方法,就像
循环那样for
Arrays.asList()
的开销很小。对于列表
和数组
,没有真正的方法实现一种方法
但您可以执行以下操作:
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),...);
}
}
void foo(列表,…){
...
对于(字符串s:list){//这是唯一使用*list*的地方
...
}
...
}
void foo(字符串[]arr,…){
如果(arr!=null){
foo(Arrays.asList(arr),…);
}
}
开销在于它将一个数组转换为一个列表——它如何转换取决于实现,它只需要履行契约
在我看来,如果您担心潜在的运行时开销,您应该编写两种方法:这是Java的本质;方法有类型签名,必须遵守它们。请避免这种情况,我只使用并允许列表、集合和映射()。无法合并这两种“集合类型” 另一种方法是使用(迭代器/迭代器)。因此,您可以在不需要深度拷贝的情况下对您的收藏进行Iterarch。来自,
数组的源代码。asList
:
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
所以基本上所有这些都发生在作业中,所以开销应该可以忽略不计。好问题
这是一种非常常见的情况,通常通过编写两个单独的方法来处理。然而,代码复制确实是一个坏主意,当您发现自己在复制代码时,您应该开始寻找更好地考虑代码的机会。(就像你现在做的一样!)
现在,如果您查看java.util.Arrays
的源代码,您会注意到Arrays.asList
ret运行私有内部类Arrays.ArrayList
的一个实例,它只是普通数组上的一个薄型包装器,并将所有相关方法调用委托给它。(这被称为数据结构的投影或视图。)因此产生的开销是微不足道的(除非您正在努力提取性能的最后一点),在我看来,您应该继续使用这种方法,而不必担心性能
我个人使用的解决方案如下 在我的个人utils中有一个名为
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();
}
}
public类RichIterable实现了Iterable{
私有可移植X;
private RichIterable(Iterable xs){
this.xs=xs;
}
公共静态RichIterable from(Iterable xs){
if(xs instanceof RichIterable){
返回(RichIterable)xs;
}否则{
返回新的RichIterable(xs);
}
}
公共静态RichIterable from(最终枚举xs){
Iterable Iterable=新的Iterable(){
@凌驾
公共迭代器迭代器(){
返回新的迭代器(){
@凌驾
公共布尔hasNext(){
返回xs.hasMoreElements();
}
@凌驾
公共A下一个(){
返回xs.nextElement();
}
@凌驾
公共空间删除(){
抛出新的UnsupportedOperationException(
“无法从枚举中删除元素。”);
}
};
}
};
返回RichIterable.from(iterable);
}
公共静态RichIterable from(最终A[]xs){
Iterable Iterable=新的Iterable(){
@凌驾
公共迭代器迭代器(){
返回新的迭代器(){
私有整数i=0;
@凌驾
公共布尔hasNext(){
返回ipublic 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();
}
}