iT邦幫忙

2026 iThome 鐵人賽

DAY 10
0
自我挑戰組

Java 程式設計與實作:30 天打造個人記帳系統系列 第 18 篇

記帳系統實作:新增「刪除消費紀錄」功能

  • 分享至 

  • xImage
  •  

昨天完成了「分類支出統計」,現在除了可以知道總共花多少錢,也可以看到飲食、交通、購物和娛樂分別花了多少。

目前系統已經可以新增和分析資料,不過我發現還少了一個很實際的功能:

如果不小心記錯一筆帳,要怎麼刪掉?

所以 Day 18 要加入 刪除消費紀錄,並正式使用之前學過的:

ArrayList.remove()

今天想完成的功能

目前的選單是:

===== 個人記帳系統 =====

  1. 新增消費
  2. 查看紀錄
  3. 查看總支出
  4. 分類支出統計
  5. 離開

今天改成:

===== 個人記帳系統 =====

  1. 新增消費
  2. 查看紀錄
  3. 查看總支出
  4. 分類支出統計
  5. 刪除消費紀錄
  6. 離開

假設目前有:

  1. 早餐|60 元|飲食
  2. 捷運|30 元|交通
  3. 電影|300 元|娛樂

如果選擇:

請輸入要刪除的紀錄編號:2

希望程式可以顯示:

已刪除:捷運

之後再次查看紀錄:

  1. 早餐|60 元|飲食
  2. 電影|300 元|娛樂

ArrayList 的 remove()

之前 Day 9 學習 ArrayList 時有簡單提到:

remove()

它可以把 ArrayList 裡面的資料刪除。

例如:

ArrayList items = new ArrayList<>();
items.add("早餐");
items.add("捷運");
items.add("午餐");

現在資料的位置是:

Index 0 → 早餐
Index 1 → 捷運
Index 2 → 午餐

如果執行:

items.remove(1);

就會刪除:

捷運

剩下:

早餐
午餐

使用者看到的編號和 Index 不一樣

這裡有一個需要注意的地方。

我們顯示給使用者的是:

  1. 早餐
  2. 捷運
  3. 午餐

但是 ArrayList 真正的 Index 是:

早餐 → 0
捷運 → 1
午餐 → 2

所以如果使用者輸入:

2

代表要刪除「捷運」。

但是程式真正要使用:

expenses.remove(1);

因此需要:

int index = number - 1;

例如:

使用者輸入 2
↓
2 - 1
↓
Index = 1
↓
刪除捷運

這和之前學 Array 時「Index 從 0 開始」是同樣的概念。

建立 deleteExpense() Method

因為我們已經習慣把不同功能分成 Method,所以今天建立:

public static void deleteExpense()

基本版本:

public static void deleteExpense() {
System.out.print("請輸入要刪除的紀錄編號:");
int number = scanner.nextInt();
scanner.nextLine();
int index = number - 1;
expenses.remove(index);
System.out.println("刪除成功!");
}

不過這裡還有一個問題。

如果目前只有 3 筆資料,使用者卻輸入:

10

就會發生錯誤。

所以還需要檢查編號。

檢查輸入的紀錄編號

可以使用:

if (number >= 1 && number <= expenses.size())

意思是:

number >= 1

而且:

number <= 紀錄數量

才是有效的編號。

完整判斷:

if (number >= 1 && number <= expenses.size()) {
int index = number - 1;
expenses.remove(index);
System.out.println("刪除成功!");
} else {
System.out.println("沒有這筆紀錄!");
}

刪除前先取得資料

如果直接:

expenses.remove(index);

資料刪掉之後,我們就不方便顯示剛剛刪除了什麼。

所以可以先:

Expense deletedExpense = expenses.get(index);

再刪除:

expenses.remove(index);

最後:

System.out.println(
"已刪除:" + deletedExpense.getItem()
);

這樣使用者會知道自己剛剛刪掉哪一筆。

Day 18 完整程式

今天把刪除功能整合進目前的記帳系統:

import java.util.Scanner;
import java.util.ArrayList;
import java.util.InputMismatchException;
class Expense {
private String item;
private int amount;
private String category;
Expense(String item, int amount, String category) {
this.item = item;
this.amount = amount;
this.category = category;
}
public String getItem() {
return item;
}
public int getAmount() {
return amount;
}
public String getCategory() {
return category;
}
}
public class Main {
static Scanner scanner = new Scanner(System.in);
static ArrayList expenses = new ArrayList<>();
public static void main(String[] args) {
boolean running = true;
while (running) {
showMenu();
try {
System.out.print("請選擇功能:");
int choice = scanner.nextInt();
scanner.nextLine();
switch (choice) {
case 1:
addExpense();
break;
case 2:
showExpenses();
break;
case 3:
calculateTotal();
break;
case 4:
categoryStatistics();
break;
case 5:
deleteExpense();
break;
case 6:
running = false;
System.out.println("已離開個人記帳系統!");
break;
default:
System.out.println("沒有這個選項!");
}
} catch (InputMismatchException e) {
System.out.println("輸入錯誤,請輸入數字!");
scanner.nextLine();
}
}
scanner.close();
}
public static void showMenu() {
System.out.println();
System.out.println("===== 個人記帳系統 =====");
System.out.println("1. 新增消費");
System.out.println("2. 查看紀錄");
System.out.println("3. 查看總支出");
System.out.println("4. 分類支出統計");
System.out.println("5. 刪除消費紀錄");
System.out.println("6. 離開");
}
public static void addExpense() {
System.out.println();
System.out.println("===== 新增消費 =====");
System.out.print("請輸入消費項目:");
String item = scanner.nextLine();
try {
System.out.print("請輸入消費金額:");
int amount = scanner.nextInt();
System.out.println();
System.out.println("請選擇消費分類:");
System.out.println("1. 飲食");
System.out.println("2. 交通");
System.out.println("3. 購物");
System.out.println("4. 娛樂");
System.out.print("請輸入選項:");
int categoryChoice = scanner.nextInt();
scanner.nextLine();
String category;
switch (categoryChoice) {
case 1:
category = "飲食";
break;
case 2:
category = "交通";
break;
case 3:
category = "購物";
break;
case 4:
category = "娛樂";
break;
default:
category = "其他";
}
Expense expense =
new Expense(item, amount, category);
expenses.add(expense);
System.out.println("記帳成功!");
} catch (InputMismatchException e) {
System.out.println("輸入錯誤,請輸入數字!");
scanner.nextLine();
}
}
public static void showExpenses() {
System.out.println();
System.out.println("===== 消費紀錄 =====");
if (expenses.size() == 0) {
System.out.println("目前沒有消費紀錄。");
return;
}
for (int i = 0; i < expenses.size(); i++) {
Expense expense = expenses.get(i);
System.out.println(
(i + 1) + ". "
+ expense.getItem()
+ "|" + expense.getAmount() + " 元"
+ "|" + expense.getCategory()
);
}
}
public static void calculateTotal() {
System.out.println();
System.out.println("===== 支出統計 =====");
if (expenses.size() == 0) {
System.out.println("目前沒有消費紀錄。");
return;
}
int total = 0;
for (int i = 0; i < expenses.size(); i++) {
total += expenses.get(i).getAmount();
}
System.out.println(
"目前共有 " + expenses.size() + " 筆消費"
);
System.out.println("總支出:" + total + " 元");
}
public static void categoryStatistics() {
System.out.println();
System.out.println("===== 分類支出統計 =====");
if (expenses.size() == 0) {
System.out.println("目前沒有消費紀錄。");
return;
}
int foodTotal = 0;
int transportTotal = 0;
int shoppingTotal = 0;
int entertainmentTotal = 0;
for (int i = 0; i < expenses.size(); i++) {
Expense expense = expenses.get(i);
switch (expense.getCategory()) {
case "飲食":
foodTotal += expense.getAmount();
break;
case "交通":
transportTotal += expense.getAmount();
break;
case "購物":
shoppingTotal += expense.getAmount();
break;
case "娛樂":
entertainmentTotal += expense.getAmount();
break;
}
}
System.out.println("飲食:" + foodTotal + " 元");
System.out.println("交通:" + transportTotal + " 元");
System.out.println("購物:" + shoppingTotal + " 元");
System.out.println("娛樂:" + entertainmentTotal + " 元");
}
public static void deleteExpense() {
System.out.println();
System.out.println("===== 刪除消費紀錄 =====");
if (expenses.size() == 0) {
System.out.println("目前沒有可以刪除的紀錄。");
return;
}
showExpenses();
try {
System.out.print("請輸入要刪除的紀錄編號:");
int number = scanner.nextInt();
scanner.nextLine();
if (number >= 1 && number <= expenses.size()) {
int index = number - 1;
Expense deletedExpense =
expenses.get(index);
expenses.remove(index);
System.out.println(
"已刪除:" + deletedExpense.getItem()
);
} else {
System.out.println("沒有這筆紀錄!");
}
} catch (InputMismatchException e) {
System.out.println("輸入錯誤,請輸入紀錄編號!");
scanner.nextLine();
}
}
}

實際執行看看

假設目前有三筆紀錄:

===== 消費紀錄 =====

  1. 早餐|60 元|飲食
  2. 捷運|30 元|交通
  3. 電影|300 元|娛樂

主選單輸入:

請選擇功能:5

程式會顯示:

===== 刪除消費紀錄 =====
===== 消費紀錄 =====

  1. 早餐|60 元|飲食
  2. 捷運|30 元|交通
  3. 電影|300 元|娛樂
    請輸入要刪除的紀錄編號:2

結果:

已刪除:捷運

再次查看:

===== 消費紀錄 =====

  1. 早餐|60 元|飲食
  2. 電影|300 元|娛樂

成功把第二筆刪除了。

刪除之後編號為什麼會改變?

原本:

Index 0 → 早餐
Index 1 → 捷運
Index 2 → 電影

刪掉 Index 1 的捷運之後,ArrayList 會自動整理:

Index 0 → 早餐
Index 1 → 電影

所以我們不需要自己移動資料。

這也是 ArrayList 比一般 Array 方便的地方之一。

如果輸入不存在的編號

例如目前只有:

  1. 早餐
  2. 電影

卻輸入:

請輸入要刪除的紀錄編號:10

因為有:

if (number >= 1 && number <= expenses.size())

所以程式不會執行 remove(),而是顯示:

沒有這筆紀錄!

這也避免程式因為錯誤的 Index 而發生 Exception。

今天用到的 &&

今天還出現:

&&

它代表 AND(而且)。

例如:

number >= 1 && number <= expenses.size()

意思就是:

編號必須大於等於 1,而且不能超過目前的紀錄數量。

兩個條件都成立,才可以刪除。

例如目前有 3 筆:

1 → 可以
2 → 可以
3 → 可以
4 → 不可以
0 → 不可以
-1 → 不可以

Day 18 學習心得

今天替記帳系統加入了刪除消費紀錄的功能,也正式使用之前學過的 ArrayList.remove()。

實作時我發現最需要注意的是使用者看到的紀錄從 1 開始,但是 ArrayList 的 Index 從 0 開始,所以刪除之前需要先把使用者輸入的編號減 1。

另外也加入了編號範圍判斷和 Exception Handling,避免使用者輸入不存在的紀錄或錯誤格式時讓程式停止。

現在記帳系統已經不只是可以新增資料,也開始可以管理資料。看到自己從前面單純的 Java 語法練習,一步一步做到可以新增、查看、統計和刪除資料的程式,開始比較有完成一個小型系統的感覺。


上一篇
記帳系統實作:依照消費分類統計金額
下一篇
記帳系統實作:新增「修改消費紀錄」功能
系列文
Java 程式設計與實作:30 天打造個人記帳系統 共 24 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言