用类构造函数和另一个数组初始化一个数组

3

我有一个类型为 B[] 的数组。我有一个构造函数 A(B b)

我想使用它们创建一个类型为A[]的数组。

我可以使用for语句来完成这个操作,但我想知道是否有更方便(更短)的方法来实现这个目标。(例如语言语法、静态方法等)

public class A {
    public A(B b) {
        A.a = B.a;
        A.b = B.b * B.c;
        ...
    }
}

public class B {
    ...
}

public class C {
    public static B[] getBs() {
        B[] bs;
        ...
        return bs;
    }
}

void process() {
    // From here
    B[] bs = C.getBs();
    A[] as = new A[bs.length];
    for (int i=0; i<bs.length; i++) {
        as[i] = new A(bs[i]);
    }
    // To here
}

2
你解释这两个数组之间关系的逻辑对我来说有些模糊。也许是我自己的问题,但如果你没有得到好的答案,考虑澄清一下。例如,A.b = B.b * B.c; 这是什么意思?为什么在 A 的构造函数体中使用类型 B 而不是参数 b?A.c 会是什么?A.b 是如何成为一个数组项的?最后,最重要的是,请发布真正的代码,而不是可能是代码,这似乎是你在这里发布的内容。 - Hovercraft Full Of Eels
请尝试发布真实的代码。如果我们能够看到您正在尝试做什么,而不是看到您可能在思考什么,那么我们可能能够提供更多帮助。 - Bmize729
3个回答

4
截至目前,关于语言的现状,你所能做的最好的就是像这样:
interface Transformer<A, B> {
    B transform(A a);
}

class ArrayUtils {
    @SuppressWarnings("unchecked")
    public static <A, B> B[] transformArray(
        Class<B> clazz,
        A[] a,
        Transformer<A, B> transformer
    ) {
        B[] b = (B[])Array.newInstance(clazz, a.length);
        for(int i = 0; i < a.length; i++) {
            b[i] = transformer.transform(a[i]);
        }
        return b;
    }
}

使用方法:

Foo[] foos = // some Foo array
Bar[] bars = 
    ArrayUtils.transformArray(
        Bar.class,
        foos,
        new Transformer<Foo, Bar>() {
            public Bar transform(Foo foo) { return new Bar(foo); } 
        }
    );

这假设:
class Foo { }
class Bar { public Bar(Foo foo) { } }

1: 2014年将会推出一些功能,使得操作更加简便。

2: 各位注意啦,下次从零开始设计类型系统时,请记得及早添加泛型,而不是后来再添加

3: 刚刚匆忙拼凑出来的,如有任何错误请随便改正。:-)


1
这些功能在我的回答中有详细说明 ;) - Jeffrey
@Jeffrey:太棒了。 :-) - jason
在我看来,这有些过度设计了,有太多的样板代码。我会选择自定义循环,它更加轻量、干净、可靠且友好于IDE。模式应该用于使设计更加明显,而不是更少。 - fernacolo

3

目前还没有。在Java 8中,由于Lambda项目的支持,我们将能够使用更多的函数式编程特性,例如映射函数

在Java 8中,以下内容是有效的:

B[] bs = C.getBs();
List<A> aList = Stream.of(bs).map(b -> new A(b)).collect(Collectors.toList());
A[] as = aList.toArray(new A[aList.size()]);

这个使用了lambda表达式和其他几个新特性1,2

虽然这可能不会更加“简短”,但是Stream默认提供并行化,所以如果你在上面的例子中将Stream.of(bs)改为Stream.of(bs).parallel(),它将在多核机器上使用大数组时表现得更好。

/edit
你也可以使用方法引用代替lambda表达式:

map(A::new)代替map(b -> new A(b))


在某种程度上是这样,但它仍然远不如可伸缩性。 - Jeffrey
同意可扩展性的观点。然而,为了值得创建和同步任务,要么项目数量应该非常大(例如10k或更多),要么每个项目的创建都应该是计算密集型的。线程总是引入不确定性(假设B的创建使用缓存...)。 - fernacolo

1

从Java 7开始,您已经使用了最短的循环:

for (int i = 0; i < bs.length; ++i) {
    as[i] = new A(bs[i]);
}

然而,如果您使用集合而不是数组,可以使用“for each”:
for (B b: bs) {
    as.add(new A(b));
}

集合还可以为您提供其他灵活性和快捷方式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接