【问题标题】:String.split() *not* on regular expression?String.split() *not* 在正则表达式上?
【发布时间】:2011-09-16 11:21:03
【问题描述】:

由于String.split() 与正则表达式一起使用,所以这个 sn-p:

String s = "str?str?argh";
s.split("r?");

...产生:[, s, t, , ?, s, t, , ?, a, , g, h]

r? 序列上拆分此字符串以生成[st, st, argh] 的最优雅方法是什么?

编辑:我知道我可以逃避有问题的?。问题是我不知道分隔符,而且我不想通过编写 escapeGenericRegex() 函数来解决这个问题。

【问题讨论】:

标签: java regex


【解决方案1】:

转义?

s.split("r\\?");

【讨论】:

  • 问了一个更通用的解决方案
【解决方案2】:

你可以使用

StringUtils.split("?r")

来自commons-lang

【讨论】:

  • StringUtils.split() 应该比 String.split() 快得多,因为 StringUtils.split 使用线性扫描分隔符,而 String.split() 使用正则表达式,这真的很慢
  • 需要注意的一点 - 根据 JavaDoc,这会将相邻的分隔符视为一个分隔符。在我的情况下,这是不希望的
  • 请注意,它接受要拆分的 字符 列表,而不是字符串。所以这会在?r的实例上拆分字符串,而不是r?的实例
  • 没有引用我们要拆分的字符串,s?
  • 这缺少第一个参数,而且无论如何也不会产生所需的输出。它拆分每个字符,而不是整个字符串。使用StringUtils.splitByWholeSeparator(s, "r?")
【解决方案3】:

试试

String s = "str?str?argh";
s.split("r\?");

【讨论】:

    【解决方案4】:

    仅使用 Java SE API 的一般解决方案是:

    String separator = ...
    s.split(Pattern.quote(separator));
    

    quote 方法返回一个正则表达式,它将作为文字匹配参数字符串。

    【讨论】:

      【解决方案5】:

      使用Guava Splitter:

      从输入字符串中提取不重叠的子字符串,通常通过识别分隔符序列的出现。此分隔符可以指定为单个字符、固定字符串、正则表达式或 CharMatcher 实例。或者,完全不使用分隔符,拆分器可以提取给定固定长度的相邻子字符串。

      【讨论】:

        【解决方案6】:

        这也很完美:

        public static List<String> splitNonRegex(String input, String delim)
        {
            List<String> l = new ArrayList<String>();
            int offset = 0;
        
            while (true)
            {
                int index = input.indexOf(delim, offset);
                if (index == -1)
                {
                    l.add(input.substring(offset));
                    return l;
                } else
                {
                    l.add(input.substring(offset, index));
                    offset = (index + delim.length());
                }
            }
        }
        

        【讨论】:

        • 此解决方案的性能并不理想,因为它会创建临时子字符串。
        • @BladeCoder:你是对的。我修好了 :) (当我写这篇文章时,我想我一定是 16 岁)
        • 确实好多了:)
        • 我有一个经常拆分的应用程序(和测试),我不需要对正则表达式进行单个拆分。 Android-Studio 一直在抱怨我的正则表达式(我不需要)不是有效的预编译模式。我将使用它,而不是在循环内的生产代码中使用它。谢谢!
        【解决方案7】:
        String[] strs = str.split(Pattern.quote("r?"));
        

        【讨论】:

          【解决方案8】:

          直接使用 Pattern 类,可以将表达式定义为 LITERAL,在这种情况下,表达式将按原样计算(不是正则表达式)。

          Pattern.compile(<literalExpression>, Pattern.LITERAL).split(<stringToBeSplitted>);
          

          示例:

          String[] result = Pattern.compile("r?", Pattern.LITERAL).split("str?str?argh");
          

          结果:

          [st, st, argh]
          

          【讨论】:

          • 如果您解释了您的代码,您的答案将是最好的。它对于将来搜索类似内容的新用户也将更加有用。
          • 我认为Pattern.quote(...) 是一个更好的解决方案。当然是更少的字符:-)
          • 性能应该没有差别。他们会在幕后做同样的事情。
          • 我必须同意你的看法。从理论上讲,LITERAL 应该比评估正则表达式更高效,但我用 java 8 做了一个小测试,对于某些输入,LITERAL 比 QUOTE 最好,但对于其他输入则相反。结论:目前在性能上没有相关差异。
          【解决方案9】:

          org.apache.commons.lang.StringUtils 具有无需昂贵的正则表达式即可拆分字符串的方法。

          请务必仔细阅读 javadocs,因为其行为可能很微妙。 StringUtils.split(如另一个答案)不符合规定的要求。请改用StringUtils.splitByWholeSeparator

          String s = "str?str?argh";
          
          StringUtils.split(s, "r?");                   //[st, st, a, gh]
          StringUtils.splitByWholeSeparator(s, "r?");   //[st, st, argh]
          

          【讨论】:

            猜你喜欢
            • 2012-04-09
            • 1970-01-01
            • 2015-05-02
            • 1970-01-01
            • 2022-12-17
            • 2019-03-30
            • 2013-10-07
            • 1970-01-01
            • 2015-03-04
            相关资源
            最近更新 更多