В Scala это будет выглядеть примерно так:
// collections are immutable by default, but we want the mutable flavour
import collection.mutable
// An alias so we don't keep repeating ourself
type DiagMultiMap[T] = mutable.Map[String, mutable.Set[Diagnostic[T]]]
//pimp DiagMultiMap with the addDiagnostic method
class MapDiag[T](theMap: DiagMultiMap[T]) {
def addDiagnostic(d: Diagnostic[T]): Unit = {
val set = theMap.getOrElseUpdate(d.getCode) {mutable.Set.empty}
set += d
}
}
//an implicit conversion to enable the pimp
implicit def mapDiagPimp[T](theMap: DiagMultiMap[T]) = new MapDiag(theMap)
//This is how we make one
def mkDiagnosticMultiMap[T](entries: Seq[Diagnostic[T]]): DiagMultiMap[T] = {
val theMap = new mutable.HashMap[String, mutable.Set[Diagnostic[T]]]()
entries foreach { theMap addDiagnostic _ }
theMap
}
Это не проверено, поскольку у меня нет доступа к коду для Diagnostic
ОБНОВЛЕНИЕ
Это научит меня писать поздно ночью, на самом деле это намного проще ...
Учитывая любую последовательность Diagnostic
объектов:
val diags = List(new Diagnostic(...), new Diagnositic(...), ...)
их можно легко сгруппировать одним способом:
val diagMap = diags.groupBy(_.getCode)
Но это немного сложнее!
Еще большая проблема заключается в том, что Diagnostic
является частьюстандартная библиотека Java, так что вы не можете переписать ее с помощью аннотаций отклонений (подробнее об этом после кода).Обертка будет делать то же самое, и, к счастью, она не слишком велика:
class RichDiagnostic[S+](underlying: Diagnostic[S]) {
def code: String = underlying.getCode
def columnNumber: Long = underlying.getColumnNumber
def endPosition: Long = underlying.getEndPosition
def kind: Diagnostic.Kind = underlying.getKind
def lineNumber: Long = underlying.getLineNumber
def messageFor(locale: Locale): String = underlying.getMessage(locale)
def position: Long = underlying.getPosition
def source: S = underlying.getSource
def startPosition: Long = underlying.getStartPosition
implicit def toUnderlying: Diagnostic[S] = underlying
}
+
в [S+]
помечает этот класс как ковариантный, поэтому RichDiagnostic[A]
считается подклассомRichDiagnostic[B]
, если A
является подклассом B
.Это ключ к тому, чтобы избежать неприятных общих подписей, не более <? extends T>
или <? super T>
!
Его также достаточно просто использовать:
val richDiags = diags.map(d => new RichDiagnostic(d))
val diagMap = richDiags.groupBy(_.code)
Если диагностика изначально поставлялась какJava List, тогда такие методы, как map
, не будут автоматически доступны для вас, но преобразование тривиально:
import collection.JavaConverters._
//the toList isn't strictly necessary, but we get a mutable Buffer otherwise
val richDiags = diagsFromJava.asScala.toList.map(d => new RichDiagnostic(d))
val diagMap = richDiags.groupBy(_.code)
Создание этой коллекции - операция за один раз, и ее придется повторять, если записидобавлены в базовый список, но я подозреваю, что это не будет проблемой.