Mooc.fi Java1作业求助:读取食谱文件出现重复输出问题
问题:读取食谱文件时所有输出重复
文本文件内容
Pancake dough 60 milk egg flour sugar salt butter Meatballs 20 ground meat egg breadcrumbs Tofu rolls 30 tofu rice water carrot cucumber avocado wasabi
当前输出
Pancake dough, cooking time: 60 Pancake dough, cooking time: 60 Pancake dough, cooking time: 60
期望输出
Pancake dough, cooking time: 60 Meatballs, cooking time: 20 Tofu rolls, cooking time: 30
当前代码
UserInterface类
public UserInterface(){ } public void start(){ ArrayList<Recipe> book = new ArrayList<>(); String row=""; try (Scanner scanner = new Scanner(Paths.get("recipes.txt"))){ ArrayList<String> item = new ArrayList<>(); while (scanner.hasNextLine()){ while (scanner.hasNextLine()) { row = scanner.nextLine(); if (row.equals("")) { break; }else{ item.add(row); } } book.add(new Recipe(item)); } } catch (Exception e) { } for (int i = 0; i < book.size(); i++) { System.out.println(book.get(i).list()); } } }
Recipe类
import java.util.ArrayList; public class Recipe { private String name; private int cookingTime; private ArrayList<String> recipe; public Recipe(ArrayList<String> r){ this.recipe = r; } public String list(){ return(this.recipeName()+", cooking time: "+this.cookingTime()); } public String recipeName(){ return this.recipe.get(0); } public int cookingTime(){ return Integer.valueOf(this.recipe.get(1)); } }
错误原因
核心问题是所有Recipe对象共享同一个item列表:
item列表仅在try块初始化一次,后续每次读取新食谱时,都会把内容添加到同一个列表中- 每个
Recipe对象保存的都是这个列表的引用,而非独立的副本 - 最终所有
Recipe调用recipeName()时,都会读取同一个列表的第0个元素(即第一个食谱的名称)
此外,代码未处理最后一个食谱后无空行的情况,可能导致最后一个食谱无法被正确添加。
解决方案
1. 每次处理新食谱时创建新的列表
将item列表的初始化移到外层while循环内,确保每个食谱对应独立的列表:
public void start(){ ArrayList<Recipe> book = new ArrayList<>(); String row=""; try (Scanner scanner = new Scanner(Paths.get("recipes.txt"))){ while (scanner.hasNextLine()){ // 每次循环创建新列表,避免共享引用 ArrayList<String> item = new ArrayList<>(); while (scanner.hasNextLine()) { row = scanner.nextLine(); if (row.equals("")) { break; } else { item.add(row); } } // 避免添加空列表(比如文件末尾的空行) if (!item.isEmpty()) { book.add(new Recipe(item)); } } } catch (Exception e) { e.printStackTrace(); // 打印异常便于调试 } for (Recipe recipe : book) { System.out.println(recipe.list()); } }
2. 优化Recipe类,保存独立数据
修改Recipe类,在构造方法中直接提取并保存名称、烹饪时间和食材,不再依赖传入的列表,避免原列表修改影响Recipe数据:
import java.util.ArrayList; public class Recipe { private String name; private int cookingTime; private ArrayList<String> ingredients; public Recipe(ArrayList<String> recipeData) { // 校验数据有效性 if (recipeData.size() >= 2) { this.name = recipeData.get(0).trim(); // 去除可能的换行空格 this.cookingTime = Integer.parseInt(recipeData.get(1).trim()); // 提取食材部分(从第2个元素开始) this.ingredients = new ArrayList<>(recipeData.subList(2, recipeData.size())); } else { this.name = "Invalid Recipe"; this.cookingTime = 0; this.ingredients = new ArrayList<>(); } } public String list() { return name + ", cooking time: " + cookingTime; } // 如需获取食材,可添加getter方法 public ArrayList<String> getIngredients() { return new ArrayList<>(ingredients); // 返回副本,避免外部修改 } }
内容的提问来源于stack exchange,提问作者Ashton Seloka
相关产品推荐
相关产品推荐

