数据排序和搜索 - OpenHarmony KMP实现

项目概述
数据排序和搜索是现代应用开发中的核心需求。无论是在数据库查询、列表展示、搜索功能还是数据分析中,都需要进行各种排序和搜索操作。然而,不同的编程语言和平台对排序和搜索的实现方式各不相同,这导致开发者需要在不同平台上重复编写类似的逻辑。
本文介绍一个基于 Kotlin Multiplatform (KMP) 和 OpenHarmony 平台的数据排序和搜索工具库。这个工具库提供了一套完整的排序和搜索能力,包括多种排序算法、二分查找、线性搜索、模糊搜索等功能。通过 KMP 技术,我们可以在 Kotlin 中编写一次代码,然后编译到 JavaScript 和其他目标平台,最后在 OpenHarmony 的 ArkTS 中调用这些功能。
技术架构
多平台支持
- Kotlin/JVM: 后端服务和桌面应用
- Kotlin/JS: Web 应用和浏览器环境
- OpenHarmony/ArkTS: 鸿蒙操作系统应用
核心功能模块
- 快速排序: 高效的通用排序算法
- 冒泡排序: 简单的排序算法
- 插入排序: 适合小数据集的排序算法
- 二分查找: 快速查找排序数据中的元素
- 线性搜索: 在未排序数据中查找元素
- 模糊搜索: 根据关键词进行模糊匹配
- 过滤和映射: 对数据进行过滤和转换
- 分组操作: 按条件对数据进行分组
Kotlin 实现
核心排序和搜索类
// 文件: src/commonMain/kotlin/SortAndSearchEngine.kt
/**
* 排序和搜索引擎
* 提供各种排序和搜索功能
*/
class SortAndSearchEngine {
/**
* 快速排序
* @param list 要排序的列表
* @param ascending 是否升序
* @return 排序后的列表
*/
fun quickSort(list: List<Int>, ascending: Boolean = true): List<Int> {
if (list.size <= 1) return list
val pivot = list[list.size / 2]
val left = list.filter { it < pivot }
val middle = list.filter { it == pivot }
val right = list.filter { it > pivot }
val sorted = quickSort(left, ascending) + middle + quickSort(right, ascending)
return if (ascending) sorted else sorted.reversed()
}
/**
* 冒泡排序
* @param list 要排序的列表
* @param ascending 是否升序
* @return 排序后的列表
*/
fun bubbleSort(list: List<Int>, ascending: Boolean = true): List<Int> {
val arr = list.toMutableList()
val n = arr.size
for (i in 0 until n) {
for (j in 0 until n - i - 1) {
val shouldSwap = if (ascending) arr[j] > arr[j + 1] else arr[j] < arr[j + 1]
if (shouldSwap) {
val temp = arr[j]
arr[j] = arr[j + 1]
arr[j + 1] = temp
}
}
}
return arr
}
/**
* 插入排序
* @param list 要排序的列表
* @param ascending 是否升序
* @return 排序后的列表
*/
fun insertionSort(list: List<Int>, ascending: Boolean = true): List<Int> {
val arr = list.toMutableList()
for (i in 1 until arr.size) {
val key = arr[i]
var j = i - 1
while (j >= 0 && (if (ascending) arr[j] > key else arr[j] < key)) {
arr[j + 1] = arr[j]
j--
}
arr[j + 1] = key
}
return arr
}
/**
* 二分查找
* @param sortedList 已排序的列表
* @param target 目标值
* @return 目标值的索引,如果不存在返回 -1
*/
fun binarySearch(sortedList: List<Int>, target: Int): Int {
var left = 0
var right = sortedList.size - 1
while (left <= right) {
val mid = (left + right) / 2
when {
sortedList[mid] == target -> return mid
sortedList[mid] < target -> left = mid + 1
else -> right = mid - 1
}
}
return -1
}
/**
* 线性搜索
* @param list 列表
* @param target 目标值
* @return 所有匹配的索引列表
*/
fun linearSearch(list: List<Int>, target: Int): List<Int> {
return list.mapIndexed { index, value -> if (value == target) index else -1 }
.filter { it != -1 }
}
/**
* 模糊搜索字符串
* @param list 字符串列表
* @param keyword 关键词
* @return 匹配的字符串列表
*/
fun fuzzySearch(list: List<String>, keyword: String): List<String> {
val lowerKeyword = keyword.lowercase()
return list.filter { it.lowercase().contains(lowerKeyword) }
}
/**
* 获取最大值
* @param list 列表
* @return 最大值
*/
fun findMax(list: List<Int>): Int {
return list.maxOrNull() ?: 0
}
/**
* 获取最小值
* @param list 列表
* @return 最小值
*/
fun findMin(list: List<Int>): Int {
return list.minOrNull() ?: 0
}
/**
* 计算平均值
* @param list 列表
* @return 平均值
*/
fun calculateAverage(list: List<Int>): Double {
return if (list.isNotEmpty()) list.sum().toDouble() / list.size else 0.0
}
/**
* 过滤列表
* @param list 列表
* @param predicate 过滤条件
* @return 过滤后的列表
*/
fun filter(list: List<Int>, predicate: (Int) -> Boolean): List<Int> {
return list.filter(predicate)
}
/**
* 映射列表
* @param list 列表
* @param transform 转换函数
* @return 转换后的列表
*/
fun map(list: List<Int>, transform: (Int) -> Int): List<Int> {
return list.map(transform)
}
/**
* 分组操作
* @param list 列表
* @param keySelector 分组键选择器
* @return 分组后的映射
*/
fun groupBy(list: List<Int>, keySelector: (Int) -> String): Map<String, List<Int>> {
return list.groupBy { keySelector(it) }
}
/**
* 去重
* @param list 列表
* @return 去重后的列表
*/
fun distinct(list: List<Int>): List<Int> {
return list.distinct()
}
/**
* 反转列表
* @param list 列表
* @return 反转后的列表
*/
fun reverse(list: List<Int>): List<Int> {
return list.reversed()
}
/**
* 获取统计信息
* @param list 列表
* @return 统计信息映射
*/
fun getStatistics(list: List<Int>): Map<String, Any> {
return mapOf(
"count" to list.size,
"sum" to list.sum(),
"max" to (list.maxOrNull() ?: 0),
"min" to (list.minOrNull() ?: 0),
"average" to calculateAverage(list),
"distinct" to list.distinct().size
)
}
}
Kotlin 实现的核心特点
Kotlin 实现中的排序和搜索功能充分利用了 Kotlin 标准库的集合处理能力。快速排序使用了分治法,通过选择枢轴并递归排序左右两部分。冒泡排序和插入排序使用了传统的算法实现。
二分查找使用了标准的二分查找算法,适用于已排序的列表。线性搜索返回所有匹配的索引。模糊搜索使用了字符串包含检查。
过滤和映射使用了 Kotlin 的高阶函数。分组操作使用了 groupBy 方法。统计功能使用了集合的 sum、maxOrNull、minOrNull 等方法。
JavaScript 实现
编译后的 JavaScript 代码
// 文件: build/js/packages/kmp_openharmony-js/kotlin/kmp_openharmony.js
// (由 Kotlin 编译器自动生成)
/**
* SortAndSearchEngine 类的 JavaScript 版本
* 通过 Kotlin/JS 编译器从 Kotlin 源代码生成
*/
class SortAndSearchEngine {
/**
* 快速排序
* @param {number[]} list - 要排序的列表
* @param {boolean} ascending - 是否升序
* @returns {number[]} 排序后的列表
*/
quickSort(list, ascending = true) {
if (list.length <= 1) return list;
const pivot = list[Math.floor(list.length / 2)];
const left = list.filter(x => x < pivot);
const middle = list.filter(x => x === pivot);
const right = list.filter(x => x > pivot);
const sorted = [...this.quickSort(left, ascending), ...middle, ...this.quickSort(right, ascending)];
return ascending ? sorted : sorted.reverse();
}
/**
* 冒泡排序
* @param {number[]} list - 要排序的列表
* @param {boolean} ascending - 是否升序
* @returns {number[]} 排序后的列表
*/
bubbleSort(list, ascending = true) {
const arr = [...list];
const n = arr.length;
for (let i = 0; i < n; i++) {
for (let j = 0; j < n - i - 1; j++) {
const shouldSwap = ascending ? arr[j] > arr[j + 1] : arr[j] < arr[j + 1];
if (shouldSwap) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
}
return arr;
}
/**
* 插入排序
* @param {number[]} list - 要排序的列表
* @param {boolean} ascending - 是否升序
* @returns {number[]} 排序后的列表
*/
insertionSort(list, ascending = true) {
const arr = [...list];
for (let i = 1; i < arr.length; i++) {
const key = arr[i];
let j = i - 1;
while (j >= 0 && (ascending ? arr[j] > key : arr[j] < key)) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = key;
}
return arr;
}
/**
* 二分查找
* @param {number[]} sortedList - 已排序的列表
* @param {number} target - 目标值
* @returns {number} 目标值的索引
*/
binarySearch(sortedList, target) {
let left = 0;
let right = sortedList.length - 1;
while (left <= right) {
const mid = Math.floor((left + right) / 2);
if (sortedList[mid] === target) {
return mid;
} else if (sortedList[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return -1;
}
/**
* 线性搜索
* @param {number[]} list - 列表
* @param {number} target - 目标值
* @returns {number[]} 所有匹配的索引
*/
linearSearch(list, target) {
return list
.map((value, index) => value === target ? index : -1)
.filter(index => index !== -1);
}
/**
* 模糊搜索
* @param {string[]} list - 字符串列表
* @param {string} keyword - 关键词
* @returns {string[]} 匹配的字符串列表
*/
fuzzySearch(list, keyword) {
const lowerKeyword = keyword.toLowerCase();
return list.filter(item => item.toLowerCase().includes(lowerKeyword));
}
/**
* 获取最大值
* @param {number[]} list - 列表
* @returns {number} 最大值
*/
findMax(list) {
return list.length > 0 ? Math.max(...list) : 0;
}
/**
* 获取最小值
* @param {number[]} list - 列表
* @returns {number} 最小值
*/
findMin(list) {
return list.length > 0 ? Math.min(...list) : 0;
}
/**
* 计算平均值
* @param {number[]} list - 列表
* @returns {number} 平均值
*/
calculateAverage(list) {
return list.length > 0 ? list.reduce((a, b) => a + b, 0) / list.length : 0;
}
/**
* 过滤列表
* @param {number[]} list - 列表
* @param {Function} predicate - 过滤条件
* @returns {number[]} 过滤后的列表
*/
filter(list, predicate) {
return list.filter(predicate);
}
/**
* 映射列表
* @param {number[]} list - 列表
* @param {Function} transform - 转换函数
* @returns {number[]} 转换后的列表
*/
map(list, transform) {
return list.map(transform);
}
/**
* 去重
* @param {number[]} list - 列表
* @returns {number[]} 去重后的列表
*/
distinct(list) {
return [...new Set(list)];
}
/**
* 反转列表
* @param {number[]} list - 列表
* @returns {number[]} 反转后的列表
*/
reverse(list) {
return [...list].reverse();
}
/**
* 获取统计信息
* @param {number[]} list - 列表
* @returns {Object} 统计信息
*/
getStatistics(list) {
const sum = list.reduce((a, b) => a + b, 0);
return {
count: list.length,
sum: sum,
max: this.findMax(list),
min: this.findMin(list),
average: this.calculateAverage(list),
distinct: this.distinct(list).length
};
}
}
JavaScript 实现的特点
JavaScript 版本完全由 Kotlin/JS 编译器自动生成,确保了与 Kotlin 版本的行为完全一致。JavaScript 的数组方法提供了强大的集合处理能力。
filter、map、reduce 等高阶函数用于数据处理。Math.max 和 Math.min 用于查找极值。Set 用于去重操作。
ArkTS 调用代码
OpenHarmony 应用集成
// 文件: kmp_ceshiapp/entry/src/main/ets/pages/SortAndSearchPage.ets
import { SortAndSearchEngine } from '../../../../../../../build/js/packages/kmp_openharmony-js/kotlin/kmp_openharmony';
@Entry
@Component
struct SortAndSearchPage {
@State selectedOperation: string = 'quickSort';
@State inputData: string = '64,34,25,12,22,11,90,88,45,50';
@State searchValue: string = '';
@State result: string = '';
@State resultTitle: string = '';
private engine = new SortAndSearchEngine();
private operations = [
{ name: '快速排序', value: 'quickSort' },
{ name: '冒泡排序', value: 'bubbleSort' },
{ name: '插入排序', value: 'insertionSort' },
{ name: '二分查找', value: 'binarySearch' },
{ name: '线性搜索', value: 'linearSearch' },
{ name: '模糊搜索', value: 'fuzzySearch' },
{ name: '统计信息', value: 'statistics' },
{ name: '去重', value: 'distinct' },
{ name: '反转', value: 'reverse' },
{ name: '最大/最小值', value: 'minmax' }
];
build() {
Column() {
// 标题
Text('📊 数据排序和搜索工具库')
.fontSize(28)
.fontWeight(FontWeight.Bold)
.fontColor('#FFFFFF')
.width('100%')
.padding(20)
.backgroundColor('#1A237E')
.textAlign(TextAlign.Center)
Scroll() {
Column() {
// 操作选择
Column() {
Text('选择操作')
.fontSize(14)
.fontWeight(FontWeight.Bold)
.fontColor('#333333')
.margin({ bottom: 12 })
Flex({ wrap: FlexWrap.Wrap }) {
ForEach(this.operations, (op: { name: string; value: string }) => {
Button(op.name)
.layoutWeight(1)
.height(40)
.margin({ right: 8, bottom: 8 })
.backgroundColor(this.selectedOperation === op.value ? '#1A237E' : '#E0E0E0')
.fontColor(this.selectedOperation === op.value ? '#FFFFFF' : '#333333')
.fontSize(11)
.onClick(() => {
this.selectedOperation = op.value;
this.result = '';
this.resultTitle = '';
})
})
}
.width('100%')
}
.width('95%')
.margin({ top: 16, left: '2.5%', right: '2.5%', bottom: 16 })
.padding(12)
.backgroundColor('#FFFFFF')
.borderRadius(6)
// 输入区域
Column() {
Text('输入数据')
.fontSize(14)
.fontWeight(FontWeight.Bold)
.fontColor('#333333')
.margin({ bottom: 8 })
TextInput({ placeholder: '输入数据(逗号分隔)', text: this.inputData })
.onChange((value) => this.inputData = value)
.width('100%')
.height(80)
.padding(12)
.border({ width: 1, color: '#4DB6AC' })
.borderRadius(6)
.fontSize(12)
.margin({ bottom: 12 })
if (this.selectedOperation === 'binarySearch' || this.selectedOperation === 'linearSearch' ||
this.selectedOperation === 'fuzzySearch') {
TextInput({ placeholder: '输入搜索值', text: this.searchValue })
.onChange((value) => this.searchValue = value)
.width('100%')
.height(50)
.padding(12)
.border({ width: 1, color: '#4DB6AC' })
.borderRadius(6)
.fontSize(12)
}
}
.width('95%')
.margin({ left: '2.5%', right: '2.5%', bottom: 16 })
.padding(12)
.backgroundColor('#FFFFFF')
.borderRadius(6)
// 操作按钮
Row() {
Button('✨ 执行')
.layoutWeight(1)
.height(44)
.backgroundColor('#1A237E')
.fontColor('#FFFFFF')
.fontSize(14)
.fontWeight(FontWeight.Bold)
.borderRadius(6)
.onClick(() => this.executeOperation())
Blank()
.width(12)
Button('🔄 清空')
.layoutWeight(1)
.height(44)
.backgroundColor('#F5F5F5')
.fontColor('#1A237E')
.fontSize(14)
.border({ width: 1, color: '#4DB6AC' })
.borderRadius(6)
.onClick(() => {
this.result = '';
this.resultTitle = '';
})
}
.width('95%')
.margin({ left: '2.5%', right: '2.5%', bottom: 16 })
// 结果显示
if (this.resultTitle) {
Column() {
Text(this.resultTitle)
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor('#FFFFFF')
.width('100%')
.padding(12)
.backgroundColor('#1A237E')
.borderRadius(6)
.textAlign(TextAlign.Center)
.margin({ bottom: 12 })
Scroll() {
Text(this.result)
.fontSize(12)
.fontColor('#333333')
.fontFamily('monospace')
.textAlign(TextAlign.Start)
.width('100%')
.padding(12)
.selectable(true)
}
.width('100%')
.height(300)
.backgroundColor('#F9F9F9')
.border({ width: 1, color: '#4DB6AC' })
.borderRadius(6)
}
.width('95%')
.margin({ left: '2.5%', right: '2.5%', bottom: 16 })
.padding(12)
.backgroundColor('#FFFFFF')
.borderRadius(6)
}
}
.width('100%')
}
.layoutWeight(1)
.width('100%')
}
.width('100%')
.height('100%')
.backgroundColor('#F5F5F5')
}
private executeOperation() {
if (!this.inputData.trim()) {
this.resultTitle = '❌ 错误';
this.result = '请输入数据';
return;
}
try {
const numbers = this.inputData.split(',').map(x => parseInt(x.trim())).filter(x => !isNaN(x));
switch (this.selectedOperation) {
case 'quickSort':
const quickSorted = this.engine.quickSort(numbers, true);
this.resultTitle = '⚡ 快速排序结果';
this.result = `原数据: ${numbers.join(', ')}\n排序后: ${quickSorted.join(', ')}`;
break;
case 'bubbleSort':
const bubbleSorted = this.engine.bubbleSort(numbers, true);
this.resultTitle = '🫧 冒泡排序结果';
this.result = `原数据: ${numbers.join(', ')}\n排序后: ${bubbleSorted.join(', ')}`;
break;
case 'insertionSort':
const insertionSorted = this.engine.insertionSort(numbers, true);
this.resultTitle = '📌 插入排序结果';
this.result = `原数据: ${numbers.join(', ')}\n排序后: ${insertionSorted.join(', ')}`;
break;
case 'binarySearch':
if (!this.searchValue) {
this.resultTitle = '❌ 错误';
this.result = '请输入搜索值';
return;
}
const sorted = this.engine.quickSort(numbers, true);
const target = parseInt(this.searchValue);
const index = this.engine.binarySearch(sorted, target);
this.resultTitle = '🔍 二分查找结果';
this.result = `已排序数据: ${sorted.join(', ')}\n搜索值: ${target}\n结果: ${index >= 0 ? `找到,位置: ${index}` : '未找到'}`;
break;
case 'linearSearch':
if (!this.searchValue) {
this.resultTitle = '❌ 错误';
this.result = '请输入搜索值';
return;
}
const searchTarget = parseInt(this.searchValue);
const indices = this.engine.linearSearch(numbers, searchTarget);
this.resultTitle = '🔎 线性搜索结果';
this.result = `数据: ${numbers.join(', ')}\n搜索值: ${searchTarget}\n结果: ${indices.length > 0 ? `找到 ${indices.length} 个,位置: ${indices.join(', ')}` : '未找到'}`;
break;
case 'fuzzySearch':
if (!this.searchValue) {
this.resultTitle = '❌ 错误';
this.result = '请输入搜索值';
return;
}
const stringNumbers = numbers.map(x => x.toString());
const fuzzyResults = this.engine.fuzzySearch(stringNumbers, this.searchValue);
this.resultTitle = '🔤 模糊搜索结果';
this.result = `数据: ${stringNumbers.join(', ')}\n关键词: ${this.searchValue}\n结果: ${fuzzyResults.length > 0 ? fuzzyResults.join(', ') : '未找到'}`;
break;
case 'statistics':
const stats = this.engine.getStatistics(numbers);
this.resultTitle = '📈 统计信息';
this.result = `数据: ${numbers.join(', ')}\n数量: ${stats.count}\n总和: ${stats.sum}\n最大值: ${stats.max}\n最小值: ${stats.min}\n平均值: ${stats.average.toFixed(2)}\n去重后数量: ${stats.distinct}`;
break;
case 'distinct':
const distinctNumbers = this.engine.distinct(numbers);
this.resultTitle = '✨ 去重结果';
this.result = `原数据: ${numbers.join(', ')}\n去重后: ${distinctNumbers.join(', ')}`;
break;
case 'reverse':
const reversed = this.engine.reverse(numbers);
this.resultTitle = '🔄 反转结果';
this.result = `原数据: ${numbers.join(', ')}\n反转后: ${reversed.join(', ')}`;
break;
case 'minmax':
const max = this.engine.findMax(numbers);
const min = this.engine.findMin(numbers);
this.resultTitle = '📊 最大/最小值';
this.result = `数据: ${numbers.join(', ')}\n最大值: ${max}\n最小值: ${min}\n差值: ${max - min}`;
break;
}
} catch (e) {
this.resultTitle = '❌ 执行出错';
this.result = `错误: ${e}`;
}
}
}
ArkTS 集成的关键要点
在 OpenHarmony 应用中集成排序和搜索工具库需要考虑多种操作类型和用户体验。我们设计了一个灵活的 UI,能够支持不同的排序和搜索操作。
操作选择界面使用了 Flex 布局和 FlexWrap 来实现响应式的按钮排列。当用户选择不同的操作时,输入区域会动态显示相应的输入字段。
对于需要搜索值的操作,我们提供了额外的输入框。结果显示使用了可选择的文本,这样用户可以轻松复制处理结果。
对于排序操作,我们显示了原数据和排序后的数据进行对比。对于搜索操作,我们显示了搜索结果和位置信息。
工作流程详解
排序和搜索的完整流程
- 操作选择: 用户在 ArkTS UI 中选择要执行的排序或搜索操作
- 数据输入: 用户输入要处理的数据
- 参数输入: 根据选择的操作输入必要的参数
- 处理执行: 调用 SortAndSearchEngine 的相应方法
- 结果展示: 将处理结果显示在 UI 中
跨平台一致性
通过 KMP 技术,我们确保了在所有平台上的行为一致性。无论是在 Kotlin/JVM、Kotlin/JS 还是通过 ArkTS 调用,排序和搜索的逻辑和结果都是完全相同的。
实际应用场景
数据库查询
在数据库查询中,需要对数据进行排序和搜索。这个工具库提供了必要的算法实现。
列表展示
在列表展示中,需要对数据进行排序和过滤。这个工具库提供了这些功能。
搜索功能
在搜索功能中,需要进行快速查找和模糊匹配。这个工具库提供了这些功能。
数据分析
在数据分析中,需要对数据进行统计和分组。这个工具库提供了必要的分析功能。
性能优化
算法选择
根据数据规模选择合适的排序算法。对于小数据集使用插入排序,对于大数据集使用快速排序。
缓存排序结果
在频繁排序相同数据时,可以缓存排序结果以避免重复计算。
安全性考虑
输入验证
在处理用户输入的数据时,应该进行验证,确保数据的有效性。
边界检查
在进行搜索和排序时,应该检查数据的边界,避免越界错误。
总结
这个 KMP OpenHarmony 数据排序和搜索工具库展示了如何使用现代的跨平台技术来处理常见的数据处理任务。通过 Kotlin Multiplatform 技术,我们可以在一个地方编写业务逻辑,然后在多个平台上使用。
排序和搜索是数据处理中的基础功能。通过使用这样的工具库,开发者可以快速、可靠地处理各种排序和搜索操作,从而提高开发效率和代码质量。
在实际应用中,建议根据具体的需求进行定制和扩展,例如添加更多的排序算法、实现高级搜索功能等高级特性。同时,定期进行性能测试和优化,确保应用在处理大量数据时仍然保持良好的性能。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)