我知道我们已经对 replacement of object instances 有疑问,答案总是:即使你可以,也永远不要这样做,这是黑魔法,但我不知道如何解决我的问题,所以让我解释一下......
我正在解析有关某些车辆及其特定模块的数据以存储在数据库中(这是关于游戏的)。每个Vehicle
除其他数据外还包含许多CompatibleModules
:
class Vehicle {
String id;
// other stuff...
CompatibleModules modules;
}
CompatibleModules
在复杂的排列(依赖项和内容)中包含许多 Module
类的后代对象(例如 Engine extends Module
) .
class CompatibleModules {
Engine defaultEngine;
List<Engine> compatibleEngines;
// other stuff...
}
预计同一Module
会在此类中被多次引用。
我只是在每辆车的基础上获取数据,所以即使某些车辆共享相同的模块(它们这样做,过度),我正在编写一个新的 Module
对象每辆车。完成解析后,我想通过删除重复项并单独存储模块来优化数据库,以便车辆仅通过 ID 引用模块。
这就是问题开始的地方:我可以轻松地从每个Vehicle
的CompatibleModules
结构中获取所有Module
,存储它们位于 HashSet
中,从而检测冲突。但在我检测到冲突后,将 CompatibleModules
中重复项的所有引用替换为原始引用并不是一项简单的任务。
在这种情况下,替换所有重复项的引用的优雅方法是什么?
最佳答案
不要将模块视为车辆的一部分,而应将它们视为用于制造车辆的独立部件。
因此,您希望有一个工厂来管理可用的模块,当您制造车辆时,您会向工厂询问必要的模块。然后工厂确保每个模块“类型”或“实例”在整个系统中只存在一次。
[编辑] 一种解决方案是替换 List<Engine> compatibleEngines
与 Set<Engine> compatibleEngines = new LinkedHashSet<>();
。 LinkedHashSet
保留插入顺序。进行此更改后,您只需添加模块即可,它们将相互覆盖。
注意:要使其正常工作,您必须覆盖 equals()
和hashCode()
.
如果你做不到这一点,那么创建一个具有良好 equals()
的包装对象和hashCode()
。清除重复项:
Set<Wrapper> wrappedEngines = new LinkedHashSet<>();
for( Engine e : compatibleEngines ) {
wrappedEngines.add( new Wrapper( e ) );
}
compatibleEngines.clear();
for( Wrapper e : wrappedEngines ) {
compatibleEngines.add( e.getDelegate() );
}
关于java - 替换重复的 java 对象,包括所有引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21481551/