【问题标题】:Initialize an array with a class constructor and another array用类构造函数和另一个数组初始化一个数组
【发布时间】:2013-08-09 03:28:02
【问题描述】:

我有一个类型为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
}

【问题讨论】:

  • 您解释这两个数组如何相关的逻辑对我来说非常粗略。也许是我,但如果你没有得到好的答案,请考虑澄清一下。例如,这是什么意思:A.b = B.b * B.c;?为什么在 A 的构造函数主体中使用类型 B 而不是参数 b? A.c 会是什么? A.b 如何是一个数组项?最后也是最重要的是,请发布真实代码,而不是可能代码,这似乎是您在此处发布的内容。
  • 是的,请尝试发布真实代码。如果我们能够准确地看到您正在尝试做的事情,而不是看到您可能正在考虑的事情,我们或许能够提供更多帮助。

标签: java arrays constructor


【解决方案1】:

就语言的当前1状态2而言,您能做的最好的事情就是这样3 :

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:记住男孩和女孩,the next time you design a type system of your own from scratch, remember to add generics early, rather than adding them on later

3:刚刚一起破解了这个。随时帮助修复任何错误。 :-)

【讨论】:

  • my answer 中概述了这些功能;)
  • @Jeffrey:太棒了。 :-)
  • 恕我直言,这是矫枉过正,太多样板。我会使用自定义循环,它更轻、更干净、更可靠且对 IDE 友好。模式应该用于使设计更明显,而不是更少。
【解决方案2】:

还没有。在Java 8,由于Project Lamda,我们将可以使用更多functional programming功能,例如map functions

在 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()]);

这使用了lamda expression,以及其他几个new features1,2

虽然这可能不会“更短”,但Stream 提供了parallelization by default,因此如果您在上面的示例中将Stream.of(bs) 更改为Stream.of(bs).parallel(),它的性能会好多多核机器上的大型阵列。

/编辑
您也可以使用 method reference 代替 lambda 表达式:

map(A::new) 而不是map(b -&gt; new A(b))

【讨论】:

  • @fernacolo 在一定程度上确实如此,但它的可扩展性仍然低得多。
  • 同意可扩展性。然而,为了完成创建和同步任务,要么项目的数量应该很大(大约 10k 或更多),要么每个项目的创建都应该是计算密集型的。线程总是引入不确定性(假设 B 的创建使用缓存......)。
【解决方案3】:

从 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));
}

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-08
    相关资源
    最近更新 更多