因为循环很慢

时间:2014-04-04 15:33:29

标签: java performance for-loop arraylist hashmap

请查看以下代码

private StringBuffer populateStringWithUnmatchingWords(ArrayList<String>unmatchingWordsHolder)
    {
        StringBuffer unMatchingWordsStr = new StringBuffer("");

        for(int u=0;u<unmatchingWordsHolder.size();u++)
        {
             Iterator iterInWordMap = wordMap.entrySet().iterator();

             while(iterInWordMap.hasNext())
             {
                 Map.Entry mEntry = (Map.Entry)iterInWordMap.next();

                 if(mEntry.getValue().equals(unmatchingWordsHolder.get(u)))
                 {
                       //out.println(matchingWords.get(m)+" : "+true);
                       unMatchingWordsStr.append(mEntry.getKey());
                       unMatchingWordsStr.append(",");
                 }
              }
        }

        return unMatchingWordsStr;
    }

for loop需要8387毫秒才能完成。 unmatchingWordsHolder也很大。 wordMap是一个HashMap,并且包含大约5000个元素。

此循环将搜索unmatchingWordsHolderwordMap中的元素是否可用。如果它们可用,则会将它们加载到unMatchingWordsStr

我有什么方法可以加快这个任务吗?

3 个答案:

答案 0 :(得分:1)

使用Collection.contains()有帮助吗?如果没别的话,那会更具可读性。这取决于ListMap的相对大小,因为最简单的方法就是这样,尽管因为你在Map上进行迭代并且正在进行List上的查询,如果Map远远大于List,那么这不是理想的:

private StringBuffer populateStringWithUnmatchingWords(ArrayList<String>unmatchingWordsHolder) {
    StringBuffer unMatchingWordsStr = new StringBuffer();

    for (Entry<String, String> entry : wordMap.entrySet()) {
        if(unmatchingWordsHolder.contains(entry.getValue())) {
            //out.println(matchingWords.get(m)+" : "+true);
            unMatchingWordsStr.append(entry.getKey());
            unMatchingWordsStr.append(",");      
        }
    }
    return unMatchingWordsStr;
}

如其他地方所述,如果您不需要线程安全StringBuilder is generally preferred to StringBuffer,但我不想弄乱您的方法签名。

答案 1 :(得分:1)

您正在遍历Map中的每个元素。更好的方法是使用HashMap并使用contains()来确定它是否存在于HashMap中。

答案 2 :(得分:0)

不确定我是否正确地得到了您的问题陈述,但是如果您想要返回逗号分隔的字符串,其中包含在另一组单词中找到的所有单词,那么您将如何在Java 8中执行此操作:< / p>

private String populateContainedWords(List<String> words, Set<String> wordSet)
{
  StringJoiner joiner = new StringJoiner(", ");

  words.stream().filter(wordSet::contains).forEach(joiner::add);

  return joiner.toString();
}

如果您只想在此逗号分隔字符串中使用不同的单词,请使用以下方法:

private String populateDistinctlyContainedWords(List<String> words, Set<String> wordSet)
{
  StringJoiner joiner = new StringJoiner(", ");

  words.stream().distinct().filter(wordSet::contains).forEach(joiner::add);

  return joiner.toString();
}

如果你想要一个逗号分隔的words列表中的字符串未包含在wordSet中,那么这里是如何完成的:

private String populateDisjointWords(List<String> words, Set<String> wordSet)
{
  StringJoiner joiner = new StringJoiner(", ");

  words.stream().filter(n -> !wordSet.contains(n)).forEach(joiner::add);

  return joiner.toString();
}