我有operator fun plus(other: PenceAmount): PenceAmount {
// Get the primary constructor.
val primaryConstructor = PenceAmount::class.primaryConstructor ?:
throw NullPointerException("The primary constructor can't be found.")
// Get the properties before the loop.
val memberProperties = PenceAmount::class.declaredMemberProperties
// Loop on each constructor parameter and get the new
// values used to create a new instance of PenceAmount.
val newValues = primaryConstructor.parameters.map { parameter ->
// Find the KProperty with the same name of the parameter (because we are in a data class).
val property = memberProperties.first { it.name == parameter.name }
// Sum the amount.
property.get(this) as Int + property.get(other) as Int
}
// Create a new instance of PenceAmount with the new values.
return primaryConstructor.call(*newValues.toTypedArray())
}
个Set<String>
对,我想创建一个"hostname:port"
。我尝试过这样:
Set<InetSocketAddress>
但是这会在 IntelliJ 中产生以下错误:
不兼容的类型。必需
Set<InetSocketAddress> ISAAddresses = StrAddresses .stream().map(addr -> new InetSocketAddress( addr.split(":")[0], Integer.parseInt(addr.split(":")[1])));
但是'map'是 推断为Set<InetSocketAddress>
:没有类型变量R的实例存在Stream<R>
符合Stream<R>
我使用地图和lambda的方式肯定是错的。
答案 0 :(得分:10)
Stream#map
功能不返回 a Map
。它将(映射)流的当前元素转换为其他元素。因此,它使用给定的 转换函数从Stream<X>
Stream<Y>
生成,其中X
和输出Y
。
StrAddresses.stream() // String
.map(addr -> new InetSocketAddress(
addr.split(":")[0],
Integer.parseInt(addr.split(":")[1]))); // InetSocketAddress
您从Stream<String>
开始,最后得到Stream<InetSocketAddress>
。
引用其documentation:
返回将应用 给定函数的结果组成的流到此流的元素。
如果您想将该流转换为Set
,则需要使用Stream#collect
方法,如下所示:
StrAddresses.stream()
.map(addr -> new InetSocketAddress(
addr.split(":")[0],
Integer.parseInt(addr.split(":")[1])))
.collect(Collectors.toSet());
实用程序方法Collectors.toSet()
返回优化良好Set
的收集器。例如,如果您明确需要HashSet
,则可以使用此代码:
.collect(Collectors.toCollection(HashSet::new));
对此流的元素执行可变减少操作。可变减少是指减少的值是可变结果容器,例如
ArrayList
[...]
作为一个小注释,您目前每次分割相同的元素两次:
addr.split(":")[0], // First
Integer.parseInt(addr.split(":")[1]))) // Second
您可以通过记住之前的值来保存该额外的split
过程。在这种情况下,可以通过使用第二次Stream#map
调用来优雅地完成此操作。首先,我们从Stream<String>
转换为Stream<String[]>
,然后转换为Stream<InetSocketAddress>
:
StrAddresses.stream() // String
.map(addr -> addr.split(":")) // String[]
.map(addrData -> new InetSocketAddress(
addrData[0], Integer.parseInt(addrData[1]))) // InetSocketAddress
.collect(Collectors.toSet());
请注意,Stream#map
是延迟操作。这意味着一旦调用该方法,Java就不会将Stream
从A
转换为<{em} B
。它会等到Stream#collect
之类的非延迟(最终确定)操作,然后遍历Stream
并应用每个延迟操作 逐元素即可。因此,您可以根据需要添加任意数量的Stream#map
调用,而不会在整个Stream
上生成额外循环。
答案 1 :(得分:4)
您需要 collect
映射到Stream
后返回的InetSocketAddress
个Set
地址。这可以作为 -
Set<InetSocketAddress> ISAAddresses = StrAddresses.stream()
.map(addr -> new InetSocketAddress(addr.split(":")[0], Integer.parseInt(addr.split(":")[1])))
.collect(Collectors.toSet());