文章目录
字符串
版本历史:最早出的是String,然后是StringBuffer(线程安全),然后是StringBuilder(非线程安全)
不可变的String
Strings are constant(是字符串常量)
常用方法:
- length
- charAt(int index):获取指定下标的char
- toLowerCase,toUpperCase:转小写,转大写
- String.valueOf():有很多重载,能够返回表示参数内容的String
使用场景
- 简单字符串操作
优缺点
- 产生大量中间对象,速度慢
StringBuilder
a mutable sequence of characters(可变字符串),非线程安全
常用方法
- append方法,里面放一个字符串就好,别再做字符串拼接
- toString,将StringBuilder转成String
使用场景
- 在为一个类重写toString方法时,如果字符串操作比较简单,则可以直接用“+”进行拼接,如果需要使用循环则是使用StringBuilder
- 多次修改字符串且有速度要求时使用
优缺点
- 速度快
- 线程不安全
什么时候会调用toString?
- 就是当this要转换成String的时候,如做字符串拼接的时候,“hello world"+this
- 还有打印的时候
StringBuffer
A thread-safe, mutable sequence of characters(线程安全的可变字符串)
常用方法:
- 也是append,toString方法
使用场景:
- 多次修改字符串且需要线程安全时使用
优缺点
- 线程安全
- 速度较慢
Formatter
格式化打印可通过java.util.Formatter类来提供
构造器
- new Formatter(System.out),往构造器传参表示把结果输出到哪里
格式化字符串
格式化说明符
%[arg_index$][flags][width][.precision]conversion
其中flags中“-”表示左对齐,默认右对齐,width是宽度,而precision是精度
而precision作用于字符串时表示显示的字符的最大数量,宽度设置这么大有什么用,我不显示,哈哈
常用方法:
- formatter.format(),直接会打印结果
正则表达式
为什么需要正则?
- 正则表达式可用来定义文本查找,替换的规则
正则表达式工具
- matches():需要完全匹配才返回true
- split():将字符串从正则表达式匹配的地方开始切割,默认是空格
- replaceFirst():第一个匹配的地方替换
- replace():仅支持字符和字符串替换(不支持正则)
- replaceAll():基于正则的字符串替换
public class RegularExpress {
public static void main(String[] args) {
String s = "this is test";
System.out.println(s.matches("this is test"));//最简单的匹配表达式,
System.out.println(s.matches("this\\s+is\\s+test"));//匹配一个或多个空格
String s1 = "afa1.51abc";
System.out.println(s1.matches(".*\\d+\\.\\d+.*"));//判断里面是否有浮点数
}
}
public class RegularExpress {
public static void main(String[] args) {
String s = "hello,world,!";
System.out.println(Arrays.toString(s.split(",")));//[hello, world, !]
System.out.println(s.replace(","," "));//hello world !
String s1 = "1hello22world333!";
System.out.println(s1.replaceFirst("\\d+"," "));//hello22world333!
System.out.println(s1.replaceAll("\\d+"," "));// hello world !
}
}
字符类
常见的几个字符类(口诀:问新疆 ?*+,点任何.)
- . 表示匹配除换行符之外的任何单个字符,你要匹配字符,要用\S\s来
- \s表示空白符(如空格,tab,换行,换页,回车),\S则是非空白符
- \d是数字[0-9],\D则是非数字
- \w是词字符[a-zA-Z0-9](即字母数字下划线),\W是非词字符
- [],方括号表示“或”的意思,与|作用相同,在[]中,点号失去作用,变成普通的小数点了,|也变成普通的竖线了
修饰匹配次数的符号
-
?表示零次或一次匹配前面的字符或表达式,如{0,1}
-
*表示零次或多次匹配前面的字符或表达式,如{0,}
-
+表示一次或多次匹配前面的字符或表达式,如{1,}
-
{n}表示匹配正好匹配n次
-
{n,}表示匹配至少匹配n次
-
{n,m}表示匹配在n,m次之间
-
? 发在匹配次数后面是指明是“懒惰模式”
-
-,中划线表示范围,如2-8
-
^表示除什么外的
选择符和分组
- 用|来表示分支
- 用()来组织结构,来分组
匹配模式
- 忽略大小写
- 单行模式
- 多行模式
逻辑操作符
- XY 即Y在X后面
- X|Y即X或Y
- (X)即捕获组
边界匹配符
它是零宽的,故他是匹配位置,而非字符的
- ^ 一行的起始,$一行的结束,\b表示词边界(即找这样一个位置,他前面的字符与后面的字符不全是\w,即换个要换个单词了,故称词边界),\B表示非词边界(则是要在同个单词内,只要是用字母数字下划线连在一起就是同个单词内)
量词
贪婪型(最大匹配模式)
贪婪型(最小匹配模式)
独占型(全部匹配模式)
原文链接:https://blog.csdn.net/renfufei/article/details/79029624
组
- 使用圆括号来分割组
Pattern和Matcher
Pattern表示一个正则表达式的编译表示,要通过调用Pattern.compile(regx),生成一个Pattern对象
Matcher是对字符串进行操作的引擎,Pattern.matcher则是生成一个matcher对象
常用方法:
- matcher对象的常用方法
- find():相当于迭代器的hasNext方法
- group():返回上次匹配的子字符串
- start(),end():返回上次匹配的开始,结束+1的下标
public class RegularExpress {
public static void main(String[] args) {
Formatter formatter = new Formatter(System.out);
Matcher m = Pattern.compile("\\w+").matcher("Evening is full of the light of planets");
while (m.find()) {
formatter.format("%-10.10s at the positions \t%s-%s\n",m.group(),m.start(),m.end()-1);
}
}
}
/* output */
Evening at the positions 0-6
is at the positions 8-9
full at the positions 11-14
of at the positions 16-17
the at the positions 19-21
light at the positions 23-27
of at the positions 29-30
planets at the positions 32-38
扫描输入Scanner
为什么需要Scanner?
- 之前的扫描输入需要读取一行文本然后进行分割,转换类型,才能得到切确的类型,Scanner解决了这个问题:他可以直接得到切确的类型
构造器
- new Scanner(),可以传入任何输入对象,如File,Reader
public class ScannerTest {
public static void main(String[] args) {
System.out.println("how old are you? what is your favorite double");
System.out.println("(input:<age><double>");
Scanner scanner = new Scanner(System.in);
int age = scanner.nextInt();
double favorite = scanner.nextDouble();
System.out.println("in 5 years you will\t"+(age+5));
System.out.println("you favorite double is\t"+favorite);
}
}
/* output */
how old are you? what is your favorite double
input:<age><double>
22
1.3
in 5 years you will 27
you favorite double is 1.3
scanner的分界符
默认是空格,也可以可以设置成自定义的
public class ScannerDelimiter {
public static void main(String[] args) {
Scanner scanner = new Scanner("1,2, 3 , 4 ,5");
scanner.useDelimiter("\\s*,\\s*");
while (scanner.hasNext()) {
System.out.println(scanner.nextInt());
}
}
}
使用正则进行扫描
public class ScannerDelimiter {
public static void main(String[] args) {
//模拟扫描录入文本
Scanner s =new Scanner(
"192.168.0.1@11/02/2020\n" +
"192.168.0.2@11/02/2020\n\t" +
"192.168.0.3@11/02/2020\n\t" +
"192.168.0.4@11/02/2020\n\t" +
"192.168.0.5@11/02/2020\n\t" );
String pattern="(\\d+[.]\\d+[.]\\d+[.]\\d+)@(\\d{2}/\\d{2}/\\d{4})";
while (s.hasNext(pattern)) {//没想到hasNext和next都要用上pattern
s.next(pattern);
MatchResult match = s.match();
String ip=match.group(1);//用上了分组
String time=match.group(2);
System.out.println("ip: "+ip+"\ttime: "+time
+"\t--positions:"+match.start()
+"--"+(match.end()-1));
}
}
}
注意
哪些放栈里面,哪些东西放堆里,方法区?哪些东西放对象池里面?哪些东西放常量池里?
- 常量池是独立于栈和堆的内存内存空间,相同内容的在常量池只有一份
- 基本数据类型,对象的引用都在栈里面
- new出来的对象都是存储在堆中
- 类的加载信息,常量池,静态域都是放在方法区
- String是特殊的引用类型,直接用 =“ ”; 创建的数据都是放常量池,除非用new创建的就会另外申请
- Byte,Short,Integer,Long,Character这5种整型的包装类只是在对应值小于等于127时才可使用对象池,超过127会自动申请空间创建对象,放在堆中,