字符串


字符串操作是计算机程序设计中最常见的行为。由其是在Java大展拳脚的Web系统中更是如此。


一、不可变String

1.String对象是不可变的,每当把String对象作为方法的参数时,都会复制一份拷贝,而该引用所指的对象其实一直待在单一的物理地址上,从未改变。

String q = "howdy";
String qq = q.toUpperCase();

2.为String对象重载的==“+”与“+=”==操作符是Java中仅有的两个重载过的操作符,而Java不允许程序员重载任何操作符。
String的不变性带来一定的效率问题。因为操作多次后就会产生很多垃圾(实际的情况是编译器在编译时会自作主张地使用StringBuilder的append方法,但是性能还是有影响)。所以就有了StringBuffer和StringBuilder。因为StringBuilder只需要生成一个对象,还可以指定其大小,

public class Immutable {
    public static Random random = new Random(47);
    public String toString(){
        StringBuilder sb = new StringBuilder("[");
        for (int i = 0; i < 25; i++) {
            sb.append(random.nextInt(100));
            sb.append(",");
        }
        sb.delete(sb.length() - 1, sb.length());
        sb.append("]");
        return sb.toString();
    }

    public static void main(String[] args) {
        Immutable imu = new Immutable();
        System.out.println(imu);
    }
}
/*
[58,55,93,61,61,29,68,0,22,7,88,28,51,89,9,78,98,61,20,58,16,40,11,22,4]
 */

贴上输出是因为它的值是不变的,不变的原因见这里

https://blog.csdn.net/zhang41228/article/details/77069734

StringBuilder提供了丰富而全面的方法,包括insert(),replace(),substring(),reverse()。但是最常用的还是append()和toString(),delete()。

3.无意识的递归

public class Infinite {
    public String toString(){
        /*
        此处infinite类型会自动转换为String类型。因为编译器看到一个String对象(不变性)后面跟着一个”+“运算符,而在后面的对象不是String,于是编译器
        试着将this转换成一个String,此处调用了this上的toString(),于是发生了递归调用。此处应该用Object.toString(),不该用this,而是super.toString()
         */
        return "Infinite address:" + this + "\n";
//        return "Infinite address:" + super.toString() + "\n";
    }

    public static void main(String[] args) {
        List<Infinite> v = new ArrayList<>();
        
        for (int i = 0; i < 10; i++) {
            v.add(new Infinite());
        }
        System.out.println(v);
    }
}

当创建了Infinite对象并将其打印出来的时候,你会得到一串非常长的异常,问题出现在它的toString()中。

二、正则表达式

1.基础

正则表达式是一种强大而灵活的文本处理工具。==使用正则表达式,我们能够以编程的形式,构造复杂的文本模式,并对输入的字符串进行搜索。一旦找到了匹配这些模式的部分,你就能随心所欲地对它们进行处理。==正则表达式提供了一种完全通用的方式,能够解决各种字符串处理相关的问题:匹配、选择、编辑以及验证。

在正则表达式中,用\d表示一位数字。在其他语言中,\表示“我想要在正则表达式中插入一个普通的反斜线,请不要给它任何特殊的意义”,而在Java中,\的意思是“我要插入一个正则表达式的斜线,所以其后的字符具有特殊的意义。”如:表示一个数字正则应该是\d;如果插入一个普通的反斜杠应该是\\。不过换行和制表符之类的东西只需:\n\t。
要表示“一个或多个之前的表达式”,应该使用“+”。表示“可能有一个负号,后面跟着一位或多位数字”,可以这样:-?\d+
应用正则表达式最简单的途径,就是利用String类内建的功能,例如:你可以检查一个String是都匹配如上表达式。

public class IntegerMarch {
    public static void main(String[] args) {
        System.out.println("-1234".matches("-?\\d+"));
        System.out.println("5678".matches("-?\\d+"));
        System.out.println("+911".matches("-?\\d+"));
        System.out.println("+911".matches("(-|\\+)?\\d+"));
    }
}
/*输出
true
true
false
true
 */

前两个字符串满足表达式,匹配成功。第三个字符串开头有一个+,它也是一个合法的整数,但却与表达式不匹配。在第四组中的表达式,括号有着将表达式分组的效果,而竖线|则表示或操作。

String类还自带了一个非常有用的正则表达式–split()。==其功能是将字符串从正则表达式匹配的地方切开。==String.split()还有一个重载的版本,它允许你限制字符串分割的次数。
split(" “); //按空格划分字符串
split(”\W+"); // \W的意思是非单词字符(如果W小写,\w:则表示一个单词字符)。
split(“n\W+”); //字母’n’后面跟着一个或多个非单词字符

String类自带的最后一个正则表达式工具是替换。

String s = "found banana full";
s.replaceFirst("f\\w+',"located");//它要匹配的是以字母f开头,后面跟一个或多个字母,并且只替换第一个匹配的部分
s.replaceAll("banana|apple|pee","banana");//它要匹配的是三个单词中的任意一个,竖线是或,但是要替换与所有匹配的部分。

如果不是只使用一次的话,非String对象的正则表达式明显具备更佳的性能。

2.正则表达式子集

我们首先从可能存在的构造集中选取一个很有用的子集
正则表达式
正则表达式特别适合替换文本,它提供了很多方法:

  • replaceFirst(String regex, String replacement) 以参数字符串replacement替换掉regex中第一个匹配成功的部分。
  • replaceAll(String regex, String replacement)以参数字符串替换掉所有匹配的部分。
  • appendReplacement(StringBuffer sbuf, String replacement)以渐进式的替换,这是一个非常重要的方法,它允许你调用其他方法生成或处理replacement(replaceFirst和replaceAll只能使用一个固定的字符串),使你能以编程的方式将目标分割成组,从而具备更强大的替换功能。
  • appendTail(StringBuffer sbuf):在执行了一次或多次appendReplacement()之后,调用此方法可以将输入字符串余下的部分复制到sbuf中
public class replacements {
    public static void main(String[] args) {
        String s = "/*! Here's a block of text to use as input to\n" +
                "    the regular expression matcher. Note that we'll\n" +
                "    first extract the block of text by looking for\n" +
                "    the special delimiters, then process the\n" +
                "    extracted block. !*/";
        // Match the specially commented block of text above:
        Matcher mInput = Pattern.compile("/\\*!(.*)!\\*/", Pattern.DOTALL).matcher(s);
        if(mInput.find())
            s = mInput.group(1); // Captured by parentheses
        // Replace two or more spaces with a single space:
        s = s.replaceAll(" {2,}", " ");
        // Replace one or more spaces at the beginning of each
        // line with no spaces. Must enable MULTILINE mode:
        s = s.replaceAll("(?m)^ +", "");
        System.out.println(s);
        s = s.replaceFirst("[aeiou]", "(VOWEL1)");

        StringBuffer sbuf = new StringBuffer();
        Pattern p = Pattern.compile("[aeiou]");
        Matcher m = p.matcher(s);
        // Process the find information as you
        // perform the replacements:
        while(m.find())
            m.appendReplacement(sbuf, m.group().toUpperCase());
        // Put in the remainder of the text:
        m.appendTail(sbuf);
        System.out.println(sbuf);
    }
}
/*输出
Here's a block of text to use as input to
the regular expression matcher. Note that we'll
first extract the block of text by looking for
the special delimiters, then process the
extracted block. 
H(VOWEL1)rE's A blOck Of tExt tO UsE As InpUt tO
thE rEgUlAr ExprEssIOn mAtchEr. NOtE thAt wE'll
fIrst ExtrAct thE blOck Of tExt by lOOkIng fOr
thE spEcIAl dElImItErs, thEn prOcEss thE
ExtrActEd blOck. 
 */

总结

以上内容整理于thinking in java。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值