Home > database >  Instantiate and initialize "multi-level" maps in Java
Instantiate and initialize "multi-level" maps in Java

Time:05-30

I'm trying to solve This problem in BeeCrowd without using a ton of if/elses.

BeeCrowd problem

It consists of reading 3 inputs from use, ex:

vertebrado
ave
carnivoro

and outputting the correspondent word of those inputs.

aguia

I know more python than java, this would be my solution in python (which works):

dict = {
  "vertebrado": {
    "ave": {
      "carnivoro": "aguia",
      "onivoro": "pomba"
    },
    "mamifero": {
      "onivoro": "homem",
      "herbivoro": "vaca"
    }
  },
  "invertebrado": {
    "inseto": {
      "hematofago": "pulga",
      "herbivoro": "lagarta"
    },
    "anelideo": {
      "hematofago": "sanguessuga",
      "onivoro": "minhoca"
    }
  }
}

word1 = input()
word2 = input()
word3 = input()

word = dict[word1][word2][word3]

print(word)

However I'm struggling to code a good solution in Java. This is my current Java solution (which also works):

import java.util.Scanner;
import java.util.HashMap;

public class Main {
    public static void main (String[]args) {
        Scanner scanner = new Scanner(System.in);
        String word1 = new String(scanner.nextLine());
        String word2 = new String(scanner.nextLine());
        String word3 = new String(scanner.nextLine());
        
        HashMap<String, HashMap<String, HashMap<String, String>>> dict = new HashMap();
        dict.put("vertebrado",  new HashMap<String, HashMap<String, String>>());
        dict.put("invertebrado", new HashMap<String, HashMap<String, String>>());
        
        dict.get("vertebrado").put("ave", new HashMap<String, String>());
        dict.get("vertebrado").put("mamifero", new HashMap<String, String>());
        
        dict.get("invertebrado").put("inseto", new HashMap<String, String>());
        dict.get("invertebrado").put("anelideo", new HashMap<String, String>());
        
        dict.get("vertebrado").get("ave").put("carnivoro", "aguia");
        dict.get("vertebrado").get("ave").put("onivoro", "pomba");
        dict.get("vertebrado").get("mamifero").put("onivoro", "homem");
        dict.get("vertebrado").get("mamifero").put("herbivoro", "vaca");
        
        dict.get("invertebrado").get("inseto").put("hematofago", "pulga");
        dict.get("invertebrado").get("inseto").put("herbivoro", "lagarta");
        dict.get("invertebrado").get("anelideo").put("hematofago", "sanguessuga");
        dict.get("invertebrado").get("anelideo").put("onivoro", "minhoca");
        
        
        String word = dict.get(word1).get(word2).get(word3);
        
        System.out.println(word);
    }
}

The obvious issue with that solution is that it's unpractical to populate the dict that way. The code is already big. If dict had a lot values, with a lot of "depth", it will become a hell to maintain.

Is there a way to reduce it? IE, declaring and initializing dict in a couple of lines?

CodePudding user response:

Use Map.of() as MC Emperor suggested:

Map<String, Map<String, Map<String, String>>> dict = Map.of(
    "vertebrado",
        Map.of(
            "ave",
                Map.of(
                    "carnivoro", "aguia",
                    "onivoro", "pomba"
                ),
            "mamifero",
                Map.of("onivoro","homem",
                        "herbivoro","vaca"
                )
        ),
    "invertebrado",
        Map.of(
            "inseto",
                Map.of(
                    "hematofago", "pulga",
                    "herbivoro", "lagarta"
                ),
            "anelideo",
                Map.of(
                    "hematofago","sanguessuga",
                    "onivoro","minhoca"
                )
        )
);

Compared to using a json file this also gives you type checking as you go, although to be really type safe you would want to introduce classes named Phylum, Class and Order to wrap your Strings, instead of leaving values "Stringly typed".

  •  Tags:  
  • java
  • Related