2011-04-07 39 views
2

我將在Scala中通過JDBC ResultSet創建封裝。
此包裝旨在成爲功能ResultSet => ParticularType
問題是我找不到製作MultiMaps的通用解決方案。Scala:將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因爲那麼它沒有被聲明。
我覺得抽象類型是很好的解決方案,但不知道如何正確對待它們。

創建這種集合的正確方法是什麼?

我也不確定是否可以重寫已經在類層次結構中定義更高的抽象類型。

回答

2

在您的定義中,MapCreator確實約束IVV爲相同類型。根據合同,Map[K,V]中返回的V必須與valueCreator返回的類型相同。例如,如果我打電話:

MapCreator((rs:ResultSet) => rs.getString("KEY"), 
    (rs:ResultSet) => rs.getString("VALUE"))(resultSet) 

我期望得到一個Map[String,String]。如果您延長MapCreator,則無法更改該關係。如果您需要Map[String,List[String]],則需要提供(ResultSet) => List[String]類型的valueCreator

考慮到這一點,你可以改變的定義和實現這樣的:

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使用類型參數,這將是難於使用抽象類型。總的來說,似乎有很多鍋爐板。我將利用更多的斯卡拉庫:

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)如果結果集就是空

也?

+0

謝謝@huynhjl。我會使用大膽的解決方案,因爲它不會導致冗餘收集遍歷。我懷念groupBy方法,但害怕它的使用太昂貴。我仍然對不重複此代碼的解決方案感興趣:'Iterator.continually(rs).takeWhile(_。next).map {rs => keyCreator(rs) - > valueCreator(rs)}' 但是對於我目前目的與groupBy的解決方案是可以接受的,因爲相對較小的集合的大小。 – 2011-04-08 19:51:42