代码之家  ›  专栏  ›  技术社区  ›  Erin

使Java HashMap对象内置processFile方法可从main方法访问

  •  0
  • Erin  · 技术社区  · 5 年前

    我用Java编写了以下程序,它将文本文件的内容读取到 HashMap 用户需要一年的时间才能返回当年赢得世界大赛的球队以及该球队赢得世界大赛的次数。我成功地构建了 哈希图 但我在努力想我该怎么做 哈希图 在程序的主驱动程序方法中可访问(我理解为什么它不可访问,我正在寻找如何访问它)。现在,实例化 哈希图 在main方法中为空。我已经在这个问题上纠结了一段时间,似乎找不到办法来解决这个问题。如有任何见解,将不胜感激!

    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 从中 哈希图 正在建造:

    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
    
    0 回复  |  直到 5 年前
        1
  •  2
  •   Andreas dfa    5 年前

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

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

    通过使用参数而不是返回值,可以有多个。

    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 ...
    }
    
        2
  •  1
  •   Basil Bourque    5 年前

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

    在里面 Java 16 稍后,我们可以通过返回 record 它保存两个生成的贴图。

    记录

    这个 records 该特性允许我们简单地声明一个类,其主要目的是透明和不可变地通信数据。只需在括号内声明成员字段的类型和名称。编译器隐式创建构造函数getters, equals & hashCode toString

    请注意,您可以申报 记录 在单独的 .java 文件,嵌套在类中,甚至本地嵌套在方法中。

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

    请注意,我们可以承诺返回更一般的 Map 界面而非特定混凝土 HashMap 实施这 polymorphic encapsulation 给了我们以后改变选择的自由 地图 实施

    getter方法的名称与其导出的属性(成员字段)相同。JavaBeans风格的命名 get… / is… 习惯于

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

    更改处理方法以返回此记录类型的对象。

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

    最好还是回去 unmodifiable maps 呼叫 Map.copyOf 在Java 10及更高版本中。A. 记录 根据定义,是指不可变地传输数据。因此,尽可能使您的记录保持不变。

    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中,您可以声明一个类来执行相同的操作(将结果返回给调用方法)。但声明一个常规类涉及到太多的样板文件,程序员通常不会费心。开发新的记录功能是为了满足这种只需传输不变数据的需求。一个很好的额外好处是大大减少了工作量。