Scala:将结果集转换为不同类型的多重映射
我将在 Scala 中创建 JDBC ResultSet 的包装器。
这个包装器旨在成为一个函数 ResultSet =>特定类型
。
问题是我找不到制作多重地图的通用解决方案。
这是我获取集合的方式:
abstract class CollectionCreator[C] extends (ResultSet => C) { def apply(rs: ResultSet): C = { do { append(rs) } while (rs.next) returnCollection() } def append(rs: ResultSet) def returnCollection(): C }
接下来是地图创建。它是集合创建的实现,并且由于映射非抽象性而不是抽象的(在我的实现中它始终以 HashMap 为后端)。
在我看来,它应该看起来像这样:
class MapCreator[K,IV](keyCreator: ResultSet => K, valueCreator: ResultSet => IV) extends CollectionCreator[Map[K, Place for V]] { type V = IV val intermediateMap = new HashMap[K, V] override def append(rs: ResultSet) { appendToMap(keyCreator(rs), valueCreator(rs)) } def appendToMap(key: K, value: IV) { intermediateMap(key) = value } override def returnCollection(): Map[K,V] = intermediateMap.toMap }
如果它有效,我会这样编写 ListMultiMap 创建:
class ListMultiMapCreator[K,IV](keyCreator: ResultSet => K, valueCreator: ResultSet => IV) extends MapCreator[K, Place for V](keyCreator, valueCreator) { override type V = List[IV] override def appendToMap(key: K, value: IV) { intermediateMap(key) = intermediateMap.get(key) match { case Some(values) => values.::(value) case None => List(value) } } }
问题是我不能在 Place for V
处使用 V
因为那时还没有声明。
我觉得抽象类型是一个很好的解决方案,但不知道如何正确对待它们。
这样的收藏创作正确的方式是什么?
我也不确定是否可以覆盖已在类层次结构中更高层定义的抽象类型。
I am going to create wrapper over JDBC ResultSet in Scala.
This wrapper is intended to be a function ResultSet => ParticularType
.
The problem is I can't find a common solution for making MultiMaps.
Here is the way I am fetching collections:
abstract class CollectionCreator[C] extends (ResultSet => C) { def apply(rs: ResultSet): C = { do { append(rs) } while (rs.next) returnCollection() } def append(rs: ResultSet) def returnCollection(): C }
Next goes maps creation. It is an implementation of collection creation and it is not abstract due to map non-abstractness (it is always backended with HashMap in my implementation).
In my opinion, it should look like this:
class MapCreator[K,IV](keyCreator: ResultSet => K, valueCreator: ResultSet => IV) extends CollectionCreator[Map[K, Place for V]] { type V = IV val intermediateMap = new HashMap[K, V] override def append(rs: ResultSet) { appendToMap(keyCreator(rs), valueCreator(rs)) } def appendToMap(key: K, value: IV) { intermediateMap(key) = value } override def returnCollection(): Map[K,V] = intermediateMap.toMap }
If it works, I would write ListMultiMap creation this way:
class ListMultiMapCreator[K,IV](keyCreator: ResultSet => K, valueCreator: ResultSet => IV) extends MapCreator[K, Place for V](keyCreator, valueCreator) { override type V = List[IV] override def appendToMap(key: K, value: IV) { intermediateMap(key) = intermediateMap.get(key) match { case Some(values) => values.::(value) case None => List(value) } } }
The problem is I can't use V
at Place for V
because it is not declared then.
I feel like abstract types is the good solution but don't know how to treat them right.
What is the correct way of such a collections creation?
I am also not sure if it is possible to override abstract types that were already defined higher in the class hierarchy.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在您的定义中,
MapCreator
实际上将IV
和V
限制为相同类型。根据约定,Map[K,V]
中返回的V
必须与valueCreator
返回的类型相同。例如,如果我打电话:我希望得到一个
Map[String,String]
。如果扩展MapCreator
,则无法更改该关系。如果您想要一个Map[String,List[String]]
您需要提供一个(ResultSet) => 类型的
。valueCreator
列表[字符串]考虑到这一点,您可以像这样更改定义和实现:
我觉得因为
CollectionCreator
使用类型参数,所以使用抽象类型会很麻烦。总的来说,似乎有很多样板。我会利用更多的 scala 库:同样在您的
do {append(rs) } while (rs.next)
中,如果结果集为空怎么办?In your definition,
MapCreator
is really constrainingIV
andV
to be the same type. By contract theV
returned inMap[K,V]
has to be the same type as the type returned byvalueCreator
. For instance, if I called:I would expect to get a
Map[String,String]
. You cannot change that relation if you extendMapCreator
. If you want aMap[String,List[String]]
you need to supply avalueCreator
of type(ResultSet) => List[String]
.With that in mind you can change the definition and implementation like this:
I feel that because
CollectionCreator
uses a type parameter, that it will be cumbersome to use abstract types. Overall, there seems to be much boiler plate. I would leverage more of the scala libraries:Also in your
do { append(rs) } while (rs.next)
what if the result set is empty?