Naetmul
Naetmul

Reputation: 15552

Initialize an array with a class constructor and another array

I have an array with Type B[]. I have a constructor A(B b).

I want to create an array with Type A[] using them.

I can use the for statement to do that, but I want to know whether there is a more convinient(shorter) way to do this. (Language syntax, static method, or whatever)

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
}

Upvotes: 3

Views: 990

Answers (3)

Jeffrey
Jeffrey

Reputation: 44808

Not yet. In Java 8, we will have access to more functional programming features thanks to Project Lamda, such as map functions.

In Java 8, the following would be valid:

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

This uses a lamda expression, and several other new features1,2.

While this may not be much "shorter," Stream provides parallelization by default, so if you changed Stream.of(bs) to Stream.of(bs).parallel() in the above example, it would perform much better with large arrays on a multi-core machine.

/edit
You could also use a method reference instead of the lambda expression:

map(A::new) instead of map(b -> new A(b))

Upvotes: 3

fernacolo
fernacolo

Reputation: 7439

As of Java 7, you already use the shortest possible loop:

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

However, if you use collections instead of arrays, you can use "for each":

for (B b: bs) {
    as.add(new A(b));
}

Collections will also give you other flexibilities and shortcuts.

Upvotes: 1

jason
jason

Reputation: 241641

As of the current1 state of the language2, about the best that you can do is something like this3:

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

Usage:

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

This assumes:

class Foo { }
class Bar { public Bar(Foo foo) { } }

1: There are features coming in 2014(?) that will make it easier.

2: Remember boys and girls, 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: Just hacked this together. Feel free to help fix any bugs. :-)

Upvotes: 4

Related Questions