Java字符串

String

String对象是不可变的,String类中修改String值的方法实际上都是创建了一个全新的String对象,以包含修改后的字符串内容。而最初的String对象则丝毫未动。

public class Immutable {
	public static String upcase(String s) {
		return s.toUpperCase();
	}
	public static void main(String[] args) {
		String q = "xiangbian";
		System.out.println(q);
		String qq = upcase(q);
		System.out.println(qq);
		System.out.println(q);
	}
}
/*
xiangbian
XIANGBIAN
xiangbian
*/

重载“+”与StringBuilder

用于String的“+”与“+=‘是Java中仅有的两个重载过的操作符,而Java并不允许程序员重载任何操作符。

public class WhitherStringBuilder {
	public static String implicit(String[] fields) {
		String result = "";
		for (int i = 0; i < fields.length; i++) {
			result+=fields[i];
		}
		return result;
	}
	public static String explicit(String[] fields) {
		StringBuilder result = new StringBuilder();
		for (int i = 0; i < fields.length; i++) {
			result.append(fields[i]);
		}
		return result.toString();
	}
	public static void main(String[] args) {
		String[] s = {"1","adfdf","fdf","123131"};
		
		System.out.println(implicit(s));
		System.out.println(explicit(s));
		
	}
}
/*
1adfdffdf123131
1adfdffdf123131
*/

以上两种方法结果一样,实则内部实现不一样。
implicit(String[] fields) 会创建多个StringBuilder对象,而explicit(String[] fields)方法只会生成一个StringBuilder对象。

无意识的递归

String上的操作

方法参数应用
构造器重载版本:默认版本,String,StringBuilder,StringBuffer,char数组,byte数组创建String对象
length()String中字符的个数
charAt()Int索引取得String中该索引位置上的char
getChars(),getBytes()要复制部分的起点和终点的索引,复制的目标数组,目标数组的起始索引复制char或byte到目标数组中
toCharArray()生成一个char[],包含String的所有字符
equals(),equalsIgnoreCase()与之进行比较的String比较两个String的内容是否相同
compareTo()与之进行比较的String按词典顺序比较String的内容,比较结果为负数、零、或正数。注意,大小写并不等价。
contains()要搜索的CharSequence如果该String对象包含参数的内容,则返回true
contentEquals()与之进行比较的CharSequence或StringBuffer如果该String对象与参数的内容完全一致,则返回true
equalsIgnoreCase()与之进行比较的String忽略大小写,如果两个String的内容相同,则返回true
regionMatcher()该String的索引偏移量,另一个String及其索引偏移量,要比较的长度。重载版本增加了”忽略大小写“功能返回boolean结果,以表明所比较区域是否相等
startsWith()可能的起始String。重载版本在参数中增加了偏移量返回boolean结果,以表明该String是否以此参数起始
endsWith()该String可能的后缀String返回boolean结果,以表明此参数是否该字符串的后缀
indexOf(),lastIndexOf()重载版本包括:char,char与起始索引,String,String与起始索引如果该String并不包含此参数,就返回-1,否则返回此参数在String中的起始索引。lastIndexOf()是从后向前搜索
substring() (subSequence())重载版本:起始索引;起始索引+终点坐标返回一个新的String,以包含参数指定的字符串
concat()要连接的String返回一个新的String对象,内容为原始String连上参数String
replace()要替换的字符,用来进行替换的新字符。也可以用一个CharSequence来替换另一个CharSequence返回替换字符后的新String对象。如果没有替换发生,则返回原始的String对象
toLowerCase(),toUpperCase()将字符的大小写改变后,返回一个新String对象。如果没有发生改变,则返回原始的String对象
trim()将String两端的空白字符删除后,返回一个新的String对象。如果没有改变发生,则返回原始的String对象
valueOf()重载版本:Object;char[];char[],偏移量,与字符个数;boolean;char;int;long;float;double返回一个表示参数内容的String
intern()为每个唯一的字符序列生成一个且仅生成一个String引用

从表中可以看出,当需要改变字符串的内容时,String类的方法都会返回一个新的String对象。、
同时,如果内容没有发生改变,String的方法只是返回指向原对象的引用,以节约存储空间和避免额外的开销。

格式化输出

System.out.format()
public class SimpleFormat {
	public static void main(String[] args) {
		int x = 5;
		double y = 3.1415926;
		System.out.println("ROW 1:["+x+" "+y+"]");
		
		System.out.format("Row 1:[%d %f]\n", x,y);
		//or
		System.out.printf("Row 1:[%d %f]\n", x,y);
	}
}

/*
ROW 1:[5 3.1415926]
Row 1:[5 3.141593]
Row 1:[5 3.141593]
*/

format()与printf()是等价的,它们只需要一个简单的格式化字符串,加上一串参数即可,每个参数对应一个格式修饰符。

Formatter类
import java.io.PrintStream;
import java.util.Formatter;

public class Turtle {
	private String name;
	private Formatter f;
	public Turtle(String name,Formatter f){
		this.name = name;
		this.f = f;
	}
	public void move(int x,int y) {
		f.format("%s The Turtle is at (%d,%d)\n", name,x,y);
	}
	public static void main(String[] args) {
		PrintStream outAlias = System.out;
		Turtle tommy = new Turtle("Tommy",new Formatter(System.out));
		Turtle terry = new Turtle("Terry",new Formatter(outAlias));	
		tommy.move(0, 0);
		terry.move(4, 8);
		tommy.move(3, 4);
		terry.move(2, 5);
		tommy.move(3, 3);
		terry.move(3, 3);
	}	
}
/*
Tommy The Turtle is at (0,0)
Terry The Turtle is at (4,8)
Tommy The Turtle is at (3,4)
Terry The Turtle is at (2,5)
Tommy The Turtle is at (3,3)
Terry The Turtle is at (3,3)
*/

所有的tommy都将输出到System.out,而所有的terry则都输出到System.out的一个别名上。
Formatter的构造器经过重载可以接受多种输出目的地,不过最常用的还是PrintStream(),OutputStream和File。

格式化说明符

在插入数据时,如果想要控制空格与对其,你需要更精细复杂的格式修饰符。
抽象语法:

%[argument_index$][flags][width][.precision]conversion

用格式修饰符来打印一个购物收据:

import java.util.*;
public class Receipt {
	private double total = 0;
	private Formatter f = new Formatter(System.out);
	public void printTitle() {
		f.format("%-15s %5s %10s\n", "Item","Qty","Price");
		f.format("%-15s %5s %10s\n", "-------","---","-----");
	}
	public void print(String name,int qty,double price) {
		f.format("%-15.15s %5d %10.2f\n", name,qty,price);
		total+=price;
	}
	public void printTotal() {
		f.format("%-15s %5s %10.2f\n", "Tax"," ",total*0.06);
		f.format("%-15s %5s %10s\n", " "," ","-----");
		f.format("%-15s %5s %10.2f\n", "Total","",total*1.06);
	}
	public static void main(String[] args) {
		Receipt receipt = new Receipt();
		receipt.printTitle();
		receipt.print("Jack's Magic Beans", 4, 4.25);
		receipt.print("Princess Peas", 3, 5.1);
		receipt.print("Three Bears Porridge", 1, 14.29);
		receipt.printTotal();
	}
}
/*
Item              Qty      Price
-------           ---      -----
Jack's Magic Be     4       4.25
Princess Peas       3       5.10
Three Bears Por     1      14.29
Tax                         1.42
                           -----
Total                      25.06
*/
Formatter

常用类型转换字符:

d整数型
cUnicode字符
bBoolean值
sString
f浮点数(十进制)
e浮点数(科学计数)
x整数(十六进制)
h散列码(十六进制)
%字符%

代码示例:

import java.util.*;
public class Conversion {
	public static void main(String[] args) {
		Formatter f = new Formatter(System.out);
		char c = 'a';
		System.out.println("c = 'a'");
		f.format("%%c: %c\n", c);
		f.format("%%s: %s\n", c);
		f.format("%%b: %b\n", c);
		f.format("%%h: %h\n", c);
		//f.format("%%d: %d\n", c);
		f.close();
	}
}
/*
c = 'a'
%c: a
%s: a
%b: true
%h: 61
*/

注意:对于b转换而言,boolean基本类型或Boolean对象以外的其他类型的参数,只要该参数不为null,那转换结果就永远都是true。

String.format()

在String.format()内部,它也是创建一个Formatter对象,然后将你传入的参数转给该Formatter。

public class DatabaseException extends Exception{
	public DatabaseException(int transactionID,int queryID,String message) {
		super(String.format("(t%d,q%d)%s", transactionID,queryID,message));
	}
	public static void main(String[] args) {
		try {
			throw new DatabaseException(3, 7, "Write failed");
		}catch(Exception e) {
			System.out.println(e);
		}
	}
}
/*
DatabaseException: (t3,q7)Write failed
*/

正则表达式

正则表达式是一种强大而灵活的文本处理工具,它提供了一种完全通用的方式,能够解决各种字符串处理相关的问题:匹配、选择、编辑以及验证。

字符:

B指定字符B
\xhh十六进制值为oxhh的字符
\uhhh十六进制表示为oxhhhh的Unicode字符
\t制表符tab
\n换行符
\r回车
\f换页
\e转义(Escape)

字符类:

.任意字符
[abc]包含了a、b和c的任何字符(和a|b|c作用相同)
[^abc]除了a、b和c之外的任何字符(否定)
[a-zA-z]从a到z或从A到Z的任何字符(范围)
[abc[hij]]任意a、b、c、h、i、和j字符(与a|b|c|h|i|j作用相同)(合并)
a-z&&[hij]任意h、i或j(交)
\s空白符(空格、tab、换行、换页和回车)
\S非空白符([^\s])
\d数字[0-9]
\D非数字[0-9]
\w词字符[a-zA-Z0-9]
\W非词字符

逻辑操作符:

XYY跟在X后面
x|yX或Y
(X)捕获组(capturing group)。可以在表达式中用\i引用第i个捕获组

边界匹配符:

^一行的起始
$一行的结束
\b词的边界
\B非词的边界
\G前一个匹配的结束

量词:

  • 贪婪型: 量词总是贪婪的,除非有其他的选项被设置。贪婪表达式会为所有可能的模式发现尽可能多的匹配。导致此问题的一个典型理由就是假定我们的模式仅能匹配第一个可能的字符组,如果他是贪婪的,那么它就会继续往下匹配。
  • 勉强型: 用问号来指定,这个量词匹配满足模式所需的最少字符数。也称懒惰的、匹配的、非贪婪的、不贪婪的。
  • 占有型: 目前这种量词只有在Java语言中可用。当正则表达式被应用与字符串时,他会产生相当多的状态,以便在匹配失败时可以回溯。而“占有型”量词并不保存这些中间状态,因此它们可以防止回溯。它们常常用于防止正则表达式失控,因此可以使正则表达式执行起来更有效。
贪婪型勉强型占有型如何匹配
X?X??X?+一个或零个X
X*X*?X*+零个或多个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次

表达式X通常必须要用圆括号括起来,以便它可以按照我们期望的效果去执行。
例如:

abc+      //这个表达式表示:匹配ab,后面跟随1个或多个c。

要表明匹配一个或多个完整的abc字符串,必须这要表示:

(abc)+         //匹配一个或多个完整的abc字符串
Pattern和Matcher

P300–P305

split()

split()方法将输入字符串断开成字符串对象数组,断开边界由下列正则表达式确定:

String[] split(CharSequence input)
String[] split(CharSequence input,int limit)

按照通用边界断开输入文本:

import java.util.*;
import java.util.regex.Pattern;
public class SplitDemo {
	public static void main(String[] args) {
		String input = "This!!unusual use!!of exclamation!!points";
		System.out.println(Arrays.toString(Pattern.compile("!!").split(input)));
		System.out.println(Arrays.toString(Pattern.compile("!!").split(input,3)));
	}
}
/*
[This, unusual use, of exclamation, points]
[This, unusual use, of exclamation!!points]
*/

第二种形式的split()方法可以限制将输入分割成字符串的数量。

替换操作

P306—P307

reset()

通过reset()方法可以将现有的Matcher对象应用于一个新的字符序列:

import java.util.regex.*;
public class Resetting {
	public static void main(String[] args) throws Exception{
		Matcher m = Pattern.compile("[frb][aiu][gx]").matcher("fix the rug with bags");
		while(m.find()) {
			System.out.print(m.group()+" ");
		}
		System.out.println();
		m.reset("fix the rig with rags");
		while(m.find()) {
			System.out.print(m.group()+" ");
		}
	}
}
/*
fix rug bag 
fix rig rag
*/

使用不带参数的reset()方法,可以将Matcher对象重新设置到当前字符序列的起始位置。

正则表达式与Java I/O

P308

扫描输入

P309-P312

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值