Create list of custom object inline, without seperate model class - java

Viewed 1642

To keep code minimal, I want to be able to create a list of a custom object in java. Similar to what we do in C# or Swift, where we define the constructor or parameters of the list in that way we don't have to create a separate object and constructor for the list.

For example

    var menuList: [(category: String, name: String, ismulti: Bool)] = [
      (category: "Categ1", name: "name1", ismulti: true),
      (category: "Categ2", name: "name2",  ismulti: false),
      (category: "Categ3", name: "name3", type: ismulti: true),
    ]

Here var menuList: [(category: String, name: String, ismulti: Bool)] reduced the need for object and constructor. Is there something similar in java?

for same what I did in java.

public class Menu{
    String category;
    String name;
    boolean isMulti;

    public Menu(String category, String name, boolean isMulti) {
        this.category = category;
        this.name = name;
        this.isMulti = isMulti;
    }

    public List<Menu> menuList = new ArrayList<Menu>() {{
        add(new Menu("categ1","name1",true));
        add(new Menu("categ2","name2",true));
        add(new Menu("categ3","name3",true));

    }};
}
4 Answers

It's worth mentioning what this syntax is:

public List<Menu> menuList = new ArrayList<Menu>() {{
    add(new Menu("categ1","name1",true));
    add(new Menu("categ2","name2",true));
    add(new Menu("categ3","name3",true));

}}

This is called - "double brace initialization" and under the hood it anonymously extends ArrayList class, generally it should be used with caution, you could read more here

Back to the original question - depending on what you need, which version of java you are using and whether you can/want to use some external libraries, you have this options, note that Arrays.asList() and List.of() return a list that does not support all of the operations, like add() or remove() and in case of the latter, also set(). Also regarding constructor, as others already mentioned, you could use project Lombok to generate constructor for you.:

Java 9

List<Menu> collect = List.of(
new Menu("categ1","name1",true),
new Menu("categ2","name2",true),
new Menu("categ3","name3",true));

Java 8

List<Menu> collect = Stream.of(
new Menu("categ1","name1",true),
new Menu("categ2","name2",true),
new Menu("categ3","name3",true))
.collect(Collectors.toList());

Java before 8

List<Menu> collect = Arrays.asList(
            new Menu("categ1", "name1", true),
            new Menu("categ2", "name2", true),
            new Menu("categ3", "name3", true));

Using Guava

Guava is an external library, see it here.

List<Menu> collect = Lists.newArrayList(
    new Menu("categ1","name1",true),
    new Menu("categ2","name2",true),
    new Menu("categ3","name3",true));

Alternatively you could write your own class like @ernest_k did, which really gives you nice flexibility when working with different types.

Just to add a third workaround (as the other answers have pointed out, you can't do this in Java - there's no such syntax).

One thing you can do is create your own reusable Tuple class. You'll be forced to have a class per number of elements, but you can reuse it with various combinations of types.

static class Tuple3<T, U, V> {
    final T _1;
    final U _2;
    final V _3;

    private Tuple3(T t, U u, V v) {
        this._1 = t;
        this._2 = u;
        this._3 = v;
    }

    public static <T, U, V> Tuple3<T, U, V> of(T t, U u, V v) {
        return new Tuple3<>(t, u, v);
    }
}

Then (with the same tuple class, you can have different flavors of this):

//menuList is a List<Tuple3<String, String, Boolean>>
var menuList = List.of(
    Tuple3.of("Categ1", "name1", true), 
    Tuple3.of("Categ2", "name2", false),
    Tuple3.of("Categ3", "name3", true)
);

//registration is a List<Tuple3<String, LocalDate, Double>>
var registrationData = List.of(
    Tuple3.of("John", LocalDate.EPOCH, 1.1), 
    Tuple3.of("James", LocalDate.now(), 2.2),
    Tuple3.of("Ron", LocalDate.now(), 3.3)
);

I personally would make fields _1, _2, and _3 public, but this is a preference. You can create getters for them if you prefer (perhaps _1() but it can't get clean enough.


I'm assuming Java 11+, but you can easily make it compatible with older versions by just dropping var and List.of

You could use Lombok to generate the constructor for you. That does not really solve your problem, but at least you have shorter code.

And you could use the diamond operator for new ArrayList<>() or use Arrays.asList() to create a new List.

@AllArgsConstructor
public class Menu {
    String category;
    String name;
    boolean isMulti;

    public List<Menu> menuList = List.of( // if Java < 9, use Arrays.asList()
            new Menu("categ1", "name1", true),
            new Menu("categ2", "name2", true),
            new Menu("categ3", "name3", true)
    );
}

Java authors prefer such design for sake of simplicity. Yes, it looks verbose for most of the developers but the regularity of the syntax with the minimal use of syntactic sugar is more programming error free and less complex. Therefore better for maintainability IMHO.

To answer you how to reduce the bolerplate with the pure Java, you can't. Hoever, there are tools and ways to make the whole code look more compact and don't lose the track about what is going code in the code.

  1. Avoid the block initialized. A lot of developers get confused when they see it. Use Arrays.asList() or List.of() as of Java 9:

    public List<Menu> menuList = List.of(
        new Menu("categ1","name1",true),
        new Menu("categ2","name2",true),
        new Menu("categ3","name3",true)
    );
    
  2. Use Project Lombok commonly used to eliminate the common boilerplate such as constructors, getters etc. using the advantage of the annotation-processor and the annotations @AllArgsConstructor etc.

The whole code becomes both easy to read and easy to maintain:

@AllArgsConstructor
public class Menu {

    String category;
    String name;
    boolean isMulti;

    public List<Menu> menuList = List.of(
        new Menu("categ1","name1",true),
        new Menu("categ2","name2",true),
        new Menu("categ3","name3",true)
    );
}
Related