【问题标题】:Quick comparison strings with startsWith使用startsWith快速比较字符串
【发布时间】:2015-11-10 17:38:52
【问题描述】:

我有以下代码:

String[] names = {"aa", ..........., "bb"};
for (int i = 0; i < names.length; i++) {
    if (names[i].toLowerCase().startsWith(query.toLowerCase()))
        c.addRow(new Object[]{i, names[i]});
}

由于数组名称可能很长,我想知道从性能的角度来看,编写此代码的最佳方法是什么。这样循环是O(N)。是否有任何 java 数据结构可以更快地完成同样的事情?

【问题讨论】:

  • 数组“名称”是否按字典顺序排列?
  • 如果names 已排序,您可以对第一个正确值进行二分搜索,然后在数组中前后循环以查找其余匹配项,这应该差不多有效尽可能

标签: java


【解决方案1】:

您可以对名称进行排序,使用二进制搜索和不区分大小写的比较器来查找潜在前缀的插入点,然后遍历数组以捕获具有相同前缀的所有其他单词:

// At preparation time
Arrays.sort(names, String.CASE_INSENSITIVE_ORDER);
...
// At query time
int pos = Arrays.binarySearch(names, query, String.CASE_INSENSITIVE_ORDER);
if (pos < 0) {
    pos = -(pos+1);
}
while (pos < names.length) {
    if (names[pos].toLowerCase().startsWith(query.toLowerCase())) {
        c.addRow(new Object[]{pos, names[pos]});
        pos++;
    } else {
        break;
    }
}

Arrays.binarySearch 找到一个插入点。如果名称匹配,pos 将是非负数;否则,您需要使用以下表达式将其转换为有效索引:-(pos+1) 如果query 是正确的前缀,则其插入点将位于具有匹配前缀的名字前面。由于names 已排序,具有相同前缀的所有条目将彼此相邻。这就是为什么您可以线性地遍历列表直到第一个不匹配,然后在该点停止。

【讨论】:

    【解决方案2】:

    【讨论】:

    • 或者直接对数组进行排序,找到第一项后就可以找到所有的项了。
    猜你喜欢
    • 2013-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-12
    • 1970-01-01
    相关资源
    最近更新 更多