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) Что делать, если набор результатов пуст?

Другие вопросы по тегам