Ojonugwa Jude Ochalifu
Ojonugwa Jude Ochalifu

Reputation: 27255

Using Map arguments in constructor

I have a class, Student with this constructor.

 public Student(String name, int age, Map<String, Integer> grades) {
    this.setName(name);
    this.setAge(age);
    this.setGrades(grades);
 }

when creating a Student object, how do I pass the Map argument in the constructor?

What am looking for is something similar to this:

List<Student> roster = new ArrayList<>();
roster.add(new Student("Ann Droid", 145, Arrays.asList(96, 78)));

If I had this constructor:

public Student(String name, int age, List<Integer> grades) {
    this.setName(name);
    this.setAge(age);
    this.setGrades(grades);
 }

Upvotes: 3

Views: 8256

Answers (5)

SanyaLuc
SanyaLuc

Reputation: 116

You can try this option using an anonymous constructor

List<Student> roster = new ArrayList<Student>();
roster.add(new Student("Ann Droid", 145, new HashMap<String, Integer>(){{
                                         put("English", 78);
                                         put("Math", 96);
                                         }}));

Or you can use Guava ImmutableMap of(), but this API is limited to five pairs.

List<Student> roster = new ArrayList<>();
roster.add(new Student("Ann Droid", 145, ImmutableMap.of("English", 78, "Math", 96);

Upvotes: 1

Alexis C.
Alexis C.

Reputation: 93872

There's no way to create a Map in a one-liner with Java <= 7 and with the standard JDK. (Well you could technically with a double brace initializer, but it's considered as a bad practice).

In Java 8, you could use the Stream API to achieve this:

import java.util.AbstractMap.SimpleEntry;
import java.util.stream.Stream;
import static java.util.stream.Collectors.toMap;

...
new Student("Name", 
            10,
            Stream.of(new SimpleEntry<>("MyString", 1), 
                      new SimpleEntry<>("AnotherString", 2))
                  .collect(toMap(SimpleEntry::getKey, SimpleEntry::getValue)));

Now you have to see it if improves readability or not for your use case ;)

Or you could modify your design so that the Map<String, Integer> is represented with a List<Grade> instead, with each Grade having a String representing the course and an Integer for the Student's mark for this course.

And then you could use Arrays.asList:

new Student("John", 
            18, 
            Arrays.asList(new Grade("French", 1), new Grade("Math", 5)));

Of course you have to ensure uniqueness of the grades.

Upvotes: 3

Wouter Lievens
Wouter Lievens

Reputation: 4029

You can make a utility function yourself. It's not very type-safe, though, because you need to circumvent typing to (ab)use the varags parameter.

public class MapExample
{
    public static <K, V> Map<K, V> map(Object... objects)
    {
        Map<K, V> map = new HashMap<>();
        for (int n = 0; n < objects.length; n += 2)
        {
            map.put((K)objects[n], (V)objects[n + 1]);
        }
        return map;
    }

    public static void main(String[] args)
    {
        System.out.println(map("AAA", 123, "BBB", 456));
    }
}

Upvotes: 3

Tim Biegeleisen
Tim Biegeleisen

Reputation: 522084

Vanilla flavor plain Java doesn't have anything for Maps as Arrays.asList(). So you will have to initialize the Map over several line of code like this:

Map<String, Integer> grades = new HashMap<String, Integer>();
grades.put("English", 90);
roster.add(new Student("Ann Droid", 145, grades);

However, with Google's Guava you can do this:

Map<String, Integer> grades = ImmutableMap.of("English", 90);

Upvotes: 5

Eran
Eran

Reputation: 393946

It can't be done with a one liner.

Map<String,Integer> grades = new HashMap<>();
grades.put("Math", 100);
roster.add(new Student("Ann Droid", 145, grades));

Upvotes: 3

Related Questions