Scala: ResultSet перевод в различные виды мультикарт
Я собираюсь создать оболочку над JDBC ResultSet в Scala.
Эта обертка предназначена для функции ResultSet => ParticularType
,
Проблема в том, что я не могу найти общее решение для создания MultiMaps.
Вот как я собираю коллекции:
абстрактный класс 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).
На мой взгляд, это должно выглядеть так:
Класс MapCreator[K,IV](keyCreator: ResultSet => K, valueCreator: ResultSet => IV) расширяет CollectionCreator [Карта [K, Место для V]] { тип V = IV val промежуточная карта = новая хэш-карта [K, V] переопределить def append(rs: ResultSet) { appendToMap(keyCreator(rs), valueCreator(rs)) } def appendToMap(ключ: K, значение: IV) { промежуточная карта (ключ) = значение } переопределить def returnCollection(): Map[K,V] = middleMap.toMap }
Если это работает, я бы написал создание ListMultiMap следующим образом:
Класс ListMultiMapCreator[K,IV](keyCreator: ResultSet => K, valueCreator: ResultSet => IV) расширяет MapCreator [K, место для V](keyCreator, valueCreator) { тип переопределения V = список [IV] переопределить def appendToMap (ключ: K, значение: IV) { middleMap (ключ) = middleMap.get(ключ) match { case Some(values) => values.::(value) case None => Список (значение) } } }
Проблема в том, что я не могу использовать V
в Place for V
потому что это не объявлено тогда.
Я чувствую, что абстрактные типы - это хорошее решение, но я не знаю, как правильно с ними обращаться.
Как правильно создавать такие коллекции?
Я также не уверен, возможно ли переопределить абстрактные типы, которые уже были определены выше в иерархии классов.
1 ответ
В вашем определении MapCreator
действительно стесняющий IV
а также V
быть того же типа. По контракту V
вернулся в Map[K,V]
должен быть того же типа, что и тип, возвращаемый valueCreator
, Например, если я позвонил:
MapCreator((rs:ResultSet) => rs.getString("KEY"),
(rs:ResultSet) => rs.getString("VALUE"))(resultSet)
Я ожидал бы получить Map[String,String]
, Вы не можете изменить это отношение, если вы продлите MapCreator
, Если вы хотите Map[String,List[String]]
вам нужно предоставить valueCreator
типа (ResultSet) => List[String]
,
Имея это в виду, вы можете изменить определение и реализацию следующим образом:
class MapCreator[K,IV](keyCreator: ResultSet => K,
valueCreator: ResultSet => IV) extends CollectionCreator[Map[K, IV]] {
val intermediateMap = new HashMap[K, IV]
def append(rs: ResultSet) { appendToMap(keyCreator(rs), valueCreator(rs)) }
def appendToMap(key: K, value: IV) { intermediateMap(key) = value }
def returnCollection(): Map[K, IV] = intermediateMap.toMap
}
class ListMultiMapCreator[K,IV](keyCreator: ResultSet => K,
elemCreator: ResultSet => IV) extends
MapCreator[K, List[IV]](keyCreator,
(rs:ResultSet) => List(elemCreator(rs))) {
override def appendToMap(key: K, value: List[IV]) {
intermediateMap(key) = intermediateMap.get(key) match {
case Some(values) => values.:::(value)
case None => value
}
}
}
Я чувствую это, потому что CollectionCreator
использует параметр типа, что использование абстрактных типов будет затруднительным. В целом, кажется, что есть много котельной плиты. Я бы использовал больше библиотек Scala:
def mapCreate[K, IV](rs: ResultSet,
keyCreator: ResultSet => K,
valueCreator: ResultSet => IV) = {
Iterator.continually(rs).takeWhile(_.next).map{rs =>
keyCreator(rs) -> valueCreator(rs)}.toMap
}
def listMultiMapCreate[K, IV](rs: ResultSet,
keyCreator: ResultSet => K,
valueCreator: ResultSet => IV) = {
Iterator.continually(rs).takeWhile(_.next).map{rs =>
keyCreator(rs) -> valueCreator(rs)}.toList.groupBy(_._1)
}
Также в вашем do { append(rs) } while (rs.next)
Что делать, если набор результатов пуст?