【问题标题】:issue with contains() to match two stringscontains() 匹配两个字符串的问题
【发布时间】:2015-11-01 07:11:58
【问题描述】:

考虑到我们有一个包含三个单词的String,例如"kids story book",我们将这些单词中的每一个添加到HashMap<String, Integer>中,而字符串部分包含单词,整数部分包含单词在字符串,即 1、2 和 3。还假设有另一个相同类型的 HashMap,它是由一组单词组成的字段。考虑每组单词都有一个共同的整数值作为 ID,表示它们属于一起。我的目标是查看第二个HashMap,以便找到任何包含kidsstorybook 的字符串,然后返回该单词及其唯一整数ID。这是我这样做的代码:

       String keyword="kids story book";
       static HashMap<String, Integer> tempp = new HashMap<>();
       static HashMap<String, Integer> stringToint = new HashMap<>();

                 //File is .txt file which contains some characters at each line
                 FileOutputStream Fcategorize=new FileOutputStream(File,true);

          FileReader inputFile = new FileReader(File);

          BufferedReader bufferReader = new BufferedReader(inputFile);

String line = bufferReader.readLine();


        for(int i = 0; line != null; i++){
        if( header(i).equals(line)){
            while( (line = bufferReader.readLine()) != null && ! Footer(i).equals( line ) )
               {


stringToint.put(line, i);
 }
              }

        }



    StringTokenizer start=new StringTokenizer(keyword);

    for(int i=-1; i<=start.countTokens();i++)
    {
        String temp=start.nextToken();
        tempp.put(temp, i);
    }

    Set<String> fkeys = stringToint.keySet();
    Iterator<String> fit = fkeys.iterator();


    Set<String> Lkeys =tempp.keySet();
    Iterator<String> sit = Lkeys.iterator();


    for(int i=0 ; i<tempp.size() ; i++)
    {
    nextToken=sit.next();
    while (fit.hasNext()){
                    String featurename = fit.next();

               if(featurename.contains(nextToken))
               {

              //Do something
               }

           }

    }

存在三个问题:首先,第一个 HashMap 确实包含所有三个单词,但是如果我使用控制台打印结果,它只会打印匹配 HashMap 的第一项而不是全部三个 (而这三个词还有其他匹配项)。其次,在代码中很明显,我从i=-1 开始循环,这是因为如果我使用i=0,它不会将所有三个字符都添加到HashMap,在这种情况下,单词的顺序String 中的顺序不会与HashMap 中的它们的顺序相同,最后,即使对于HashMap 的第一个位置的项目,它甚至不会返回所有匹配项,由contains() 使用。我手动检查,发现有更多结果要返回,而它没有发生。

【问题讨论】:

  • 请提供一个可运行的小示例来说明您的问题,其中包含有关两个地图的填充方式的代码。

标签: java string contains stringtokenizer


【解决方案1】:

第三个问题是您没有在每个单词搜索时重置 fit 迭代器(在您的代码中,重置意味着初始化一个新的)。 实际上,您每次都需要在 for 循环中初始化它

for(int i=0 ; i<tempp.size() ; i++)
{
    nextToken=sit.next();
    fit = fkeys.iterator();
    while (fit.hasNext()){
         ....

【讨论】:

  • 但我想知道为什么Iterator&lt;String&gt; fit=fkeys.iterator() 没用?我的意思是如果我从中删除=fkeys.iterator(),它仍然可以正常运行。此外,IDE 也会显示Unused assignment 通知。
  • 是的,这是因为在 for 循环中重新初始化它时没有使用它。只需声明变量 Iterator fit;或将其设置为 null :: Iterator fit = null;
  • 但在其他一些情况下,我使用这样的方法,并且在 While 循环之外工作得很好。是不同的东西还是什么?我有点困惑。
  • 你需要初始化一个迭代器,你需要循环使用它。在这里,你有一个 while 循环,如果你没有在 while 循环之前初始化它,迭代器将从它之前的状态继续。总而言之,如果你只需要它一次就可以了,但是,如果你需要它用于独立循环(就像现在的 while 一样),你需要在每次独立循环之前重新初始化它。
  • 你的意思是whilefor的情况是一样的吗?
【解决方案2】:

解决你的第二个问题:你应该存储 start.countTokens();首先进入另一个变量,而不是在每个循环中评估它。因为每次调用 start.nextToken(),start.countTokens() 都会减 1。

编辑:您可以使用 LinkedHashMap 来维护条目添加到地图中的顺序。

HashMap<String, Integer> tempp = new LinkedHashMap<>(); // use LinkedHashMap to maintain order

    String keyword = "kids story book";
    StringTokenizer start = new StringTokenizer(keyword);
    int count = start.countTokens(); // save it to another variable

    for (int i = 0; i < count; i++) {
        String temp = start.nextToken();
        tempp.put(temp, i);
    }

    for (Map.Entry entry : tempp.entrySet()) {
        System.out.println(entry.getKey() + ", " + entry.getValue());
    }
    // gives you
    // kids, 0
    // story, 1
    // book, 2

【讨论】:

  • 但订单仍然是个问题。最后一个是第一位的。虽然有i=2 但出现在HashMap 的开头。为什么呢?顺序是20,然后是1
  • @lonesome HashMap 不会以条目添加到 Map 的方式维护条目的顺序,如果您想保持顺序。使用 LinkedHashMap。我已经更新了我的答案
  • 明白,谢谢。在我仍然没有在一个答案中解决所有问题时获得我的 +1。
猜你喜欢
  • 2011-11-25
  • 2011-11-26
  • 2011-06-15
  • 2016-11-11
  • 2019-12-01
  • 1970-01-01
  • 2019-10-28
  • 2012-12-03
相关资源
最近更新 更多