程式碼片段
mCurrentIndex = (mCurrentIndex + 1) % mQuestionBank.length;
int question = mQuestionBank[mCurrentIndex].getmQuestion();
mQuestionTextView.setText(question);
為何需要取模運算?
實現陣列索引循環 (Circular Array),防止索引越界。
情境分析
- 陣列長度
length = 4 (索引 0~3)
mCurrentIndex 初始為 0
- 每次點擊按鈕索引 +1
無取模運算後果
| 點擊次數 | mCurrentIndex (無 %) | 結果 |
| 1 | 1 | 正常 |
| 2 | 2 | 正常 |
| 3 | 3 | 正常 |
| 4 | 4 | ❌ ArrayIndexOutOfBoundsException (最大索引 3) |
| 5 | 5 | 崩潰 |
有取模運算效果
| 點擊次數 | 計算式 | mCurrentIndex | 對應題目 |
| 1 | (0+1)%4 | 1 | 第 2 題 |
| 2 | (1+1)%4 | 2 | 第 3 題 |
| 3 | (2+1)%4 | 3 | 第 4 題 |
| 4 | (3+1)%4 | 0 | 第 1 題 (循環回頭) |
| 5 | (0+1)%4 | 1 | 第 2 題 |
| ... | ... | ... | 無限循環 |
數學原理
(index + 1) % length 將無限遞增的自然數映射至有限範圍 [0, length-1]:
a % b 餘數範圍:0 ~ b-1
- 當
index = length - 1 時:(length-1 + 1) % length = 0
- 形成閉環:
0 → 1 → ... → length-1 → 0 → ...
進階:雙向循環 (上一題/下一題)
// 下一題 (遞增循環)
mCurrentIndex = (mCurrentIndex + 1) % length;
// 上一題 (遞減循環) - 注意負數取模
mCurrentIndex = (mCurrentIndex - 1 + length) % length;
// 或
mCurrentIndex = Math.floorMod(mCurrentIndex - 1, length); // Java 8+ 推薦
常見變體
| 需求 | 公式 |
| 步長 N 循環 | (index + N) % length |
| 指定起始索引 | (startIndex + offset) % length |
| 隨機打亂後循環 | 先 Collections.shuffle(list),再用索引循環 |
實務應用場景
- 題庫循環練習
- 圖片輪播
- 音樂播放清單循環
- 日誌緩衝區 (Ring Buffer)
- 負載均衡輪詢