【问题标题】:match array against string in java将数组与java中的字符串匹配
【发布时间】:2009-11-04 08:40:00
【问题描述】:

我正在使用 bufferedreader 读取文件,所以假设我有

line = br.readLine();

我想检查这一行是否包含许多可能的字符串之一(我有一个数组)。我希望能够写出类似的东西:

while (!line.matches(stringArray) { // not sure how to write this conditional
  do something here;
  br.readLine();
}

我对编程和 Java 还很陌生,我的方法正确吗?

【问题讨论】:

    标签: java arrays string match


    【解决方案1】:

    将所有值复制到Set<String>,然后使用contains()

    Set<String> set = new HashSet<String> (Arrays.asList (stringArray));
    while (!set.contains(line)) { ... }
    

    [EDIT] 如果你想知道行的一部分是否包含集合中的字符串,你必须遍历集合。将set.contains(line) 替换为调用:

    public boolean matches(Set<String> set, String line) {
        for (String check: set) {
            if (line.contains(check)) return true;
        }
        return false;
    }
    

    当您使用正则表达式或更复杂的匹配方法时,相应地调整检查。

    [EDIT2] 第三种选择是将数组中的元素与| 连接在一个巨大的正则表达式中:

    Pattern p = Pattern.compile("str1|str2|str3");
    
    while (!p.matcher(line).find()) { // or matches for a whole-string match
        ...
    }
    

    如果数组中有很多元素,这可能会更便宜,因为正则表达式代码会优化匹配过程。

    【讨论】:

    • 如果我错了请纠正我,但这不是检查数组是否包含从文件中读取的行,而不是检查该行是否包含数组中的字符串之一?跨度>
    • Regex 然后依赖于 String 数组的内容。可能被视为安全漏洞,具体取决于您正在检查的条件。
    • @Daniel:没有关于这些数据来自哪里的信息,所以我无法对此发表评论。
    • 感谢大家的意见。我不懂一些语法,所以我有一些阅读要做。
    • 您可以先使用Pattern.quote() 转义文字字符串。
    【解决方案2】:

    这取决于stringArray 是什么。如果是Collection 那就没问题了。如果它是一个真正的数组,您应该将其设为CollectionCollection 接口有一个名为contains() 的方法,它将确定给定的Object 是否在Collection 中。

    将数组转换为Collection的简单方法:

    String tokens[] = { ... }
    List<String> list = Arrays.asList(tokens);
    

    List 的问题是查找成本很高(技术上是线性的或O(n))。更好的选择是使用Set,它是无序的,但具有近乎恒定的 (O(1)) 查找。你可以像这样构造一个:

    来自Collection

    Set<String> set = new HashSet<String>(stringList);
    

    从数组中:

    Set<String> set = new HashSet<String>(Arrays.asList(stringArray));
    

    然后set.contains(line) 将是一个便宜的操作。

    编辑:好的,我认为您的问题不清楚。您想查看该行是否包含数组中的任何单词。那么你想要的是这样的:

    BufferedReader in = null;
    Set<String> words = ... // construct this as per above
    try {
      in = ...
      while ((String line = in.readLine()) != null) {
        for (String word : words) {
          if (line.contains(word)) [
            // do whatever
          }
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      if (in != null) { try { in.close(); } catch (Exception e) { } }
    }
    

    这是一个相当粗略的检查,它的使用出人意料地开放,并且往往会在诸如“废品”之类的词上给出令人讨厌的误报。对于更复杂的解决方案,您可能必须使用正则表达式并查找单词边界:

    Pattern p = Pattern.compile("(?<=\\b)" + word + "(?=\b)");
    Matcher m = p.matcher(line);
    if (m.find() {
      // word found
    }
    

    您可能希望更有效地执行此操作(例如不编译每一行的模式),但这是使用的基本工具。

    【讨论】:

    • 注意正则表达式方法的安全隐患 - 取决于数组中字符串的来源,这可能会破坏正则表达式并允许注入任意条件。
    【解决方案3】:

    使用String.matches(regex) 函数,如何创建一个匹配字符串数组中任意一个字符串的正则表达式?类似的东西

    String regex = "*(";
    for(int i; i < array.length-1; ++i)
      regex += array[i] + "|";
    regex += array[array.length] + ")*";
    while( line.matches(regex) )
    {
      //. . . 
    }
    

    【讨论】:

    • -1 这很容易出错。根据字符串数组的内容,您的正则表达式会发生变化。甚至可以被认为是一个安全漏洞。
    • 该数组从未被声明为静态数组。您如何建议实现一个匹配动态数组且“不变”的正则表达式?
    猜你喜欢
    • 2010-09-20
    • 1970-01-01
    • 2019-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-28
    • 1970-01-01
    • 2015-10-14
    相关资源
    最近更新 更多