You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin中如何按与当前设备坐标的距离对Location列表排序

按坐标距离排序Location列表的几种实现方式

首先,我们需要一个计算两个Location之间距离(或距离平方,排序时用平方更高效,因为开根号不影响大小比较)的辅助函数。另外注意你的Location类中属性名用了Long(大写L),这和Kotlin的Long类型重名,建议改成lon或long避免混淆,下面示例中会保留你的原属性名,但建议修改。

// 计算两点间欧几里得距离的平方(排序无需开根号,提升效率)
fun Location.distanceSquaredTo(other: Location): Double {
    val latDiff = this.lat - other.lat
    val longDiff = this.Long - other.Long
    return latDiff * latDiff + longDiff * longDiff
}

方法1:使用sortBy快速排序

sortBy是Kotlin集合的扩展函数,接收一个lambda表达式,返回用于排序的依据值,默认按该值升序排列(正好符合“由近到远”的需求)。

直接调用即可完成排序:

locations.sortBy { it.distanceSquaredTo(myLocation) }

这个方法最简洁,适合简单的排序场景。


方法2:使用sortWith配合Comparator

sortWith需要传入一个Comparator实例,用于定义两个元素的比较规则,适合需要自定义复杂排序逻辑的场景。

2.1 用Comparator.compareBy快速构建

和sortBy逻辑类似,只是通过Comparator的方式传入排序依据:

locations.sortWith(Comparator.compareBy { it.distanceSquaredTo(myLocation) })

2.2 自定义完整Comparator实现

如果需要额外的排序逻辑(比如距离相同时按纬度排序),可以手动实现Comparator:

locations.sortWith(object : Comparator<Location> {
    override fun compare(a: Location, b: Location): Int {
        val distanceA = a.distanceSquaredTo(myLocation)
        val distanceB = b.distanceSquaredTo(myLocation)
        // 升序排列:a更近返回-1,相等返回0,b更近返回1
        return distanceA.compareTo(distanceB)
    }
})

也可以用lambda简化写法:

locations.sortWith(Comparator { a, b ->
    val distanceA = a.distanceSquaredTo(myLocation)
    val distanceB = b.distanceSquaredTo(myLocation)
    distanceA.compareTo(distanceB)
})

补充:真实地理经纬度的距离计算

如果你的坐标是真实的地球经纬度,欧几里得距离会有误差,建议使用Haversine公式计算球面距离:

const val EARTH_RADIUS = 6371000.0 // 地球平均半径,单位:米

fun Location.haversineDistanceTo(other: Location): Double {
    val lat1 = Math.toRadians(this.lat)
    val lon1 = Math.toRadians(this.Long)
    val lat2 = Math.toRadians(other.lat)
    val lon2 = Math.toRadians(other.Long)

    val dLat = lat2 - lat1
    val dLon = lon2 - lon1

    val a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
            Math.cos(lat1) * Math.cos(lat2) *
            Math.sin(dLon / 2) * Math.sin(dLon / 2)
    val c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))

    return EARTH_RADIUS * c // 返回两点间球面距离,单位:米
}

使用时只需要把排序逻辑中的distanceSquaredTo替换成haversineDistanceTo即可,排序方式完全一致。

内容的提问来源于stack exchange,提问作者Joel Delgado

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 14:15:43