在Java中搜索集合

时间:2009-08-23 13:50:07

标签: java search string collections

我有一个java属性文件,其中包含一对国家/地区名称和代码的键/值对。我将把这个文件的内容加载到像List或HashMap这样的Collection中。

然后,我希望用户能够搜索国家/地区,例如,如果他们在文本框中键入“Aus”并单击“提交”,那么我想搜索我拥有的集合,其中包含密钥/值对国家/地区代码/名称(例如AUS => Australia),并返回找到匹配的国家/地区。

除了循环使用集合的元素并使用charAt()之外,还有更有效的方法吗?

4 个答案:

答案 0 :(得分:3)

如果性能很重要,您可以使用TreeSet或TreeMap来保存国家/地区名称,并执行以下操作来识别以给定字符串开头的国家/地区。

NavigableMap<String, String> countries = new TreeMap<String, String>();
countries.put("australia", "Australia");
...

String userText = ...
String tmp = userText.toLower();
List<String> hits = new ArrayList<String>();
Map.Entry<String, String> entry = countries.ceilingEntry(tmp);
while (entry != null && entry.getKey().startsWith(tmp)) {
    hits.add(entry.getValue());
    entry = map.higherEntry(entry.getKey());
}
// hits now contains all country names starting with the value of `userText`, 
// ignoring differences in letter case.

这是O(logN),其中N是国家/地区的数量。相比之下,集合的线性搜索是O(N)

答案 1 :(得分:1)

如果没有通过像Lucene之类的东西索引集合,那么你必须通过循环遍历所有元素来手动检查。你可以使用startsWith而不是循环遍历字符串:

String userText = ...
for (Map.Entry<String, String> entry : map) {
    boolean entryMatches = entry.getKey().startsWith(userText);
    ...

或者使用正则表达式:

Pattern pattern = Pattern.compile(userText);

for (Map.Entry<String, String> entry : map) {
    boolean entryMatches = pattern.matcher(entry.getKey()).find();
    ...

答案 2 :(得分:1)

循环使用String.contains()是除非你想移动像Lucene这样的重型火炮的方式。

答案 3 :(得分:-1)

由于列表足够小以加载到内存中,使用静态方法java.util.Collections.binarySearch()对其进行排序然后进行二分查找。这会返回一个索引,无论确切的字符串是否在列表中都可以正常工作(尽管如果不是,它会返回一个负数,所以一定要检查一下)。然后,从该索引开始,只需迭代前进即可查找具有该前缀的所有字符串。作为一个很好的副作用,结果输出将按字母顺序排列。

要使整个事件不区分大小写,请记住在加载列表时转换为小写,当然在搜索之前将前缀转换为小写。