在 Kotlin 中将映射值转换为数据 Class
Transform Map Values to Data Class in Kotlin
我有一个地图,其值是不同对象类型(LocalDate、LocalTime、Float、List(Float))的数组列表。
我想将地图值转换为我创建的自定义数据class。
我已经尝试解构映射值组件,但是我收到错误消息“Map.Entry 类型的解构声明初始值设定项必须具有 'component3()' 函数”。
我将如何执行下面的转换?
Blockquote
val localDate1 = LocalDate.now()
val localTime1 = LocalTime.now()
val float1 = 1f
val floatList1 = listOf<Float>(1f, 2f, 3f)
val localDate2 = LocalDate.now()
val localTime2 = LocalTime.now()
val float2 = 2f
val floatList2 = listOf<Float>(4f, 5f, 6f)
val myMap = HashMap<String, Any>()
myMap["keyOne"] = arrayListOf<Any>(localDate1, localTime1, float1, floatList1)
myMap["keyTwo"] = arrayListOf<Any>(localDate2, localTime2, float2, floatList2)
val newMap = myMap.mapValues { (date, time, float, floatList) -> /*Here i am getting destructuring error*/
CustomObject(
date,
time,
float,
floatList
)
}
Blockquote
data class CustomObject (
val date: LocalDate,
val time: LocalTime,
val float: Float,
val floatList: List<Float>
)
Map.mapValues()
takes a lambda whose receiver is the map Entry,不是它的值。 (该方法是以 lambda 的结果命名的,而不是它的参数。) 所以你不能那样解构它。
还有类型转换问题:myMap
是一个值为 Any
的映射,但您似乎假设每个值实际上是 List
的 Any
](实际元素是按适当顺序排列的适当类型)。所以你需要做必要的转换来告诉编译器它们是什么类型(或者至少,你假设它们是什么类型......)
因此您可以将其解构为一个单独的步骤,例如:
val newMap = myMap.mapValues { entry ->
val (date, time, float, floatList) = entry.value as List<Any>
CustomObject(
date as LocalDate,
time as LocalTime,
float as Float,
floatList as List<Float>
)
}
或者您可以直接使用数组值:
val newMap = (myMap as Map<String, List<Any>>).mapValues {
CustomObject(
it.value[0] as LocalDate,
it.value[1] as LocalTime,
it.value[2] as Float,
it.value[3] as List<Float>
)
}
但是我认为首先避免列出列表会好得多。您需要大量额外的代码来创建列表然后转换它们——但其中大部分代码都是不安全的:如果列表不够长,每个解构都可能会失败并出现异常(可能是 ArrayIndexOutOfBoundsException),并且每个转换都可能因 ClassCastException 而失败。转换总是有代码味道,尤其是像这样未经检查的; Kotlin 的类型系统足够强大,可以表达大多数你可能想要的东西,所以像这样绕过它往往表明设计可以改进。
因此,如果有任何方法可以直接创建自定义对象,那可能会更短、更安全、更快且更易于阅读。
import java.time.LocalDate
import java.time.LocalTime
data class CustomObject(
val date: LocalDate,
val time: LocalTime,
val float: Float,
val floatList: List<Float>
)
val myMap = mapOf(
"keyOne" to listOf(LocalDate.now(), LocalTime.now(), 1f, listOf(1f, 2f, 3f)),
"keyTwo" to listOf(LocalDate.now(), LocalTime.now(), 2f, listOf(4f, 5f, 6f))
)
val newMap = myMap.mapValues {
CustomObject(
it.value[0] as LocalDate,
it.value[1] as LocalTime,
it.value[2] as Float,
(it.value[3] as List<*>).map { fl -> fl as Float }
)
}
println(newMap)
我有一个地图,其值是不同对象类型(LocalDate、LocalTime、Float、List(Float))的数组列表。
我想将地图值转换为我创建的自定义数据class。
我已经尝试解构映射值组件,但是我收到错误消息“Map.Entry
我将如何执行下面的转换?
Blockquote
val localDate1 = LocalDate.now()
val localTime1 = LocalTime.now()
val float1 = 1f
val floatList1 = listOf<Float>(1f, 2f, 3f)
val localDate2 = LocalDate.now()
val localTime2 = LocalTime.now()
val float2 = 2f
val floatList2 = listOf<Float>(4f, 5f, 6f)
val myMap = HashMap<String, Any>()
myMap["keyOne"] = arrayListOf<Any>(localDate1, localTime1, float1, floatList1)
myMap["keyTwo"] = arrayListOf<Any>(localDate2, localTime2, float2, floatList2)
val newMap = myMap.mapValues { (date, time, float, floatList) -> /*Here i am getting destructuring error*/
CustomObject(
date,
time,
float,
floatList
)
}
Blockquote
data class CustomObject (
val date: LocalDate,
val time: LocalTime,
val float: Float,
val floatList: List<Float>
)
Map.mapValues()
takes a lambda whose receiver is the map Entry,不是它的值。 (该方法是以 lambda 的结果命名的,而不是它的参数。) 所以你不能那样解构它。
还有类型转换问题:myMap
是一个值为 Any
的映射,但您似乎假设每个值实际上是 List
的 Any
](实际元素是按适当顺序排列的适当类型)。所以你需要做必要的转换来告诉编译器它们是什么类型(或者至少,你假设它们是什么类型......)
因此您可以将其解构为一个单独的步骤,例如:
val newMap = myMap.mapValues { entry ->
val (date, time, float, floatList) = entry.value as List<Any>
CustomObject(
date as LocalDate,
time as LocalTime,
float as Float,
floatList as List<Float>
)
}
或者您可以直接使用数组值:
val newMap = (myMap as Map<String, List<Any>>).mapValues {
CustomObject(
it.value[0] as LocalDate,
it.value[1] as LocalTime,
it.value[2] as Float,
it.value[3] as List<Float>
)
}
但是我认为首先避免列出列表会好得多。您需要大量额外的代码来创建列表然后转换它们——但其中大部分代码都是不安全的:如果列表不够长,每个解构都可能会失败并出现异常(可能是 ArrayIndexOutOfBoundsException),并且每个转换都可能因 ClassCastException 而失败。转换总是有代码味道,尤其是像这样未经检查的; Kotlin 的类型系统足够强大,可以表达大多数你可能想要的东西,所以像这样绕过它往往表明设计可以改进。
因此,如果有任何方法可以直接创建自定义对象,那可能会更短、更安全、更快且更易于阅读。
import java.time.LocalDate
import java.time.LocalTime
data class CustomObject(
val date: LocalDate,
val time: LocalTime,
val float: Float,
val floatList: List<Float>
)
val myMap = mapOf(
"keyOne" to listOf(LocalDate.now(), LocalTime.now(), 1f, listOf(1f, 2f, 3f)),
"keyTwo" to listOf(LocalDate.now(), LocalTime.now(), 2f, listOf(4f, 5f, 6f))
)
val newMap = myMap.mapValues {
CustomObject(
it.value[0] as LocalDate,
it.value[1] as LocalTime,
it.value[2] as Float,
(it.value[3] as List<*>).map { fl -> fl as Float }
)
}
println(newMap)