[英]Better to use a list of pairs, or two lists?
我正在编写一个构成Java类公共接口一部分的方法。 它广泛允许调用者指定要分配给多个数据库实体的值 - 因此它们必须提供实体本身的ID以及要分配给它们的值。
我在实现它作为List<Pair<Integer, Integer>>
或只有两个List<Integer>
参数之间摇摆不定。 两者都显然有效 ,并且在我的方法中都不会导致任何实现或效率问题。 它在任何情况下( 2xn数组)基本上都是相同的信息,只是条纹不同。
所以我想对你认为哪一个会更好,以及为什么会有一些意见。
到目前为止我看到的对列表的优点:
这对列表的优点:
Pair
是作为一个概念来掌握) 两种情况都具有相同的类型安全性,以及参数不匹配的相同可能性(例如,首先输入值,而当它应该相反时输入ID秒)。 后一个问题可以通过在Integer
周围创建一个简单的包装器来调用,这个包装器叫做PrimaryKey
,它有自己的优点和缺点,无论如何都与这个问题正交,因为在这两种情况下都可以使用它。
然而,有一个中间立场可能成为第三种选择 - 一个简单的容器类,其中包含objectId和value的整数字段。 这并没有使编译器帮助确保通过键入来确保对象是正确的,但它确实在赋值中提供了额外的安全层。 我不认为我会这样做,因为我不喜欢用像这样的普通类来污染公共接口的想法。
我强烈建议将这些数据捆绑在一起,可能是一对,但更多是作为一个特定的容器。 这样你就可以自由地引入与这两个对象相关的额外功能。
保持两个列表分开将是一个痛苦。 你必须将两者一起传递并使它们保持同步。 为此创建新对象的开销可以忽略不计,而且正是OOP的设计目标(您只需为应用程序编写新的Java代码就可以创建非JDK类,不要忘记)。
我一直在创建像这样的小班。 它们强制实施强大的类型安全性,并提供增强和重构的范围。 IDE可以更容易地识别和执行重构。
我觉得你所经历的分析已经很好地确定了两种方法的优缺点。
我还倾向于使用Pair
类,引用您列出的优点:
- 更准确地反映实体之间的实际关系
- 消除某些类型的动态错误(例如列表长度不匹配)
对我来说最重要的是最重要的一个。
始终编写演示意图的代码。 不要仅仅考虑实现来编写代码。
使用像Pair
这样的类表示意图是存在一对表示ID和实际实体本身的值。 它还表明,一个Pair
对象是一个需要一起处理的离散数据单元 - 不能因为拥有两个独立的ID和实体List
而感到厌烦。
为什么不使用Dictionary (地图类型,现在Java调用它,我认为它曾经是Hashtable
)? 这会将ID映射到值并避开您的困境。
当API公开时,请确保您只是实现核心功能,因为您提供给客户端的所有内容都永远不会被收回。
想想一个只有2个参数赋值的方法(Integer entityId,Integer someOtherId),让客户想出如何添加更多项目。
如果你想允许方便的访问,给它们一个带有接口“Assignment”的util类,它只定义了getEntityId()和getSomeOtherId(),并带有DefaultAssignment等默认实现,它保存了对id的最终引用。
然后您的客户可以选择他们想要的方式,您不必确保支持您的“配对”课程。
我会去的List
中Pair
S,如果两个整数真正属于一起,应该代表“一件事”。
使用两个单独列表的另一个缺点是,如果列表总是大小相同,编译器不会检查您。 然后你将解释留给你方法的客户; 客户端需要匹配两个列表中的元素。
我没有看到使用像Pair
这样的类是一个很大的缺点“因为它依赖于非JDK类”,正如你所说,但如果你真的不想使用像Pair
这样的东西,你甚至可以把它作为一个列表数组: List<Integer[]>
,其中每个数组包含两个Integer
对象。 (在我看来,这比使用Pair
丑)。
列表对方法是显而易见的,因为它更准确地反映了意图 - 但如果ID是唯一的,则Map可能会更好。
如果您有数百万这些对,并且内存消耗成为主要考虑因素,您可能希望切换到列表对(因为每对将少一个对象)。
我不同意这一点:
因为虽然JDK中没有Pair
类,但是有一个接口: Map.Entry
,它适合您作为键/值关联的预期用途。
在我看来,请使用对列表(或您自己更具体的容器),因为这似乎是最自然地反映您正在解决的问题。 它只是一个变量来跟踪和发送到方法,而不是两个。
使用对列表或地图。
我不买你列出的任何“骗局”论点。
你应该总是在更大的抽象方面犯错误。 你正在编写一种面向对象的语言,在我看来,封装和信息隐藏是思考对象的最重要原因。 它隐藏了用户的实现细节,让他们专注于您的课程提供的内容。 他们可以忘记你的班级如何完成他们想要的东西。 强迫您的客户维护两个列表,要求他们了解他们需要的内容。
首先编写单元测试。 然后,您可以轻松查看最容易使用的内容,然后选择它作为您的实现。
您可以考虑将参数设置为Iterator<Pair>
。 如果调用类具有List<Pair>
,则获取迭代器是微不足道的。 如果不是,则创建迭代器可能更容易构造,更快和/或更自然。 在某些情况下,它甚至可以帮助您消除内存不足问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.