查找String值的最快方法

时间:2011-09-19 10:12:13

标签: java string data-structures comparison

我有一个简单的应用程序,它从大文本文件中读取小字符串中的数据并将它们保存到数据库中。为了实际保存每个这样的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”慢。

5 个答案:

答案 0 :(得分:5)

使用HashSet,以小写形式存储值及其contains()方法,该方法具有比TreeSet更好的查找性能(包含的常量时间与对数时间)。

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实现的全速和零集合相关代码(例如,Collat​​or,Comparator等)。

<强> EDITED
感谢Jon Skeet指出某些土耳其字符在调用toLowerCase()时表现得很奇怪,但如果您不打算支持土耳其语输入(或者其他语言可能存在非标准案例问题),那么这种方法很有效为了你。

答案 1 :(得分:2)

在大多数情况下,我通常以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));
}

很好有一种方法可以存储所有被忽略值的校对键,但是在测试时避免创建新的校对键,但我不知道这样做的方法。

答案 2 :(得分:1)

将要忽略的单词添加到列表中,然后检查该单词是否在该列表中。

这是动态的。

答案 3 :(得分:1)

如果使用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;
  }
}

答案 4 :(得分:0)

看起来String []比其他提出的方法稍好一些(性能方面),所以我会用它。

就是这样:

public boolean ignore(String value)
{
    for (String ignore:IGNORED_VALUES)
    {
        if (ignore.equalsIgnoreCase(value))
        {
            return true;
        }

        return false;
    }

IGNORED_VALUES对象只是一个String [],其中包含所有被忽略的值。