Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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
}
like image 236
Naetmul Avatar asked Feb 21 '26 21:02

Naetmul


2 Answers

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. :-)

like image 53
jason Avatar answered Feb 24 '26 11:02

jason


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

like image 44
Jeffrey Avatar answered Feb 24 '26 10:02

Jeffrey



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!