如何在类中存储60个射箭得分整数以实现SQLite数据库读写?
我正在搭建一款记录射箭比赛得分的应用。每场比赛包含60支箭,得分范围为0-10。请问如何最优设计类来存储每支箭的得分,以便写入SQLite数据库?我可为每支箭单独设置变量,但这种方式效率低下,是否有更优方案?示例代码:
public class Portsmouth { private int id; Date date; private int arrow1; private int arrow2; private int arrow3; ... private int arrow60; }
完全理解你的困扰——用60个单独的arrowX变量确实太冗余了,不仅写起来费劲,后续维护(比如统计总分、修改某支箭得分)也会格外麻烦。下面给你几个更优的设计思路,完美适配SQLite的存储需求:
方案一:用集合存储单场得分(轻量易用)
如果你的核心需求只是单场比赛对应一组得分,且不需要做太细粒度的历史统计(比如单独查所有比赛第10支箭的平均得分),用集合替代60个变量是最省心的选择。比如用List<Integer>或者数组,然后把这组得分序列化后存入数据库(转成JSON字符串就很方便)。
示例Java代码:
import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; public class Portsmouth { private int id; private Date date; // 专门存储60支箭的得分,默认初始化为0分 private List<Integer> arrowScores; // 构造方法:初始化时确保是60个元素的列表 public Portsmouth() { this.arrowScores = new ArrayList<>(Collections.nCopies(60, 0)); } // 设置某支箭的得分(索引建议从0或1开始,自己调整) public void setArrowScore(int index, int score) { // 校验索引和得分合法性 if (index >= 0 && index < 60 && score >= 0 && score <= 10) { arrowScores.set(index, score); } else { throw new IllegalArgumentException("无效的箭支索引或得分范围"); } } // 获取某支箭的得分 public int getArrowScore(int index) { if (index >= 0 && index < 60) { return arrowScores.get(index); } throw new IllegalArgumentException("无效的箭支索引"); } // 快捷计算总分 public int getTotalScore() { return arrowScores.stream().mapToInt(Integer::intValue).sum(); } // 省略id、date、arrowScores的getter/setter }
SQLite存储适配:
给Portsmouth表加一个arrow_scores字段,类型设为TEXT。存储时用Gson或Jackson把List<Integer>转成JSON数组字符串(比如[9,10,8,...]);读取时再反序列化为列表即可。
方案二:拆分两张表(规范化设计,适合复杂统计)
如果后续需要做精细化统计(比如统计某运动员所有比赛前10箭的得分趋势、所有比赛第5支箭的平均得分),数据库规范化设计才是长久之计。我们可以把比赛信息和箭支得分拆成两张表:
主表:matches(比赛表)
- 字段:
id(主键,自增)、date(比赛日期)、athlete_id(关联运动员ID,可选)、match_type(比赛类型,比如Portsmouth)
- 字段:
子表:arrow_scores(箭支得分表)
- 字段:
id(主键,自增)、match_id(外键,关联matches表的id)、arrow_number(箭支序号,1-60)、score(得分0-10)
- 字段:
对应的Java实体类设计:
import java.util.Date; // 比赛主表实体 public class Match { private int id; private Date date; private int athleteId; // 可选,关联运动员信息 private String matchType; // 比如"Portsmouth" // 构造方法、getter/setter省略 } // 箭支得分实体 public class ArrowScore { private int id; private int matchId; // 关联的比赛ID private int arrowNumber; // 1-60 private int score; // 0-10 // 构造方法、getter/setter省略 }
核心优势:
- 完全符合数据库范式,没有冗余数据
- 支持各种复杂查询:比如
SELECT AVG(score) FROM arrow_scores WHERE arrow_number = 5就能轻松得到所有比赛第5支箭的平均得分 - 扩展性极强:以后如果比赛箭数变了(比如改成36支),根本不用修改表结构,只要调整业务逻辑就行
方案三:混合模式(兼顾易用性和扩展性)
要是你既想在业务代码里方便地操作单场比赛的所有得分,又想保留数据库的可查询性,可以试试混合模式:
- 业务层用
List<Integer>来管理单场得分,方便操作 - DAO层做转换:保存比赛时,把
List<Integer>拆成60条ArrowScore记录插入子表;查询时,根据match_id把所有箭支得分查出来,再组装成List<Integer>返回给业务层
这样业务层用起来省心,数据库层面也能支持所有统计需求,算是个折衷的最优解。
最后提个小建议:不管选哪种方案,一定要给得分加合法性校验(确保是0-10的整数),别让无效数据混进数据库里。
内容的提问来源于stack exchange,提问作者Mooney_S

