收集独特物体的最佳方法

时间:2019-07-18 10:36:17

标签: inheritance kotlin

我正在尝试仅收集唯一的对象,然后将它们输出到CSV文件 下面的代码可以吗?还是有正确的方法?

interface f {
    val s1: String
    val s2: String
    fun tot():Int
}

data class A(override val s1: String, override val s2:String, val sub_cost1: Int, val sub_cost2: Int) : f {
    override fun tot() : Int { return sub_cost1 + sub_cost2}
}
data class B(override val s1: String, override val s2:String, val b_cost: Int, val area: Int) : f {
    override fun tot() : Int { return b_cost}
}
data class C(override val s1: String, override val s2:String, val c_cost: Int) : f{
    override fun tot() : Int { return c_cost}
}

fun main(args: Array<String>) {
    val s = mutableSetOf<f>()
    s.add(C("a0","b0", 1))
    s.add(C("a0","b0", 1)) // equal to first elem, must not be added!
    s.add(A("a1","a2", 2, 3))
    s.add(B("b1","b2", 5, 6))

    // to output into CSV file
    println("s1, s2, sub_cost1, sub_cost2, b.cost, c.cost, tot")
    for (i in s) { 
        when (i) {
            is A -> println("${i.s1}, ${i.s2}, ${i.sub_cost1}, ${ i.sub_cost2}, , , ${i.tot()}")
            is B -> println("${i.s1}, ${i.s2}, , , ${i.b_cost}, , ${i.tot()}")
            is C -> println("${i.s1}, ${i.s2}, , , , ${i.c_cost}, ${i.tot()}")
        }
    }
}

预期输出:

s1,s2,sub_cost1,sub_cost2,b_cost,c_cost,tot

a0,b0,,,,,1,1

a1,a2,2,3,,,5

b1,b2,,,,5,5

1 个答案:

答案 0 :(得分:1)

是的,使用Set自动防止重复很普遍。我认为它当然算是“正确的”,在这里没有什么更好的建议。

请注意,这仅在集合可以告诉为重复项时才有效;因此,对象需要具有equals()方法的适当实现,或者您需要给集合提供一个Comparator。在这种情况下,您使用的是data class,它会自动为您提供合适的equals()实现。

使用Set也可以使任何人都清楚自己的意图。

(另一个优点是大多数实现都可以非常快速地检查对象的存在与否。它们也有缺点:与简单的List相比,它们倾向于占用更多的内存。 ,但是较简单的实现没有一致或可预测的迭代顺序。但这通常不是问题-如果需要有序的迭代,则可以使用LinkedHashSet。)

我可能要看的是更改代码中的一件事是when;这要求代码的主要部分了解f的每个实现及其内部。最佳方法并不明显。如果您认为其中的字符串处理与对象内部的关系比所创建的CSV格式的关系更紧密,则可以在接口中添加一个返回String的方法(标准{{1} }方法或诸如toString()之类的方法;那么每个类都可以按照自己的意愿实现它,而主代码可以调用它,而不必关心细节。 (或者,如果将CSV详细信息更好地放在一起,那么toCSVLine()可能会更好。或者您可能会发现一种混合方法,其中when界面中的方法可以提供所需的一切无需了解实施情况。)

(此外,我会大写f接口。Kotlin(和Java)编码标准都以大写字母开头的接口名称,就像类名一样。)