修剪Java中字符串的可能前缀

修剪Java中字符串的可能前缀,java,regex,string,Java,Regex,String,我有字符串str,我想从中提取子字符串,不包括可能的前缀“abc” 首先想到的解决方案是: if (str.startsWith("abc")) return str.substring("abc".length()); return str; 我的问题是: if (str.startsWith("abc")) return str.substring("abc".length()); return str; 是否有一种“更干净”的方法可以使用split和“abc”前缀的正则

我有
字符串str
,我想从中提取子字符串,不包括可能的前缀
“abc”

首先想到的解决方案是:

if (str.startsWith("abc"))
    return str.substring("abc".length());
return str;
我的问题是:

if (str.startsWith("abc"))
    return str.substring("abc".length());
return str;
  • 是否有一种“更干净”的方法可以使用
    split
    “abc”
    前缀的正则表达式来执行此操作

  • 如果是,它是否比上面的方法效率低(因为它搜索整个字符串)

  • 如果是,是否有更好的方法(其中“更好的方法”=干净高效的解决方案)

  • 请注意,
    “abc”
    前缀可能出现在字符串的其他位置,不应删除


    谢谢

    比上面短的代码将是这一行:

    return str.replaceFirst("^abc", "");
    
    但就性能而言,我想两种代码之间不会有任何实质性的差异。一个使用正则表达式,一个不使用正则表达式,但使用搜索和子字符串

  • 使用可以做到这一点,但它不是更好的解决方案。事实上,它将是模糊的,我不建议使用它的目的
  • 在这种情况下,不要在效率上浪费时间,这并不重要,只关注逻辑性和清晰性。但是请注意,使用regex通常比较慢,因为它涉及额外的操作,所以您可能希望保持
    startsWith
  • 如果您想检查字符串是否以“abc”开头,那么您的方法很好,它就是为此而设计的

  • 您可以轻松地测量代码运行所需的时间。以下是您可以做的:

    创建一个大循环,在其中,您可以将其计数器附加到某个伪字符串,以模拟要检查的字符串,然后尝试使用
    startsWith
    启动一次,然后在以下操作之后使用
    replaceAll

    for(int i = 0;i<900000;i++) {
        StringBuilder sb = new StringBuilder("abc");
        sb.append(i);
        if(sb.toString().startsWith("abc")) { ... } 
    }
    long time = System.currentTimeMillis() - start;
    System.out.println(time); //Prints ~130
    
    for(inti=0;i试试这个

    str = str.replaceAll("^abc", "");
    

    就效率而言,您可以使用
    StringBuilder
    在一个字符串上执行多个操作,如子字符串、查找索引、子字符串等


    就清洁度/效率而言,可以使用StringUtils(Apache Commons Lang)


    希望有帮助。

    使用
    String。用
    ^abc
    替换first
    (以匹配前导
    abc

    一个不使用正则表达式的解决方案(我之所以需要它,是因为我要删除的字符串是可配置的,并且包含反斜杠,在正则表达式中需要转义以便在文本中使用):

    Apache Commons Lang将使用
    String.startsWith
    String.substring
    str
    的开头删除
    remove

    该方法的主要功能是提供信息:

    public static String removeStart(final String str, final String remove) {
        if (isEmpty(str) || isEmpty(remove)) {
            return str;
        }
        if (str.startsWith(remove)){
            return str.substring(remove.length());
        }
        return str;
    }
    

    如果您关心性能,您可以通过使用相同的预编译前缀
    模式
    来匹配多个字符串,从而改进
    str.replaceFirst(“^abc”,”)
    解决方案

    final Pattern prefix = Pattern.compile("^abc"); // Could be static constant etc
    for ... {
        final String result = prefix.matcher(str).replaceFirst("");
    }
    

    我想如果你从很多字符串中去掉相同的前缀,差别会很明显。

    谢谢,但我没有描述我使用此方法的整个上下文,因此我不认为你可以声称我不应该“在这种情况下浪费时间提高效率”。这里有几个答案建议
    str.replaceFirst(^abc)“,”)
    。这会相当有效吗?@barakmanos您计划使用多少字符串?10000000000(需要再添加几个0才能添加此注释,但仍然有很多)谢谢
    ᴍaroun
    。它应该是
    replaceFirst
    ,而不是
    replaceAll
    。此外,请注意,
    startsWith(…)
    的任何使用都必须后跟
    子字符串(…)
    length()
    ,您在上面的测试中没有考虑到这一点。我将发布一个关于
    replaceFirst
    性能的单独问题,并查看答案(尽管我可能会使用您在上面的建议来经验性地断言这一点)。如果字符串类似于“123abcxyz”`它将变成
    “123xyz”
    如果是这种情况,那么此解决方案对我不起作用。您对
    “abc”不同职位的预期输出是什么
    ?我已经稍微编辑了正则表达式,以确保
    abc
    从开头剥离,否则字符串将保持不变。如果字符串由于锚的存在而没有以
    abc
    开头,它将立即停止。^这将只“切断”前缀
    “abc”
    ,如果存在这样一个?^使其在开始时仅与abc匹配
    “123abc456”如何。replaceFirst(^abc),“)
    ?是否将
    replaceFirst
    进行“彻底搜索”,或者它会立即停止,因为
    “^”
    ?@barakmanos,
    ^
    只在输入字符串的开头匹配。我没有检查
    replaceFirst
    ;我不确定它是否会进行彻底搜索,但我想不会。担心“效率”在这里是相当愚蠢的,除非你试图每X执行数百万次,这是瓶颈。你的代码,按原样,读起来很好并传达了意图。我的前缀包含下划线,我真的不喜欢使用双反斜杠来转义。第一个反斜杠用于Java编译器,第二个反斜杠用于Regexp编译器。
    final Pattern prefix = Pattern.compile("^abc"); // Could be static constant etc
    for ... {
        final String result = prefix.matcher(str).replaceFirst("");
    }