如何在优先队列kotlin中使用比较器

How to use comparator in priority queue kotlin

嘿,我想在 kotlin 的优先级队列中使用自定义比较器。我有数据class

Product.kt

data class Product(val value: String? = null, val price: String? = null) {
    var priceInLong = price?.toLong()
}

我想创建一个价格值最小的最小堆。我正在创建对象,但它给了我某种错误

fun main() {
    var queue = PriorityQueue<Long> { p1: Product, p2: Product ->
        p1.priceInLong?.let {
            p2.priceInLong?.minus(it)
        }
    }

    val list = listOf(
        Product("1", "4.83"),
        Product("2", "4.53"),
        Product("3", "3.54"),
        Product("4", "3.66"),
        Product("5", "5.16")
    )
}

错误

None of the following functions can be called with the arguments supplied.
<init>((MutableCollection<out TypeVariable(E)!>..Collection<TypeVariable(E)!>?))   where E = TypeVariable(E) for    constructor PriorityQueue<E : Any!>(c: (MutableCollection<out E!>..Collection<E!>?)) defined in java.util.PriorityQueue
<init>(Comparator<in TypeVariable(E)!>!)   where E = TypeVariable(E) for    constructor PriorityQueue<E : Any!>(comparator: Comparator<in E!>!) defined in java.util.PriorityQueue
<init>(PriorityQueue<out TypeVariable(E)!>!)   where E = TypeVariable(E) for    constructor PriorityQueue<E : Any!>(c: PriorityQueue<out E!>!) defined in java.util.PriorityQueue
<init>(SortedSet<out TypeVariable(E)!>!)   where E = TypeVariable(E) for    constructor PriorityQueue<E : Any!>(c: SortedSet<out E!>!) defined in java.util.PriorityQueue
<init>(Int)   where E = TypeVariable(E) for    constructor PriorityQueue<E : Any!>(initialCapacity: Int) defined in java.util.PriorityQueue

图片

1. I want to solve this error and add value by price which is minimum comes first.

2. Is my above queue comparator logic is correct to use min heap?

谢谢

更新

我试过这个建议

var queue = PriorityQueue<Product> { p1, p2 ->
        return if (p1.priceInLong != null && p2.priceInLong != null) {
            p2.priceInLong - p1.priceInLong
        } else {
            0
        }
    }

获取错误

更新 2

val queue = PriorityQueue<Product> { p1, p2 ->
        val priceOne = p1.priceInLong
        val priceTwo = p2.priceInLong
        if (priceOne != null && priceTwo != null) {
            if(priceOne == priceTwo){
                return 0 
            }
        } else {
            return 0
        }
    }

data class Product(val value: String? = null, val price: String? = null) {
    val priceInLong = price?.toLong()
}

这个:

{ p1: Product, p2: Product ->
        p1.priceInLong?.let {
            p2.priceInLong?.minus(it)
        }
}

returns null 如果 p1.priceInLong 为空(不执行 let 块),或者如果 p2.priceInLong 为空(let 块 return 为空)。这就是 null-safety 使用 ? 检查的结果。

您收到错误消息是因为您的 Comparator 函数需要 return 一个 Int,但您的 returns Int?,即可为空int 值 - 可以是 int,也可以是 null。所以它与所需的构造函数不匹配,这就是为什么它抱怨 none 的函数匹配。

所以你需要决定如果这些值中的一个(或两个)为空,并且 return 一个整数而不是任何空值,那么你的函数 returns Int 而不是 Int?


如果您在评论中所说的是正确的,并且这些值都不会为空,您可以使用 !!

断言
{ p1: Product, p2: Product ->
    p2.priceInLong!! - p1.priceInLong!!
}

但是使用 !! 是一个不好的迹象 - 你怎么知道它们永远不会为空?如果您可以肯定地说,为什么 priceInLong 首先可以为 null?

I want to solve this error

这里有两个问题:

  1. PriorityQueue 的类型参数应该是 Product(如果你想在其中存储这些对象)。
  2. Comparator 的 Lambda 应该 return Int,而不是 Long?。如果保证 priceInLong == null 不会有 Product,您可以只使用 not-null 断言运算符来摆脱可空性,然后得到 sign 的差异避免 .toInt() 转换可能的整数溢出:
val queue = PriorityQueue<Product> { p1, p2 -> (p1.priceInLong!! - p2.priceInLong!!).sign }