使 Java HashMap 对象内置于 processFile 方法中的代码可从 main 方法访问

Code to make Java HashMap Object built in processFile method accessible from main method

所以我在 Java 中编写了以下程序,它将文本文件的内容读取到 HashMap 并在一年内从用户到 return 哪支球队赢得了那一年的世界大赛以及该队赢得世界大赛的次数。我已经成功构建了 HashMap 但我正在努力解决如何在程序的主要驱动程序方法中使 HashMap 可访问(我明白为什么它不可访问,我正在寻找如何访问它)。现在,main 方法中实例化的 HashMap 是空的。我已经坚持了一段时间,似乎无法找到一种方法来做到这一点。任何见解将不胜感激!

import java.io.*; // contains all classes used in file processing
import java.io.File; // allows program to gather file information
import java.io.FileNotFoundException;

import java.util.*;
import java.util.Scanner; // allows program to get user input

public class Program3 {

    public void processFile(String filename)
    {
        // pass filename as arg to File class
        File worldSeries = new File("Program3.txt");

        // Create a Scanner object
        Scanner scan;

        // Create String line variable to read each line
        String line = "";

        try {
            // HashMap which tracks each year's World Series Winner
            HashMap<Integer,String> yearWinner = new HashMap<Integer,String>();
            // HashMap which tracks the number of times each team wins the World Series
            HashMap<String,Integer> numWins = new HashMap<String,Integer>();

            // Set startYear
            int startYear = 1903;

            // Pass filename to Scanner object
            scan = new Scanner(worldSeries);

            // Check for another line in input to scan
            while(scan.hasNextLine()){
                // Skip years during which the WorldSeries was not played
                if(startYear == 1904 || startYear == 1994) {
                    startYear++;
                }
                line = scan.nextLine(); // reads nextLine of String data type
                yearWinner.put(startYear, line); //  inserts a mapping into a HashMap
                if(numWins.containsKey(line)) { // checks if a key is mapped into the HashMap or not
                    numWins.put(line, numWins.get(line)+1); // if key exists, increment numWins value
                }else {
                    numWins.put(line,1); // if key does not exist, set numWins to 1
                }
                startYear++; // increment year
            }
            //testing for some case
            System.out.println(yearWinner.get(1905));
            System.out.println(numWins.get("New York Yankees"));
        } catch (FileNotFoundException e) {
            System.out.println("File not found");
        }
    }
    /*
    collectInput - method to collect user input for the year.
     */
    public int collectInput() {
        Scanner in = new Scanner(System.in); // Scanner object to read user input.

        int year; // declare year
        System.out.print("Please enter a year between 1903 & 2020: ");
        year = in.nextInt(); // collect the user input

        // check the year is either 0(sentinel value) or within range 1903 and 2020.
        while (year != 0 && (year < 1903 || year > 2020)) {
            // otherwise collect a valid year.
            System.out.print("Year is invalid! Please enter a year between 1903 & 2020: ");
            year = in.nextInt();
        }

        return year; // return the year.
    }
    /*
    displayOutput - method gets the user input and displays the output.
    @param winners - class instance
    @param yearWinner - map which stores year and team
    @param winsMap - map which stores team and number of wins
     */
    public void displayOutput(Program3 winners, HashMap<Integer, String> yearWinner, HashMap<String, Integer> numWins) {

        // loop the input until sentinel value is entered
        while (true) {

            // call the method to collect input from user
            int year = collectInput();

            // validate for sentinel value
            if (year == 0) {
                System.out.println("Thank you, goodbye!");
                return; // end program
            }

            // get the winning team for the given year.
            String winningTeam = winners.getWinningTeamForYear(year, yearWinner);

            // if there is winning team for the given year..
            if (winningTeam != null) {
                // get the number of wins of that team between 1903 and 2020.
                int numOfWins = winners.getNumberOfWins(winningTeam, numWins);
                // display the winning team and number of wins.
                System.out.println("The winning for the Year " + year + " is: " + winningTeam);
                System.out.println("Number of Wins secured by team: " + winningTeam + " is " + numOfWins);
            }
        }
    }
    // pass the year and get the winning team
    public String getWinningTeamForYear(int year, HashMap<Integer, String> yearWinner) {
        // if there is an entry for the given year.. to validate excluded years
        if (yearWinner.containsKey(year)) { // if yearWinner containsKey
            return yearWinner.get(year); // return the winning team
        }
        else {
            // display the message and return null.
            System.out.println("World Series not held in " + year);
            return null;
        }
    }

    // pass the team name in the hashmap and get the number of wins
    public int getNumberOfWins(String winningTeam, HashMap<String, Integer> numWins) {
        return numWins.get(winningTeam);
    }

    public static void main(String[] args) {

        HashMap<Integer, String> yearWinner = new HashMap<>(); // hashmap to store year and winners.
        HashMap<String, Integer> numWins = new HashMap<>(); // hashmap to store winners and number of wins.

        String fileName = "Program3.txt"; // file name where the data is stored.
        // You can also use full path of file Ex. E:\InputFiles\Program3.txt (\ delimiter slash indicating \)

        Program3 winners = new Program3();
        winners.processFile("Program3.txt");
        System.out.println(yearWinner);
        winners.displayOutput(winners, yearWinner, numWins); // non static method to collect user input and display output.

    }
}

Program3.txt 正在构建 HashMap

Boston Americans
New York Giants
Chicago White Sox
Chicago Cubs
Chicago Cubs
Pittsburgh Pirates
Philadelphia Athletics
Philadelphia Athletics
Boston Red Sox
Philadelphia Athletics
Boston Braves
Boston Red Sox
Boston Red Sox
Chicago White Sox
Boston Red Sox
Cincinnati Reds
Cleveland Indians
New York Giants
New York Giants
New York Yankees
Washington Senators
Pittsburgh Pirates
St. Louis Cardinals
New York Yankees
New York Yankees
Philadelphia Athletics
Philadelphia Athletics
St. Louis Cardinals
New York Yankees
New York Giants
St. Louis Cardinals
Detroit Tigers
New York Yankees
New York Yankees
New York Yankees
New York Yankees
Cincinnati Reds
New York Yankees
St. Louis Cardinals
New York Yankees
St. Louis Cardinals
Detroit Tigers
St. Louis Cardinals
New York Yankees
Cleveland Indians
New York Yankees
New York Yankees
New York Yankees
New York Yankees
New York Yankees
New York Giants
Brooklyn Dodgers
New York Yankees
Milwaukee Braves
New York Yankees
Los Angeles Dodgers
Pittsburgh Pirates
New York Yankees
New York Yankees
Los Angeles Dodgers
St. Louis Cardinals
Los Angeles Dodgers
Baltimore Orioles
St. Louis Cardinals
Detroit Tigers
New York Mets
Baltimore Orioles
Pittsburgh Pirates
Oakland Athletics
Oakland Athletics
Oakland Athletics
Cincinnati Reds
Cincinnati Reds
New York Yankees
New York Yankees
Pittsburgh Pirates
Philadelphia Phillies
Los Angeles Dodgers
St. Louis Cardinals
Baltimore Orioles
Detroit Tigers
Kansas City Royals
New York Mets
Minnesota Twins
Los Angeles Dodgers
Oakland Athletics
Cincinnati Reds
Minnesota Twins
Toronto Blue Jays
Toronto Blue Jays
Atlanta Braves
New York Yankees
Florida Marlins
New York Yankees
New York Yankees
New York Yankees
Arizona Diamondbacks
Anaheim Angels
Florida Marlins
Boston Red Sox
Chicago White Sox
St. Louis Cardinals
Boston Red Sox
Philadelphia Phillies
New York Yankees
San Francisco Giants
St. Louis Cardinals
San Francisco Giants
Boston Red Sox
San Francisco Giants
Kansas City Royals
Chicago Cubs
Houston Astros
Boston Red Sox
Washington Nationals
Los Angeles Dodgers

将两个地图作为参数添加到 processFile() 方法。

传递为空的集合类型的参数,并期望由方法填充,称为结果收集器

通过使用参数而不是 return 值,您可以拥有多个。

public void processFile(String filename, HashMap<Integer,String> yearWinner,
                        HashMap<String,Integer> numWins)
{
    ... code unchanged ...

    try {
        // delete the lines that declared yearWinner and numWins

        // Set startYear
        int startYear = 1903;

        ... code unchanged ...
public static void main(String[] args) {

    ... code unchanged ...

    winners.processFile("Program3.txt", yearWinner, numWins);

    ... code unchanged ...
}

正确而聪明。但是传递这样的结果收集器参数有一个缺点。它们被用来与调用方法通信的事实并不明显。

Java 16 and later, we can make more obvious the results by returning a record 中包含两个生成的地图。

记录

records 功能让我们可以简要地声明一个 class,其主要目的是透明和不可变的数据通信。只需在括号内声明成员字段的类型和名称。编译器隐式创建构造函数 getters、equals & hashCodetoString.

请注意,您可以在单独的 .java 文件中声明您的 record,嵌套在 class 中,甚至可以在本地方法中声明。

record Results ( Map<Integer,String> yearWinner, Map<String,Integer> numWins ) 
{
}

请注意,我们可以承诺 return 更通用的 Map interface rather than specific concrete HashMap implementation. This polymorphic encapsulation 让我们可以自由地稍后更改我们对 Map 实现的选择。

getter 方法的名称与它们导出的 属性(成员字段)相同。 Java使用 get…/is… 的 Beans 风格命名 使用。

System.out.println( myResults.yearWinner() ) ;

将您的处理方法更改为return此记录类型的对象。

public Results processFile( String filename )  // Returns a `Results` object. 
{
    …
    HashMap<Integer,String> yearWinner = … ;
    HashMap<String,Integer> numWins = … ;
    return new Results( yearWinner , numWins ) ;
}

在 Java 10 及更高版本中优于 return unmodifiable maps. Call Map.copyOf。根据定义,record 意味着不可变地传递数据。因此,尽可能使您的记录尽可能不可变。

public Results processFile( String filename )
{
    …
    HashMap<Integer,String> yearWinner = … ;
    HashMap<String,Integer> numWins = … ;
    return new Results( Map.copyOf( yearWinner ) , Map.copyOf( numWins ) ) ;  // Return immutable maps, copied from our mutable maps.
}

当然,在旧版本的 Java 中,您可以声明一个 class 来做同样的事情(return 结果调用方法)。但是声明一个传统的 class 涉及太多的样板文件,以至于程序员通常不会费心。新的记录功能是专门为解决这种仅传递不可变数据的需求而开发的。一个很好的额外好处是样板文件的大量减少。