1

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?

2
  • Why not just add a private method setElements(ArrayList<ArrayList<Double>> elements) and call it from both constructors? Commented Oct 23, 2018 at 8:56
  • 1
    Have a private static method that does the conversion, and then you can just this(convertArrayToList(elements)); Commented Oct 23, 2018 at 8:56

4 Answers 4

3

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
}
Sign up to request clarification or add additional context in comments.

Comments

3

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

Comments

3

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

Comments

-1

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

4 Comments

This is far far far too complex.
Really? If the author uses List, it will be simple.
What about that: Arrays.stream(array).map(d -> Arrays.stream(d).collect(Collectors.toCollection(ArrayList::new))).collect(Collectors.toCollection(ArrayList::new));
I already have a simple method for converting Double[][] to ArrayList<ArrayList<Double>>. Other than that, this answer says the same as the other ones.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.