Java-搜索提供前几个字符的字符串集合

Java-搜索提供前几个字符的字符串集合,java,search,collections,Java,Search,Collections,我有一个字符串集合,我只想搜索前几个字符 例如,考虑字符串的列表:[汤姆,托马兹,爱丽丝,托尔斯泰,约翰]。字符串[to]将导致列表[tom、tomaz、tolstoy] 性能是这里的一个主要问题,列表可能非常大 优化这一点的最佳方法是什么?索引?分类?怎么做 谢谢 看看索尔和卢森。他们通过索引进行字符串搜索,或者您也可以按照其他人的建议编写自己的 如果像这样搜索是一个优先事项,并且不会与您的其他要求发生冲突,我建议您查看以整理数据。如果您坚持使用列表,您的选择是有限的。它根本不适合做这种事情

我有一个字符串集合,我只想搜索前几个字符

例如,考虑字符串的列表:[汤姆,托马兹,爱丽丝,托尔斯泰,约翰]。字符串[to]将导致列表[tom、tomaz、tolstoy]

性能是这里的一个主要问题,列表可能非常大

优化这一点的最佳方法是什么?索引?分类?怎么做


谢谢

看看索尔和卢森。他们通过索引进行字符串搜索,或者您也可以按照其他人的建议编写自己的


如果像这样搜索是一个优先事项,并且不会与您的其他要求发生冲突,我建议您查看以整理数据。

如果您坚持使用列表,您的选择是有限的。它根本不适合做这种事情

执行您正试图执行的操作的数据结构称为Trie

一个快速的google从杜克大学推出了这个java实现:

假设您的列表足够小,可以保存在内存中,我会使用一个


这将为您提供一个与前缀长度成比例的查找时间。

如果您想完全在内存中执行此操作,而不需要任何依赖项,这里有一个快速选项:

static int MAX_PREFIX = 3;
Map<String, List<String>> map = new HashMap<String, List<String>>();

public void addItem(String item) {
    for (int i = 0; i < MAX_PREFIX && i < item.length(); i++) {
        String prefix = item.substring(0, i);
        List<String> matches = map.get(prefix);
        if (matches == null) {
            matches = new ArrayList<String>();
            map.put(prefix, matches);
        }
        matches.add(item);
    }
}

public List<String> getMatches(String prefix) {
    List<String> matches = map.get(prefix);
    return matches == null ? Collections.<String>emptyList() : matches;
}
static int MAX_PREFIX=3;
Map Map=newhashmap();
公共无效附加项(字符串项){
对于(int i=0;i

这将非常快,因为它只是一个
映射
查找,从前缀
字符串
直接转到所需结果的
列表。如果你的列表太大,以至于它不适合内存,那么你需要考虑外部的。如前所述,您可能希望查看Lucene以获取本地索引。或者数据库,只需索引列并执行类似“prefix%”的
查询。

trie是通用的解决方案,正如已经建议的那样,但是如果您想要一个轻量级且相对快速的解决方案,而不需要外部依赖项,只需将所有字符串放入
树集
并使用
tailSet()
查找与前缀匹配的第一个元素,然后遍历尾集,直到找到不匹配的字符串。(注意:如果没有字符串与前缀匹配,那么这甚至可能是第一个元素。)


如果您的列表不超过几千个字符串,那么这种方法在实践中已经足够好了。

是否可以使用数据库?有些索引针对此类搜索进行了优化如果可以,也许可以使用trie而不是集合,因为它更适合此类搜索。尝试和字典自动机最适合此任务。您能告诉我们非常大是什么意思吗?给我们一个大概的数量级。您希望字符串集合经常更改还是基本固定?在Trie上的内存需求和插入时间是惊人的。也就是说,随机访问时间变为O(1),如果你不在乎这些,只想要最快的访问时间,这是很好的。我在某种程度上假设列表是提前知道的,所以我对读取访问和简单性进行了优化。插入时间在这里并不可怕,你可以插入大约百万/秒,最大前缀为3(我只是试了一下)。max prefix越长,但越差。时间是相对的:)这里的单个插入是prefix\u len哈希查找和插入,而在Trie中,它是遍历prefix\u len节点后的单个插入。这也会为每个项消耗内存中的(前缀\u len*size\u of \u ref)+项大小(最小值,忽略哈希表本身和键冲突)。尽管如此,访问时间接近O(1),其中Trie最坏的情况是O(n)。我并不反对Trie的优点:)只是提供了一个可能适合该用例的替代方案。