[英]Fastest way to lookup a String value
我有一个简单的应用程序,可以从大型文本文件中读取小字符串中的数据,并将其保存到数据库中。 为了实际保存每个这样的String,应用程序会多次(可能数千次或多次)调用以下方法:
setValue(String value)
{
if (!ignore(value))
{
// Save the value in the database
}
}
当前,我通过依次比较一组字符串来实现ignore()
方法,例如
public boolean ignore(String value)
{
if (value.equalsIgnoreCase("Value 1") || (value.equalsIgnoreCase("Value 2"))
{
return true;
}
return false;
}
但是,由于我需要检查许多将在代码另一部分定义的“可忽略的”值,因此我需要使用数据结构进行此检查,而不是使用多个连续的if
语句。
因此,我的问题是,从标准Java到实现该目标的最快数据结构是什么? HashMap? 一套? 还有吗
初始化时间不是问题,因为它将静态发生,并且每次应用程序调用一次。
编辑:到目前为止,建议的解决方案(包括HashSet)似乎比仅使用String []包含所有被忽略的单词并针对其中每个单词运行“ equalsIgnoreCase”要慢。
使用HashSet (以小写形式存储值)及其contains()方法,该方法具有比TreeSet更好的查找性能(contains时间与log-time相比)。
Set<String> ignored = new HashSet<String>();
ignored.add("value 1"); // store in lowercase
ignored.add("value 2"); // store in lowercase
public boolean ignore(String value) {
return ignored.contains(value.toLowerCase());
}
以小写形式存储值并搜索小写输入避免了在比较期间处理大小写的麻烦,因此您可以获得HashSet实现的全速和要编写的零收集相关代码(例如Collator,Comparator等)。
已编辑
感谢Jon Skeet指出某些土耳其语字符在调用toLowerCase()
时表现toLowerCase()
,但是如果您不打算支持土耳其语输入(或其他不带标准大小写问题的语言),那么这种方法将非常适合您。
在大多数情况下,我通常以HashSet<String>
开头-但是,由于您不区分大小写,因此这会变得有点困难。
您可以尝试使用TreeSet<Object>
使用适当的Collator
来区分大小写。 例如:
Collator collator = Collator.getInstance(Locale.US);
collator.setStrength(Collator.SECONDARY);
TreeSet<Object> set = new TreeSet<Object>(collator);
请注意,您不能创建TreeSet<String>
因为Collator
仅实现Comparator<Object>
。
编辑:虽然上述版本仅适用于字符串,但创建TreeSet<CollationKey>
可能更快:
Collator collator = Collator.getInstance(Locale.US);
collator.setStrength(Collator.SECONDARY);
TreeSet<CollationKey> set = new TreeSet<CollationKey>();
for (String value : valuesToIgnore) {
set.add(collator.getCollationKey(value));
}
然后:
public boolean ignore(String value)
{
return set.contains(collator.getCollationKey(value));
}
这将是不错的存储排序键的所有忽略值的方法,但建议尽量避免进行测试时,创造新的整理键,但我不知道这样做的一种方式。
如果使用Java 7,这是一种快速的方法:
public boolean ignore(String value) {
switch(value.toLowerCase()) { // see comment Jon Skeet
case "lowercased_ignore_value1":
case "lowercased_ignore_value2":
// etc
return true;
default:
return false;
}
}
将要忽略的单词添加到列表中,然后仅检查单词是否在该列表中。
这使其成为动态的。
似乎String [](在性能方面)比其他建议的方法稍好,所以我将使用它。
简直是这样的:
public boolean ignore(String value)
{
for (String ignore:IGNORED_VALUES)
{
if (ignore.equalsIgnoreCase(value))
{
return true;
}
return false;
}
IGNORED_VALUES对象只是一个String [],其中包含所有被忽略的值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.