1. 项目背景与核心需求
这个案例的灵感来源于真实的外卖平台后台管理系统。作为一名Java开发者,我经常需要处理各种集合数据,而ArrayList作为最常用的集合类之一,在外卖系统的订单管理、菜品管理等场景中有着广泛应用。
通过模拟外卖系统,我们可以深入理解:
- 如何使用ArrayList存储和操作业务对象
- 如何设计合理的类结构来模拟现实业务
- 如何通过控制台交互实现基本功能
提示:这个案例特别适合Java初学者练习面向对象编程和集合框架的使用,建议在理解ArrayList基本用法后再进行实践。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心类设计解析
2.1 Food类实现
Food类是外卖系统的基石,代表一个具体的菜品项。我通常会这样设计:
java复制public class Food {
private String id; // 菜品编号
private String name; // 菜品名称
private double price; // 菜品价格
private String desc; // 菜品描述
private int sales; // 月销量
// 构造方法
public Food(String id, String name, double price, String desc) {
this.id = id;
this.name = name;
this.price = price;
this.desc = desc;
this.sales = 0; // 初始销量为0
}
// getter和setter方法
// toString()方法
}
在实际开发中,我建议:
- 使用String类型存储ID而不是int,方便扩展
- 价格使用double类型但要处理精度问题
- 添加销量字段便于后续数据分析
2.2 FoodManager类设计
FoodManager是系统的核心管理类,负责菜品的CRUD操作:
java复制import java.util.ArrayList;
import java.util.Scanner;
public class FoodManager {
private ArrayList<Food> foodList = new ArrayList<>();
private Scanner sc = new Scanner(System.in);
// 添加菜品
public void addFood() {
System.out.println("请输入菜品ID:");
String id = sc.next();
// 检查ID是否已存在
for(Food food : foodList) {
if(food.getId().equals(id)) {
System.out.println("该ID已存在!");
return;
}
}
System.out.println("请输入菜品名称:");
String name = sc.next();
System.out.println("请输入菜品价格:");
double price = sc.nextDouble();
System.out.println("请输入菜品描述:");
String desc = sc.next();
Food food = new Food(id, name, price, desc);
foodList.add(food);
System.out.println("添加成功!");
}
// 其他方法...
}
注意:在实际项目中,我会使用更健壮的输入验证,这里简化了处理。
3. 完整功能实现
3.1 主菜单设计
一个完整的外卖系统通常包含以下功能:
java复制public void start() {
while(true) {
System.out.println("-----外卖管理系统-----");
System.out.println("1.添加菜品");
System.out.println("2.删除菜品");
System.out.println("3.修改菜品");
System.out.println("4.查询所有菜品");
System.out.println("5.根据ID查询菜品");
System.out.println("6.退出系统");
System.out.println("请输入您的选择:");
String choice = sc.next();
switch(choice) {
case "1":
addFood();
break;
case "2":
deleteFood();
break;
case "3":
updateFood();
break;
case "4":
showAllFoods();
break;
case "5":
findFoodById();
break;
case "6":
System.out.println("感谢使用,再见!");
System.exit(0);
default:
System.out.println("输入有误,请重新输入!");
}
}
}
3.2 删除功能实现
删除菜品时常见的坑是并发修改异常:
java复制public void deleteFood() {
System.out.println("请输入要删除的菜品ID:");
String id = sc.next();
// 传统for循环会有并发修改问题
// 改为使用迭代器或增强for循环+标志位
boolean found = false;
for(Food food : foodList) {
if(food.getId().equals(id)) {
foodList.remove(food);
found = true;
break;
}
}
if(found) {
System.out.println("删除成功!");
} else {
System.out.println("未找到该ID对应的菜品!");
}
}
3.3 查询与展示功能
良好的展示格式能提升用户体验:
java复制public void showAllFoods() {
if(foodList.isEmpty()) {
System.out.println("暂无菜品信息!");
return;
}
System.out.println("ID\t名称\t价格\t描述\t销量");
System.out.println("----------------------------------");
for(Food food : foodList) {
System.out.printf("%s\t%s\t%.2f\t%s\t%d%n",
food.getId(),
food.getName(),
food.getPrice(),
food.getDesc(),
food.getSales());
}
}
4. 高级功能扩展
4.1 菜品排序功能
实际外卖系统通常需要多种排序方式:
java复制// 按价格排序
public void sortByPrice() {
foodList.sort(new Comparator<Food>() {
@Override
public int compare(Food f1, Food f2) {
return Double.compare(f1.getPrice(), f2.getPrice());
}
});
showAllFoods();
}
// 按销量排序
public void sortBySales() {
foodList.sort((f1, f2) -> f2.getSales() - f1.getSales());
showAllFoods();
}
4.2 数据持久化
ArrayList是内存中的集合,程序退出后数据会丢失。可以添加简单的文件存储:
java复制// 保存到文件
public void saveToFile() throws IOException {
try (ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("foods.dat"))) {
oos.writeObject(foodList);
}
}
// 从文件加载
@SuppressWarnings("unchecked")
public void loadFromFile() throws IOException, ClassNotFoundException {
File file = new File("foods.dat");
if(file.exists()) {
try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream(file))) {
foodList = (ArrayList<Food>) ois.readObject();
}
}
}
5. 实战中的经验与坑
5.1 并发修改异常处理
在遍历ArrayList时直接删除元素会抛出ConcurrentModificationException。解决方案:
- 使用迭代器的remove方法
- 使用普通for循环倒序遍历
- Java8+可以使用removeIf方法
java复制// 安全的删除方式示例
Iterator<Food> iterator = foodList.iterator();
while(iterator.hasNext()) {
Food food = iterator.next();
if(food.getId().equals(id)) {
iterator.remove();
}
}
5.2 性能优化建议
当数据量较大时,可以考虑:
- 使用HashMap辅助查询,建立ID到Food对象的映射
- 分页展示数据,避免一次性加载过多
- 对于频繁修改的操作,考虑使用LinkedList
java复制// 使用HashMap优化查询
private Map<String, Food> foodMap = new HashMap<>();
// 添加时同步更新
foodList.add(food);
foodMap.put(food.getId(), food);
5.3 输入验证的完善
基础版本忽略了输入验证,实际应该:
java复制public double getValidPrice() {
while(true) {
try {
double price = sc.nextDouble();
if(price > 0) {
return price;
}
System.out.println("价格必须大于0,请重新输入:");
} catch(InputMismatchException e) {
System.out.println("请输入有效的数字:");
sc.next(); // 清除错误的输入
}
}
}
6. 项目扩展思路
6.1 添加订单管理
完整的外卖系统还需要订单管理:
java复制public class Order {
private String orderId;
private List<Food> items;
private Date orderTime;
private double total;
// 其他字段和方法...
}
6.2 引入用户系统
添加用户类和登录验证:
java复制public class User {
private String username;
private String password;
private String role; // admin/customer
// ...
}
public boolean login(String username, String password) {
// 验证逻辑
}
6.3 图形界面开发
控制台程序可以升级为Swing或JavaFX界面:
java复制// JavaFX示例
TableView<Food> table = new TableView<>();
TableColumn<Food, String> idCol = new TableColumn<>("ID");
idCol.setCellValueFactory(new PropertyValueFactory<>("id"));
// 添加其他列...
table.getColumns().addAll(idCol, nameCol, priceCol);
这个ArrayList实现的外卖系统案例,虽然简单但涵盖了集合框架的核心应用场景。我在实际教学中发现,通过这样的项目练习,学生能更快掌握ArrayList的特性和面向对象的设计思想。建议在完成基础功能后,尝试自己添加更多业务逻辑,比如折扣计算、会员系统等,这对提升编程能力很有帮助。
