简体   繁体   中英

How do I tell if a key is contained in a non-named Hashmap within a Hashmap? Java, JavaFX

I am currently working on an assignment for school where I am supposed to create a hashmap within a hashmap like this:

Map<String, Map<String, Integer>> girlsByYear = new HashMap<>();
Map<String, Map<String, Integer>> boysByYear = new HashMap<>();

According to the professor, there are not supposed to be any other maps needed to complete the assignment. The maps add elements to them by accessing files within a package that contain names, gender, and rank of baby names by year. When the program is compiled and finished, a JavaFX chart is created that requests a girl or boy's name to be entered. When entered, the chart shows by year the rank of how popular the name was.

Currently, I have figured most of it out, but I cannot understand how to access the Hashmap within the first Hashmap without a key for the first hashmap. By that, I mean that I am supposed to have a check performed by the textbox for the JavaFX class that reviews whether the name is in the Hashmap or not. Here is my code:

public class NameHelper {

// Declare the hash maps.
Map<String, Map<String, Integer>> girlsByYear = new HashMap<>();

Map<String, Map<String, Integer>> boysByYear = new HashMap<>();

// Declare addition variables.
String firstWord = "";
String secondWord = "";
String thirdWord = "";
Integer rank;

String fileName;

// This method will load the files from the data package, review the files,
// and add each item respectively to either map.
public void load() throws FileNotFoundException {
    File dir = new File("src/data");
    File [] files = dir.listFiles();

    // for each file in the directory...
    for (File f : files)
    {

        // Get the file name and split the year from it to add to each name.
        String newFileName = f.getName();
        fileName = newFileName.replaceAll("[yobtxt.]","");

        Scanner scanner = new Scanner(f);

        // While the files are not empty.
        while(scanner.hasNextLine()) {

            // If the second column split by a delimiter is M then add the information
            // to the boys.  Else girls.

            String input = scanner.nextLine();  
            // Set the input to string values to enter into each hash map.
            String initial = input.split(",")[1];
            firstWord = fileName;
            secondWord = (input.split(",")[0]).toLowerCase();
            thirdWord = input.split(",")[2];
            rank = Integer.parseInt(thirdWord);

            // Use a switch statements since if statements aren't working.
            switch(initial) {
            case "M":
                boysByYear.put(firstWord, new HashMap<String, Integer>());
                boysByYear.get(firstWord).put(secondWord, rank);


                break;
            case "F":
                girlsByYear.put(firstWord, new HashMap<String, Integer>());
                girlsByYear.get(firstWord).put(secondWord, rank);

                break;
                default:
                    System.out.println("This is an issue");
                    break;
            }

        }

        // Close the scanner.
        scanner.close();

    }

}


// This method will return a sorted set of years by getting the keyset from the hashmaps.
public Set<String> getYears() {

    // Create the set.
    Set<String> set = new HashSet<>();

    // Add all the years of the listed by file name.
    for(String key : girlsByYear.keySet()) {
        set.add(key);
    }

    // Convert the set to a sorted set.
    TreeSet<String> treeSet = new TreeSet<>(set);
    return treeSet;
}

// This method will return true if the supplied name is found in the data structure.
// Use the gender input to determine which map to search by using "containsKey".
public boolean isNamePresent(String name, String gender) {


    if(gender == "M") {


        //Check if the name is within the map's map.
        if(boysByYear.get(name).containsKey(name)) {
            return true;
        }

    }
    else if(gender == "F") {
        if(girlsByYear.containsKey(name.toLowerCase())) {
            return true;
        }
    }
    return false;
}

The section that I need help with is the isNamePresent method. I need to check if the name is in the key of the second hashmap which is set up in this format (String year, HashMap(String name, Integer rank))

Any help or guidance would be greatly appreciated!

Additional notes: The JavaFx section for the chart was provided by the professor.

One thing you need to fix first is comparing the strings using == . This doesn't work unless both the string passed as gender parameter is a string literal. You need to use equals instead, see How do I compare strings in Java? ( switch does this automatically).

Furthermore you should avoid duplicating code by retrieving the map to a local variable:

Map<String, Map<String, Integer>> map;
switch (gender) {
    case "M":
        map = boysByYear;
        break;
    case "F":
        map = girlsByYear;
        break;
    default:
        return false; // alternatively throw new IllegalArgumentException();
}

To find out, if at least one of the maps contains name as a key, go through all the values and check the maps:

final String nameLower = name.toLowerCase();
return map.values().stream().anyMatch(m -> m.containsKey(nameLower));

BTW: You need to fix the way you read the data. Otherwise you'll get at most one name per year&gender, since you replace the Map . Furthermore I recommend storing the result of split instead of invoking it 3 times. Also don't use fields as variables only needed in a loop and choose more discriptive variable names:

Map<String, Integer> boys = new HashMap<>();
Map<String, Integer> girls = new HashMap<>();

boysByYear.put(fileName, boys);
girlsByYear.put(fileName, girls);

while(scanner.hasNextLine()) {

    // If the second column split by a delimiter is M then add the information
    // to the boys.  Else girls.

    String input = scanner.nextLine();
    String[] parts = input.split(",");

    // Set the input to string values to enter into each hash map.
    String gender = parts[1];

    String name = parts[0].toLowerCase();
    int rank = Integer.parseInt(parts[2]);

    switch(gender) {
        case "M":
            boys.put(name, rank);
            break;
        case "F":
            girls.put(name, rank);
            break;
        default:
            System.out.println("This is an issue");
            break;
    }

}

To access the inner hash map without knowing the key of the outer map, you can iterate over each entry of the outer map.

for(Map.Entry<String, Integer> mapEntry: boysByYear.entrySet()){
// Get the innerMap and check if the name exists
    Map<String, Integer> innerMap = mapEntry.getValue();
        if(innerMap.containsKey(name)){
            return true;
        }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM