ОБНОВЛЕНИЕ 1 : я расширил ответ, чтобы предоставить больше деталей и объяснений.
Используйте Integer
вместо Int
и java.lang.Double
вместо scala.Double
(это то, что Double
интерпретируется как Scala) в ваших Scala определениях.
Проблема в том, что Java не позволяет использовать примитивы в коллекциях, поэтому в качестве типа используется Integer
вместо int
и Double
вместо double
. В Scala, обработка Int
, Double
, et c. более сложный Он будет обрабатывать их как примитивы (например, Java * int
, double
, et c.) В большинстве случаев, но он будет блокировать (и распаковывать) их при использовании с коллекциями.
Однако при взаимодействии с Java необходимо быть более явным. Scala неявно преобразует Integer
экземпляров в Int
экземпляров - и наоборот - когда это необходимо, но не может неявно преобразовывать коллекции примитивов в штучной упаковке.
Вы можете использовать Java коллекции в Scala просто отлично, с нулевыми накладными расходами; вам вообще не нужно конвертировать их в Scala эквивалентов. Тем не менее, вам, очевидно, потребуется выполнить преобразования, если вы передадите их в код, который ожидает эквивалентные коллекции Scala, или если вы хотите использовать коллекции Scala со своим наследием Java код. (Если неясно, java.util.Map
- это не то же самое, что scala.collection.immutable.Map
, и java.util.List
- это не то же самое, что scala.collection.immutable.List
. Коллекции Scala являются неизменными и предназначены для эффективного использования с использованием функционального программирования парадигмы.)
Если вы беспокоитесь о производительности, вам следует использовать набор инструментов для микро-бенчмаркинга, такой как ScalaMeter , что позволит вам точно измерить сравнение использования коллекций Java в исходном виде с преобразованием в / из Scala коллекций.
ОБНОВЛЕНИЕ 2 :
Я переписал вашу первую попытку, используя коллекции Java. Чтобы избежать путаницы с типами Scala, я переименовал конфликтующие типы Java, добавив к ним префикс J
:
package examples
import java.lang.{Double => JDouble}
import java.util.{List => JList, Map => JMap}
import scala.language.implicitConversions
class Wrapper(val asJava: Inner) {
implicit def consume(map: JMap[Integer, JList[JDouble]]): Unit = {
asJava.consume(map)
}
}
. коллекции Java Map
и List
, а также коробочные примитивы. Он компилируется, но абсолютно ничего не покупает (подпись Wrapper.consume
точно такая же, как Inner.consume
). Тем не менее, он иллюстрирует, как использовать Java коллекции in situ in Scala.
Если вы хотите использовать Scala коллекций и конвертируем в Java эквивалентов, которые, как я думаю, является целью вашей второй попытки, тогда это будет выглядеть так:
package examples
import java.lang.{Double => JDouble}
import scala.jdk.CollectionConverters._
import scala.language.implicitConversions
class Wrapper(val asJava: Inner) {
implicit def consume(map: Map[Int, List[Double]]): Unit = {
val jmap = map.asInstanceOf[Map[Integer, List[JDouble]]]
asJava.consume(jmap.map(p => p._1 -> p._2.asJava).asJava)
}
}
В этом случае сначала нам нужно привести коллекцию к использованию упакованных типов (определения эквивалентны под капотом), у которых нет накладных расходов как таковых.
Затем мы должны преобразовать Scala структур данных, эквивалентных Java структур данных. Совершенно очевидно, что это требует дополнительных усилий, если только обернуть структуры данных Scala в интерфейс Java.
ОБНОВЛЕНИЕ 3
Я также должен отметить, что использование метода Wrapper.consume
implicit
является странным выбором. Я думаю, что вы, возможно, намеревались создать класс implicit
, чтобы (во второй попытке) вы могли неявно потреблять Scala структур данных с экземпляром Inner
. (По сути, Inner
оформляется функциями, предоставленными в Wrapper
.) * Экземпляры Inner
будут неявно преобразованы в Wrapper
экземпляры без дополнительных затрат (это даже не создаст экземпляр Wrapper
в большинстве случаи, из-за предложения extending AnyVal
):
import java.lang.{Double => JDouble}
import scala.jdk.CollectionConverters._
import scala.language.implicitConversions
package object examples {
implicit class Wrapper(val asJava: Inner) extends AnyVal {
def consume(map: Map[Int, List[Double]]): Unit = {
val jmap = map.asInstanceOf[Map[Integer, List[JDouble]]]
asJava.consume(jmap.map(p => p._1 -> p._2.asJava).asJava)
}
}
}
Обратите внимание, что Wrapper
теперь необходимо определить внутри package object
. (Это потому, что неявные классы могут быть определены только внутри object
некоторого вида, который должен быть введен в область видимости, и package object
, как правило, является наиболее удобным способом достижения этого.)