如何基于Discord用户IdLong存储并检索关联数据?
Discord JDA 用户数据存储解决方案
一、内存中高效存储与检索
别用ArrayList<ArrayList<Long>>了,直接用键值对集合(Map),把用户ID作为键(Long类型),用户的相关数据作为值。这样通过用户ID可以直接定位到对应数据,时间复杂度是O(1),比遍历ArrayList高效太多。
实现步骤:
- 定义一个简单的数据类封装用户信息(比如初始值和后续新增数据):
public class UserData { private long initialValue; // 初始值1L // 可按需添加其他long型字段 // 构造方法、getter/setter public UserData(long initialValue) { this.initialValue = initialValue; } public long getInitialValue() { return initialValue; } public void setInitialValue(long initialValue) { this.initialValue = initialValue; } // 新增字段的getter/setter同理 }
- 初始化全局
Map存储用户数据:
private Map<Long, UserData> userDataMap = new HashMap<>();
- 处理
;create指令时存入数据:
// 指令监听方法示例 public void onCommand(MessageReceivedEvent event) { String message = event.getMessage().getContentRaw(); if (message.startsWith(";create")) { long userId = event.getAuthor().getIdLong(); if (!userDataMap.containsKey(userId)) { userDataMap.put(userId, new UserData(1L)); event.getChannel().sendMessage("数据创建成功!").queue(); } else { event.getChannel().sendMessage("你已创建过数据!").queue(); } } }
- 检索指定用户的初始值:
long targetUserId = 123456789L; // 目标用户ID if (userDataMap.containsKey(targetUserId)) { long initialValue = userDataMap.get(targetUserId).getInitialValue(); // 后续逻辑处理 }
二、文件持久化存储(解决Bot重启数据丢失问题)
方案1:JSON格式存储(最适合自学开发者)
用JSON序列化整个userDataMap,读写操作简单,无需手动处理行定位。推荐用Google的Gson库实现:
- 添加Gson依赖(Maven示例):
<dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.10.1</version> </dependency>
- 实现保存与加载方法:
private static final String DATA_FILE = "user_data.json"; private Gson gson = new GsonBuilder().setPrettyPrinting().create(); // 保存数据到文件 public void saveUserData() { try (FileWriter writer = new FileWriter(DATA_FILE)) { gson.toJson(userDataMap, writer); } catch (IOException e) { e.printStackTrace(); } } // 从文件加载数据 public void loadUserData() { File file = new File(DATA_FILE); if (!file.exists()) return; try (FileReader reader = new FileReader(file)) { Type mapType = new TypeToken<Map<Long, UserData>>(){}.getType(); userDataMap = gson.fromJson(reader, mapType); } catch (IOException e) { e.printStackTrace(); } }
- 使用时机:
- Bot启动时调用
loadUserData()加载数据 - 每次修改数据(如
;create执行后)调用saveUserData()保存 - 也可定时保存,比如用
ScheduledExecutorService每5分钟执行一次保存操作
方案2:自定义文本行存储(坚持每行存用户数据)
如果一定要用每行存储(格式示例:用户ID:初始值:其他数据),可按以下方式实现查找与修改:
- 查找指定用户ID的行:
public String findUserLine(long userId) { try (BufferedReader reader = new BufferedReader(new FileReader("user_data.txt"))) { String line; while ((line = reader.readLine()) != null) { String[] parts = line.split(":"); if (parts.length > 0 && Long.parseLong(parts[0]) == userId) { return line; } } } catch (IOException e) { e.printStackTrace(); } return null; }
- 修改用户数据(需读写整个文件):
public void updateUserData(long userId, long newInitialValue) { List<String> lines = new ArrayList<>(); boolean isUserExist = false; // 读取所有行 try (BufferedReader reader = new BufferedReader(new FileReader("user_data.txt"))) { String line; while ((line = reader.readLine()) != null) { String[] parts = line.split(":"); if (parts.length > 0 && Long.parseLong(parts[0]) == userId) { // 修改该行数据 lines.add(userId + ":" + newInitialValue + ":" + (parts.length > 2 ? parts[2] : "")); isUserExist = true; } else { lines.add(line); } } } catch (IOException e) { e.printStackTrace(); } // 新用户则添加行 if (!isUserExist) { lines.add(userId + ":" + newInitialValue + ":"); } // 重新写入文件 try (BufferedWriter writer = new BufferedWriter(new FileWriter("user_data.txt"))) { for (String line : lines) { writer.write(line); writer.newLine(); } } catch (IOException e) { e.printStackTrace(); } }
此方案适合简单场景,但数据量大时效率低于JSON方案,因为每次修改都需读写整个文件。
内容的提问来源于stack exchange,提问作者Marvel Charles
相关产品推荐
相关产品推荐

