如何在Java的User对象内部访问存储该对象的HashMap
我现在有一个存储User对象的HashMap<ObjectId, User>,这些User对象之间存在关联关系。我需要在User对象的方法里通过查找其他用户来更新当前用户的参数,但不知道怎么在User类内部访问这个外部的HashMap。
我的User类代码如下:
import org.bson.types.ObjectId; import org.bson.BsonDocument; import java.util.ArrayList; import java.util.List; public class User { private ObjectId _id; private int grade; private String region; private ArrayList<ObjectId> _reg_by; private ObjectId regBy; public User(){ } public ObjectId getId() { return _id; } public void setId(final ObjectId id) { this._id = id; } public int getGrade() { return grade; } public void setGrade(final int grade) { this.grade = grade; } public String getRegion() { return region; } public void setRegion(final String region) { this.region = region; } public ObjectId getRegBy() { if(regBy == null) { regBy = ((_reg_by.size() != 0) ? _reg_by.get(0) : null); } return regBy; } public void setRegBy(final ObjectId regBy) { this.regBy = regBy; } public ArrayList<ObjectId> get_reg_by(){ return _reg_by; } public void set_reg_by(ArrayList<ObjectId> _reg_by){ this._reg_by = _reg_by; } private String updateRegion(){ if(getRegBy() == null) return null; //TODO search for the person who registered him and use the region! // how to get access to others from here?! } }
我在Main函数中创建这个HashMap:
HashMap<ObjectId, User> users = mongoHandler.getUsers();
希望能在User类的updateRegion方法里实现对这个HashMap的访问,完成区域更新的逻辑。
我来给你几个可行的方案,你可以根据自己的项目场景来选择:
方案1:将HashMap作为参数传入updateRegion(最推荐)
这是最符合单一职责原则的方式,让User类只专注于自身的业务逻辑,不需要依赖外部的存储结构。你只需要修改updateRegion方法,把外部的users HashMap作为参数传进去:
// 修改updateRegion方法,添加参数 public String updateRegion(HashMap<ObjectId, User> users){ ObjectId regById = getRegBy(); if(regById == null) return null; // 从HashMap中找到注册当前用户的用户 User regByUser = users.get(regById); if(regByUser != null){ String newRegion = regByUser.getRegion(); this.setRegion(newRegion); // 更新当前用户的区域 return newRegion; } return null; }
之后在Main里调用的时候,直接传入users集合即可:
// 假设你要更新某个特定用户的区域 User targetUser = users.get(someObjectId); targetUser.updateRegion(users);
优点:
- 低耦合:
User类不需要知道自己被存储在哪里,测试时可以轻松传入模拟的HashMap - 逻辑清晰:方法的依赖关系一目了然
- 线程安全:没有共享的静态状态,多线程环境下不会出问题
缺点:每次调用都需要传参,稍微有点繁琐,但这是合理的设计代价。
方案2:给User类添加静态引用(不推荐)
如果实在不想每次传参,可以考虑把users HashMap设为User类的静态变量,但这种方式会带来强耦合和并发风险,只适合简单的单线程场景:
public class User { // 静态变量存储所有用户的集合 private static HashMap<ObjectId, User> allUsers; // 添加静态方法初始化这个引用 public static void setAllUsers(HashMap<ObjectId, User> users) { allUsers = users; } // 修改updateRegion方法 private String updateRegion(){ ObjectId regById = getRegBy(); if(regById == null) return null; // 检查静态变量是否初始化 if(allUsers == null){ throw new IllegalStateException("请先调用User.setAllUsers初始化用户集合"); } User regByUser = allUsers.get(regById); if(regByUser != null){ String newRegion = regByUser.getRegion(); this.setRegion(newRegion); return newRegion; } return null; } // 其他原有代码... }
然后在Main里初始化静态变量:
HashMap<ObjectId, User> users = mongoHandler.getUsers(); User.setAllUsers(users);
缺点:
- 强耦合:
User类和外部的存储结构绑定在一起,后续如果换了存储方式(比如改成数据库直接查询),修改成本很高 - 并发风险:静态变量是全局共享的,多线程环境下修改或访问需要加锁,容易引发问题
- 测试困难:静态状态会在测试用例之间残留,需要额外的清理步骤
方案3:通过构造函数/Setter注入HashMap(中等推荐)
你也可以在创建User对象的时候,把users HashMap注入到每个User实例中,或者通过Setter方法设置:
public class User { // 实例变量存储用户集合 private HashMap<ObjectId, User> users; // 可选:修改构造函数注入 public User(HashMap<ObjectId, User> users) { this.users = users; } // 可选:添加Setter方法注入 public void setUsers(HashMap<ObjectId, User> users) { this.users = users; } // 修改updateRegion方法 private String updateRegion(){ ObjectId regById = getRegBy(); if(regById == null || users == null) return null; User regByUser = users.get(regById); if(regByUser != null){ String newRegion = regByUser.getRegion(); this.setRegion(newRegion); return newRegion; } return null; } // 其他原有代码... }
如果你的User对象是由MongoDB驱动自动创建的,可能需要在获取集合后手动注入:
HashMap<ObjectId, User> users = mongoHandler.getUsers(); // 遍历所有用户,设置users引用 for(User user : users.values()){ user.setUsers(users); }
优点:
- 比静态引用更灵活,每个
User实例可以关联不同的集合(虽然你这里可能用不到) - 耦合度比静态方式低
缺点:
- 如果是ORM框架自动创建的
User对象,注入步骤会比较繁琐 - 每个
User实例都持有整个HashMap的引用,内存占用会稍微高一点(不过影响不大)
总结
优先选择方案1,它是最干净、最易维护的设计。静态引用的方式尽量避免,除非是非常简单的小项目。如果你的项目有依赖注入框架(比如Spring),也可以考虑用框架来注入用户集合,但本质上和方案3类似。
内容的提问来源于stack exchange,提问作者nima

