简体   繁体   English

如何将Scala Case类转换为Java HashMap

[英]How To Convert Scala Case Class to Java HashMap

I'm using Mule ESB (Java Based) and I have some scala components that modify and create data. 我正在使用Mule ESB(基于Java),并且有一些Scala组件可以修改和创建数据。 My Data is represented in Case Classes. 我的数据以案例类表示。 I'm trying to convert them to Java, however Just getting them to convert to Scala types is a challenge. 我正在尝试将它们转换为Java,但是让它们转换为Scala类型是一个挑战。 Here's a simplified example of what I'm trying to do: 这是我要执行的操作的简化示例:

package com.echostar.ese.experiment


import scala.collection.JavaConverters

case class Resource(guid: String, filename: String)
case class Blackboard(name: String, guid:String, resource: Resource)

object CCC extends App {
    val res = Resource("4alskckd", "test.file")
    val bb = Blackboard("Test", "123asdfs", res)

    val myMap = getCCParams(bb)
    val result = new java.util.HashMap[String,Object](myMap)
    println("Result:"+result)

    def getCCParams(cc: AnyRef) =
        (Map[String, Any]() /: cc.getClass.getDeclaredFields) {(a, f) =>
            f.setAccessible(true)
            val value = f.get(cc) match {
                //  this covers tuples as well as case classes, so there may be a more specific way
                case caseClassInstance: Product => getCCParams(caseClassInstance): Map[String, Any]
                case x => x
            }
            a + (f.getName -> value)
        }
}

Current Error: Recursive method needs return type. 当前错误:递归方法需要返回类型。

My Scala Foo isn't very strong. 我的Scala Foo不太强壮。 I grabbed this method from another answer here and basically know what it's doing, but not enough to change this to java.util.HashMap and java.util.List 我抓住从另一个回答这个方法在这里基本上知道它在做什么,但不足以改变这java.util.HashMap中和的java.util.List

Expected Output: 预期产量:

Result:{"name"="Test", "guid"="123asdfs", "resource"= {"guid"="4alskckd", "filename"="test.file"}}

UPDATE1: 1. Added getCCParams(caseClassInstance): Map[String, Any] to line 22 Above per @cem-catikkas. UPDATE1:1.在每个@ cem-catikkas的第22行上方添加了getCCParams(caseClassInstance): Map[String, Any] IDE syntax error still says "recursive method ... needs result type" and "overloaded method java.util.HashMap cannot be applied to scala.collection.immutable.Map". IDE语法错误仍然显示“递归方法...需要结果类型”和“重载方法java.util.HashMap无法应用于scala.collection.immutable.Map”。 2. Changed java.util.HashMap[String, Object] 2.更改了java.util.HashMap [String,Object]

You should follow what the error tells you. 您应该按照错误告诉您的内容进行操作。 Since getCCParams is a recursive method you need to declare its return type. 由于getCCParams是递归方法,因此您需要声明其返回类型。

def getCCParams(cc: AnyRef): Map[String, Any]

Answering this in case anyone else going through the issue ends up here (as happened to me). 以防万一其他人遇到这个问题(在我身上)。

I believe the error you were getting had to do with the fact that the return type was being declared at method invocation (line 22), however the compiler was expecting it at the method's declaration (in your case, line 17). 我相信您得到的错误与以下事实有关:返回类型是在方法调用时声明的(第22行),但是编译器希望在方法的声明中声明它(在您的情况下,第17行)。 The below seems to have worked: 以下似乎有效:

def getCCParams(cc: AnyRef): Map[String, Any] = ...

Regarding the conversion from Scala Map to Java HashMap , by adding the ._ wildcard to the JavaConverters import statement, you manage to import all the methods of the object as single identifiers, which is a requirement for implicit conversions. 关于从Scala Map到Java HashMap转换 ,通过将._通配符添加到JavaConverters import语句,您可以设法将对象的所有方法作为单个标识符导入,这是隐式转换的要求。 This will include the asJava method which can then be used to convert the Scala Map to a Java one, and then this can be passed to the java.util.HashMap(Map<? extends K,? extends V> m) constructor to instantiate a HashMap : 这将包括asJava方法,该方法随后可用于将Scala Map转换为Java,然后可以将其传递给java.util.HashMap(Map<? extends K,? extends V> m)构造函数以实例化一个HashMap

import scala.collection.JavaConverters._
import java.util.{HashMap => JHashMap}

...

val myMap = getCCParams(bb)
val r = myMap.asJava    // converting to java.util.Map[String, Any]
val result: JHashMap[String,Any] = new JHashMap(r)

I wonder if you've considered going at it the other way around, by implementing the java.util.Map interface in your case class? 我想知道您是否考虑过通过在case类中实现java.util.Map接口来解决问题? Then you wouldn't have to convert back and forth, but any consumers downstream that are using a Map interface will just work (for example if you're using Groovy's field dot-notation). 这样,您就不必来回转换,但是任何使用Map接口的下游使用者都可以使用(例如,如果您使用的是Groovy的字段点符号)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM