Java/Kotlin:按类ID查找多个哈希集的交集
我在查找包含数据类的散列集数组的交集时遇到问题(我希望通过标识符进行交集): 我已将.csv文件中的一些数据拉入这种类型的结构:Java/Kotlin:按类ID查找多个哈希集的交集,java,kotlin,set,guava,hashset,Java,Kotlin,Set,Guava,Hashset,我在查找包含数据类的散列集数组的交集时遇到问题(我希望通过标识符进行交集): 我已将.csv文件中的一些数据拉入这种类型的结构: ArrayList<HashSet<Protein>> ArrayList 所以我有六个数组列表[1个用于每个csv],每个列表包含一个包含数千个蛋白质结构的散列集。以下是我到目前为止尝试的基于common Protein.id的交叉点哈希集: fun intersection(data: ArrayList<HashSet<P
ArrayList<HashSet<Protein>>
ArrayList
所以我有六个数组列表[1个用于每个csv],每个列表包含一个包含数千个蛋白质结构的散列集。以下是我到目前为止尝试的基于common Protein.id的交叉点哈希集:
fun intersection(data: ArrayList<HashSet<Protein>>): HashSet<Protein> {
val intersectionSet = HashSet<Protein>(data[0])
for (i in 1..data.size) {
intersectionSet.retainAll(data[i])
}
return intersectionSet
}
fun交叉点(数据:ArrayList):HashSet{
val intersectionSet=HashSet(数据[0])
用于(i在1..data.size中){
交叉集保留(数据[i])
}
返回交叉集
}
这将返回一个空列表,考虑到它试图与蛋白质对象相交并将每个标准作为一个整体进行匹配,这是有意义的
如何调用数据[I].id作为交点条件?我对Kotlin和数据类相当陌生:)如果在
Protein
类中添加hashCode
和equals
函数的定义,如下所示,HashSet
将能够使用id
字段适当地检查交叉点
class Protein(val id: String, val score: Double, val molw: Double, val spc: Int) {
override fun hashCode() = id.hashCode()
override fun equals(other: Any?) = other?.let { id == (it as Protein).id } ?: false
}
此外,您可能希望将交叉点
函数中的循环范围更改为1..(data.size-1)
而不是1..data.size
,以避免越界。或者,您可以按如下功能编写:
fun intersection(data: ArrayList<HashSet<Protein>>): HashSet<Protein> {
return data.reduce { acc, it -> acc.apply { retainAll(it) } }
}
fun交叉点(数据:ArrayList):HashSet{
返回data.reduce{acc,it->acc.apply{retainAll(it)}
}
如果您在Protein
类中为hashCode
和equals
函数添加如下定义,则HashSet
将能够使用id
字段适当检查交叉点
class Protein(val id: String, val score: Double, val molw: Double, val spc: Int) {
override fun hashCode() = id.hashCode()
override fun equals(other: Any?) = other?.let { id == (it as Protein).id } ?: false
}
此外,您可能希望将交叉点
函数中的循环范围更改为1..(data.size-1)
而不是1..data.size
,以避免越界。或者,您可以按如下功能编写:
fun intersection(data: ArrayList<HashSet<Protein>>): HashSet<Protein> {
return data.reduce { acc, it -> acc.apply { retainAll(it) } }
}
fun交叉点(数据:ArrayList):HashSet{
返回data.reduce{acc,it->acc.apply{retainAll(it)}
}
要简化给定的答案,您可以使用apply
:
return data.reduce { acc, it -> acc.apply { retainAll(it) } }
要简化给定的答案,您可以使用
apply
:
return data.reduce { acc, it -> acc.apply { retainAll(it) } }
请注意,如果您不希望依赖输入成为哈希集,可以执行以下操作:
fun <T> multiIntersect(data: Collection<Set<T>>) =
HashSet(data.minBy { it.size }!!).apply { data.forEach { retainAll(it) } }
fun multiIntersect(数据:收集)=
HashSet(data.minBy{it.size}!!)。应用{data.forEach{retainAll(it)}
通过从最小的集合开始,您可以潜在地节省大量的运行时间,因为检索集合的大小可以在恒定的时间内完成,因为它保存在对象的字段中。请注意,如果您不希望依赖输入成为哈希集,您可以执行以下操作:
fun <T> multiIntersect(data: Collection<Set<T>>) =
HashSet(data.minBy { it.size }!!).apply { data.forEach { retainAll(it) } }
fun multiIntersect(数据:收集)=
HashSet(data.minBy{it.size}!!)。应用{data.forEach{retainAll(it)}
通过从最小的集合开始,您可以潜在地节省大量的运行时间,因为检索集合的大小可以在恒定的时间内完成,就像它保存在对象的字段中一样。漂亮的解决方案;对于我的交集函数版本和您提供的功能来说,它都是一种魅力。1..data.size调用也很好。后续问题-是否有任何原因需要将hashCode()覆盖指定为Int?当我运行代码而不指定类型时,它的工作原理是相同的。你说得对。没有理由指定类型,因为函数体只是一个表达式,编译器可以推断类型。
等于
时也是如此。我已经更新了答案。漂亮的解决方案;对于我的交集函数版本和您提供的功能来说,它都是一种魅力。1..data.size调用也很好。后续问题-是否有任何原因需要将hashCode()覆盖指定为Int?当我运行代码而不指定类型时,它的工作原理是相同的。你说得对。没有理由指定类型,因为函数体只是一个表达式,编译器可以推断类型。等于
时也是如此。我已经更新了答案。谢谢!我完全错过了。我刚刚更新了答案。谢谢!我完全错过了。我刚刚更新了答案。