前言
最近一段时间重读了java编程思想,把一些东西重新理解记录一遍
目的
整理知识点,方便以后回顾,这一章主要讲解了java的字符串
正文
1.字符串
字符串的操作是计算机程序设计中最常见的行为。
关键词: StringBuilder ,StringBuffer,toString(),format转换,正则表达式
2.不可变String
String对象时不可变的。每当把String对象作为方法的参数时,都会复制一份引用。(其实就是对函数中参数列表中参数的操作不会影响外面的原参数)
3.重载“+”与StringBuilder
用于String的“+”与“+=”是Java中仅有的两个重载过的操作符,而Java并不允许程序员重载任何操作符。
在使用"+"操作符时,编译器自动引入了java.lang.StringBuilder类,避免了连加情况下产生大量需要回收的垃圾(每+一次就会产生一个新的字符串)。
因此,当为一个类编写toString()方法时,如果字符串操作简单,可以信赖编译器,它会为你合理的构造最终字符串结果。但是如果要在toString()中使用循环,那么最好自己创建一个StringBuilder对象,结合append()用它来构造最终结果。
StringBuilder提供了丰富而全面的方法,包括insert()、replace()、subString()甚至reverse(),但最常用的还是append()和toString(),delete()方法。
StringBuilder是Java SE5引入的,在这之前还有Java的StringBuffer。StringBuffer是线程安全的,因此开销会大一些。StringBuilder字符串操作会更快一些。
4.无意识的递归
如果希望toString()方法打印出对象的内存地址,不可以使用this关键字。如果这样写
1 | public String toString() { |
编译器会试图将"+"后面的this转换为String,此时调用toString()函数,导致无穷递归。因此如果想要打印出内存地址,应该调用Object.toString()方法,所以调用super.toString()就可以了
1 | public String toString() { |
结果是:
1 | [ E02_RepairInfinite address: E02_RepairInfinite@3e25a5 |
5.String上的操作
String的一些基本方法:
一、构造函数
1 | String(byte[ ] bytes):通过byte数组构造字符串对象。 |
二、方法
1 | 1. char charAt(int index) :取字符串中的某一个字符,其中的参数index指的是字符串中序数。字符串的序数从0开始到length()-1 。 |
6.格式化的输出
Java SE5推出了格式化输出这一功能。如下:
printf()
printf()并不是用重载的“+”操作符来连接引号内的字符串,而是使用特殊的占位符来表示数据将来的位置。而且它还将插入格式化字符串的参数,以逗号分隔,排成一行。
1 | printf("Row 1: [%d %f]\n", x, y); |
这些占位符称作格式修饰符,它不但说明了插入位置,还说明了插入说明类型的变量,%d表示整数,%f表示浮点数,%s表示字符串。
System.out.format()
Java SE5引入的format方法可用于PrintStream或者PrintWriter对象。其中也包括System.out对象。
format()方法模仿自C的printf(),两者是等价的,以下展示三种方法输出坐标点:
1 | public class SimpleFormat { |
Formatter类
在Java中,所有新的格式化功能都有java.util.Formatter处理。Formatter构造器经过重载可以接受多种输出目的地,最常用的还是PrintStream()\OutputStream和File。
1 | import java.io.*; |
tommy输出到System.out中,terry输出到System.out的一个别名中
格式化说明符
为了在插入数据是控制空格和对齐,需要更加精细的格式修饰符。格式如下:
1 | [argument_index$][flags][width][.precision]conversion |
flags表示左右对齐,默认是右对齐,如果想左对齐就使用“-”标志
with控制最小尺寸(宽度)至少该这么长,不够用空格替代。
在with后面加上"."后面表示精度precision。
用于String(%s)时,表示最多可写的字符数
用于浮点数(%f)表示小数点后面的位数,多了舍入,少了补0,默认是6位
用于整数(%d)时,不可用于整数,会触发异常
1 | import java.util.*; |
Formatter转换
常用的类型转换:
d 整型 (十进制)
c Unicode字符
b Boolean
sString
f 浮点型 (十进制)
e 浮点型(科学计数)
x 整数 (十六进制)
h 散列码(十六进制)
% 字符"%"
实例:
1 | Formatter f = new Formatter(System.out); |
所有类型变量都可以执行b转换,除了Boolean类型对应相应的true/false,其它的只要参数不为Null,结果永远是true。(参数为数字0,仍然是true,这点与C不同)
String.format()
String.format()是一个static方法,它接受与Formatter.format()方法一样的参数,但返回一个String对象。
如下所示:
1 | String.format("(t%d, q%d) %s", transactionID,queryID, message) |
7.正则表达式
正则表达式是一个强大而灵活的文本处理工具。它提供可一种完全通用的方式,能够解决各种字符串处理相关的问题:匹配、选择、编辑和验证。
正则可以切分,替换,判断字符串,通过设定的regex规则。
在Java中,\的意思是“我要插入一个正则表达式的反斜线,所以其后字符含有特殊意义”
1 | \\d 表示一位数字 |
1 | public class IntegerMatch { |
split()方法目标是“将字符串从正则表达式匹配的地方切开”
1 | //: strings/Splitting.java |
String.split()还有个重载版本,允许限制字符串分隔次数。
String类自带“替换”正则表达式
1 | import static net.mindview.util.Print.*; |
创建正则表达式
B字符B
1 | \xhh十六进制值为oxhh的字符 |
字符类:
1 | . 任意字符 |
逻辑操作符:
1 | XY X后面有Y |
边界匹配符:
1 | ^一行的开始 |
量词
量词描述一个模式吸收输入文本的方式:
贪婪型:
贪婪表达式会为所有可能的模式发现尽可能多的匹配。
勉强型:
用问号来指定,这个词量匹配满足模式所需的最少字符数。
占有型:
Java特有。当正则表达式被用于字符串时,它会产生相当多的状态,以便在匹配失败时可以回溯。而“占有的”词量并不保存这些中间状态,因此它们可以防止回溯。
贪婪型 | 勉强型 | 占有型 | 如何匹配 |
---|---|---|---|
X? | X?? | X?+ | 一个或0个X |
X* | X*? | x*+ | 0个或者多个X |
x+ | x+? | X++ | 一个或者多个X |
X{n} | X{n}? | X{n}+ | 恰好n次X |
X{n,} | X{n,}? | X{n,}+ | 至少n次X |
X{n,m} | X{n,m}? | X{n,m}+ | X至少n次,且不超过m次 |
接口CharSequence从CharBuffer、String、StringBuffer、StringBuilder类中抽象出字符序列的一般化定义
1 | interface CharSequence { |
这些类都实现了该接口
Parttern和Matcher
Parttern对象表示编译后的正则表达式。
1、导入java.util.regex包
2、用static Parttern.compile()方法来编译正则表达式。
3、使用已编译的Parttern对象上的matcher()方法,加上一个输入字符串,从而共同构造一个Matcher对象。它有很多功能可用。
1 | //{Args: abcabcabcdefabc "abc+" "(abc)+" "(abc){2,}" } |
使用Matcher上的方法,我们能够判断各种不同类型的匹配是否成功:
1 | boolean matches()判断整个输入字符串是否匹配正则表达式,只有整个输入都匹配正则表达式时才会true |
1 | import java.util.regex.*; |
组
组是用括号划分的正则表达式,组号为0表示整个正则表达式,组号为1表示第一队括号()括起的组,依次类推。
Matcher对象提供了一系列方法
1 | public int groupCount() 返回该匹配器的模式中的分组数目,不包括第0组 |
Pattern标记
Pattern类的compile()方法还有另一个版本,它接受一个标记参数,以调整匹配的行为。
Pattern Pattern.compile(String regex, int flag)
flag来自Pattern类中的常量,常用的有Pattern.CASE_INSENSITIVE,Pattern.MULTILINE, 以及 Pattern.COMMENTS
split()
spilit()方法将输入字符断开成字符串对象数组,断开边界由正则表达式确定。默认情况下是遇到空格切分的
1 | String[] split(CharSequence input) //通过正则表达式分隔input |
1 | import java.util.regex.*; |
替换操作
1 | replaceFirst(String replacement) 用于替换第一个匹配成功的部分为字符串replacement |
reset()
public Matcher reset(); //这个方法将Matcher重置为最初的状态
正则表达式与Java I/O
可以讲正则表达式用于动态字符串,应有两个参数: 文件名和要匹配的正则表达式。 输出:匹配的部分和该部分所在行。
1 | //: strings/JGrep.java |
8.扫描输入
input元素使用类来自java.io。
ReadLine()方法将一行输入转为String对象。
Java SE5新增了Scanner类(java.util.*),可以接受任何类型的输入对象,包括File对象,InputStream、String或者Readable对象。Readable时Java SE5新增的一个接口,具有read()方法。
使用Scanner,所有输入,粉刺,翻译的操作都隐藏在不同类型的next()中,比如nextInt()、nextDouble(),普通的next()方法方法返回下一个String。
所有基本类型都有next()方法,除了char类型,包括BigDecimal和BigInteger。
Scanner还有相应的hasNext方法,用以判断下一个输入分词是否是所需的类型。
Scanner可以自动吞IOException异常。
Scanner定界符
默认情况下,Scanner根据空白字符对输入进行分词,也可以用正则表达式指定定界符,利用函数scanner.useDelimiter(正则表达式)
1 | import java.util.*; |
用正则表达式扫描
除了能够扫描基本类型外,可能还想要扫描自定义的正则表达式。
1 | //: strings/ThreatAnalyzer.java |
配合正则表达式扫描时,只针对下一个输入分词,如果正则表达式中含有定界符,则永远不可能匹配成功
9.StringTokenizer
以前用StringTokenizer来分词,现在基本上已经废弃不用了。
参考资料
https://blog.csdn.net/severusyue/article/details/51784228 severusyue