java - 在java中将java映射转换为scala不可变映射

标签 java scala collections

我需要一个方法,它获取 java Map 并将其转换为 scala 不可变 Map。 我尝试过这样做

import scala.Predef;
import scala.Tuple2;
import scala.collection.JavaConverters;

public static <K,V> scala.collection.immutable.Map<K,V> convert(java.util.HashMap<K,V> javaMap) {
       return JavaConverters.mapAsScalaMapConverter(javaMap).asScala().toMap(Predef.<Tuple2<K,V>>conforms());
}

但我收到以下消息

所需类型:scala.$less$colon$less,scala.Tuple2>

提供:scala .Predef.$less$colon$less,scala.Tuple2>

我需要使用Java语言解决这个问题,但我无法编写任何Scala代码 upd:我也尝试过强制转换,但我得到了 java.lang.ClassCastException: java.util.HashMap 无法强制转换为 scala.collection.immutable.Map

最佳答案

我编写了以下 Scala 代码:

import scala.collection.JavaConverters._

class MapConversion {

  def fromScala[K, V](map: scala.collection.immutable.Map[K, V]): java.util.Map[K, V] = map.asJava

  def toScala[K, V](map: java.util.Map[K, V]): scala.collection.mutable.Map[K, V] = map.asScala
}

并编译它

scala-cli compile --scala "2.12.11" .

(JavaConverters 建议使用 Scala 2.12 或更早版本)。

然后我在https://dmitriy-gulyaev.github.io/java-disassembler/中打开了生成的MapConversion.class虽然我也可以使用 javap

阅读字节码表明最接近的 Java 代码将类似于:

class MapConversion {

  <K, V> java.util.Map<>K, V> fromScala(
    scala.collection.immutable.Map<K, V> map
  ) {
     return
        // get JavaConverters$ companion object instance
        scala.collection.JavaConverters$.MODULE$
        // use implicit conversion to wrap it in Decorators$AsJava
          .mapAsJavaConverter(map)
          // call asJava to convert the value
          .asJava 
  }

  <K, V> scala.collection.mutable.Map<K, V> toScala(
    java.util.Map<K, V> map
  ) {
    return
      // get JavaConverters$ companion object instance
      scala.collection.JavaConverters$.MODULE$
        // use implicit conversion to wrap it in Decorators$AsScala
        .mapAsScalaMapConverter(map)
        // call asScala to convert the value
        .asScala
  }
}

(免责声明:我没有测试过,也不打算测试)。

然而,99% 的情况下,“不使用 Scala 语言”的要求很难辩护:它放弃了适合这项工作的正确工具(编译器),它需要逆向生成,而这又需要 JVM 工作原理的知识,并且每次进行任何更改都需要进行此类逆向工程。它也不会“保存”代码库免受“Scala 污染”,因为显然 Scala 标准库和使用它的代码已经在依赖项中。

如果整个公司不想与 Scala 打交道,那也没关系。但这些问题可以通过以下方式更容易解决:

  1. 定义接口(interface):
interface JavaToScalaAdapters {
  // ...
}
  • 在 Scala 中将其实现为顶级类,没有构造函数参数、全局变量等
  • class JavaToScalaAdaptersImpl extends JavaToScalaAdapters {
      // ...
    }
    
  • 在 Java 中调用 new 来获取此实现,并像任何其他 Java 代码一样调用它
  • JavaToScalaAdapters adapters = new JavaToScalaAdaptersImpl();
    

    它可能是所有公司 Java 项目中使用的单个工件,这些项目依赖 Scala,即使他们不想这样做。任何其他解决方案都会浪费大量时间和金钱。即使这是一种一次性解决方法,用 Scala 编写、编译并将 .class 文件放入版本控制中的资源目录中,也比对代码进行逆向工程更快。此类逆向工程唯一合理的情况是学习或开发一些低级实用程序。

    关于java - 在java中将java映射转换为scala不可变映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77023755/

    相关文章:

    JavaFX:如何在代码中设置背景图像?

    java - Kafka Streams - 偏移量提交失败。请求超时

    scala - 如何以功能风格进行文件创建和操作?

    java - 的意思 ?在 Map<String, ?>

    java - 迭代包含用户定义对象的 HashSet 元素并显示满足特定条件的元素

    java - 在 Java 中传递 2D ArrayList

    java - 为什么 UsbAccessory 类是在 API Level 12 中添加的,而不是从 API Level 8 中添加的?

    scala - Akka中的reference.conf与application.conf文件

    class - Scala 中符号的导入和通配符导入

    java - hibernate:父级的子ID检索列表