Alex Jones
Alex Jones

Reputation: 236

Java: Multiple constructors forcing code reuse?

I have a class where one of its members is ArrayList<ArrayList<Double>> elements, and so I have a constructor that takes in that same type and all is good.

public elementArray(ArrayList<ArrayList<Double>> elements)
{
    this.elements =  elements;
    // a bunch of other stuff happens
}

However, I also need to be able to construct with an input of type Double[][], so I first convert it to the 2D list type, and then call the original constructor...

public elementArray(Double[][] array)
{
    // convert Double[][] array to ArrayList<ArrayList<Double>> elements
    this(elements);
}

Only, I can't call another constructor except as the first thing that happens in my constructor! Am I doomed to copy-paste here, or is there a clever way to do what I want?

Upvotes: 1

Views: 244

Answers (4)

Ilya
Ilya

Reputation: 728

But it is better to use the List instead of ArrayList.

    public elementArray(Double[][] array) {
        this(convert(elements));
    }

    static ArrayList<ArrayList<Double>> convert(Double[][] elements) {
        return IntStream.range(0, elements.length)
                .mapToObj(i -> IntStream.range(0, elements[i].length)
                        .mapToObj(j -> elements[i][j])
                        .collect(ArrayList::new, List::add, (u, v) -> u.addAll(v)))
                .collect(ArrayList::new,
                        (u, v) -> v.add(u),
                        (u, v) -> u.addAll(v));
    }

Upvotes: -1

Ryan Leach
Ryan Leach

Reputation: 4470

A common pattern to use would be to use a Builder instead.

https://iluwatar.github.io/java-design-patterns/patterns/builder/

Or a static factory method.

https://iluwatar.github.io/java-design-patterns/patterns/factory-method/

e.g. Using a static factory method, you would have only a single (possibly private) constructor, that accepts the rawest version of what your class needs.

public class elementArray{
    public elementArray(ArrayList<ArrayList<Double>> elements)
    {
        this.elements =  elements;
        // a bunch of other stuff happens
    }
    public static elementArray create(Double[][] array)
    {
        // convert Double[][] array to ArrayList<ArrayList<Double>> elements
        return new elementArray(elements);
    }
    public static elementArray create(ArrayList<ArrayList<Double>> elements)
    {
        return new elementArray(elements);
    }
}

and then, instead of invoking the constructor, you would call the static methods.

elementArray.create(new double[][]{{1.0d},{2.0d}});

This has been used fairly commonly in recent Java, in Guava and the Java standard library.

see Arrays.asList https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html#asList-T...-

Upvotes: 3

ernest_k
ernest_k

Reputation: 45309

You can't have code before the call to this(), you also can't call other instance methods.

You can extract that conversion into a separate static method:

private static ArrayList<ArrayList<Double>> arrayToList(Double[][] d) {
    //convert and return list
}

And reuse this method in your second constructor:

public elementArray(Double[][] array) {
    this(arrayToList(array));
}

Upvotes: 3

OhleC
OhleC

Reputation: 2890

One solution would be to extract the conversion into a static method:

public elementArray(Double[][] array) {
    this(convert(elements));
}

private static ArrayList<ArrayList<Double>> convert(Double[][] array) {
    // convert Double[][] array to ArrayList<ArrayList<Double>> elements
}

Upvotes: 3

Related Questions