字符串
从概念上讲,Java字符串就是 Unicode 字符序列。
String e=""; // an empty string
String greeting="Hello";
子串
String类的 substring 方法可以从一个较大的字符串提取出一个子串。例如:
String greeting = "Hello";
String s = greeting.substring(0,3);
创建了一个由字符“ Hel” 组成的字符串。
substring 方法的第二个参数是第一个不想取的位置,(0,3)表示取第0、1、2位,这种方法的优点是可以容易的计算出子串的长度 3-0=3。
拼接
字符串拼接一般有两种办法:
- 字符串 + 字符串
与绝大多数程序设计语言一样,可以用+将两个字符串连接起来,中间没有空格。
当将一个字符串与一个非字符串的值进行拼接时,后者被转换成字符串(任何一个 Java对象都可以转换成字符串)。例如:
int age = 13; String rating = "PG" + age;
rating设置为“ PG13”。
这种特性通常用在输出语句中。例如:
System.out.println("The answer is " + answer);
- join方法
如果需要把多个字符串放在一起,用一个定界符分隔,可以使用静态join方法:
String all=String.join("/","S","M","L","XL");
//all is the string "S/M/L/XL"
join的第一个参数为字符串间的连接符,如需要多个字符串直接连在一起,第一个参数为 “” 即可。
不可变字符串
Java字符串中的字符是不可修改的,所以Java的String类对象成为不可变字符串。
若要将 greeting = "Hello"
变成"Help!"
,不能进行直接修改,可以先取子串再拼接:
greeting = greeting.substring(0,3)+"p!";
Java中不可变字符串的优点:编译器可以让字符串共享。
检测字符串是否相等
可以使用equals方法检测两个字符串是否相等,用法:
s.equals(t)
若字符串s与t相等,返回ture,否则返回false。
s与t可以是字符串变量,也可以是字符串字面量,"Hello".equals(t)
也是合法的。
若想检测两个字符串是否相等而不区分大小写,可以用 equalsIgnoreCase 方法:
"Hello".equalsIgnoreCase("hel1o")
- 一定不要使用 == 运算符检测两个字符串是否相等!
这个运算符只能够确定两个字串 是否放置在同一个位置上。如果字符串放置在同一个位置上,它们必然相等。但是,完全有可能将内容相同的多个字符串的拷贝放置在不同的位置上。
String greeting = "Hello"; //initialize greeting to a string
if (greeting == "Hello")...
// probably true
if (greeting.substring(0, 3) == "Hel")...
// probably false
如果虚拟机始终将相同的字符串共享, 就可以使用 == 运算符检测是否相等。但实际上只有字符串常量是共享的,而 + 或 substring 等操作产生的结果并不是共享的。
空串与Null串
空串
空串是长度为0的字符串,它有自己的字符串长度(0)和内容(空)。
检验一个字符串是否为空串:
if(str.length() == 0)
或
if(str.equals(""))
Null串
String 变量还可以存放一个特殊的值,名为 null, 这表示目前没有任何对象与该变量关联。
检验一个字符串是否为 null:
if(str == null)
- 首先要检查一个字符串是否为 null,在 null 上调用方法会出现错误。
码点与代码单元
大多数的常用 Unicode 字符使用一个代码单元就可以表示,而辅助字符需要一对代码单元表示。
- 返回代码单元数量:
greeting.length()
- 返回码点数量(实际长度):
greeting.codePointCount(0, greeting.length())
- 返回位置n的代码单元:
greeting.charAt(n)
- 返回第i个码点:
greeting.codePointAt(i)
使用 UTF-16 编码表示字符⑪(U+1D546) 需要两个代码单元。调用
char ch = sentence.charAt(1)
返回的不是一个空格,而是⑪的第二个代码单元。
Java的String类中常用的方法
char charAt (int index)
返回给定位置的代码单元。除非对底层的代码单元感兴趣, 否则不需要调用这个方法。int codePointAt(int index)
5.0
返回从给定位置开始的码点。int offsetByCodePoints(int startIndex, int cpCount)
5.0
返回从 startIndex 代码点开始,位移 cpCount 后的码点索引。int compareTo(String other)
按照字典顺序,如果字符串位于 other 之前,返回一个负数;如果字符串位于 other 之后,返回一个正数;如果两个字符串相等,返回 0。IntStream codePoints()
8
将这个字符串的码点作为一个流返回。调用 toArray将它们放在一个数组中。new String(int[] codePoints, int offset, int count)
5.0- 用数组中从 offset 开始的 count 个码点构造一个字符串。
boolean equals(0bject other)
如果字符串与 other 相等, 返回 true。boolean equalsIgnoreCase(String other)
如果字符串与 other 相等 (忽略大小写), 返回 true。boolean startsWith(String prefix)
boolean endsWith(String suffix)
如果字符串以 suffix 开头或结尾, 则返回 true。int indexOf(String str)
int indexOf(String str, int fromIndex)
int indexOf(int cp)
int indexOf(int cp, int fromIndex)
返回与字符串 str 或代码点 cp 匹配的第一个子串的开始位置。这个位置从索引 0 或 fromlndex 开始计算。 如果在原始串中不存在 str, 返回 -1。int lastIndexOf(String str)
Int lastIndexOf(String str, int fromIndex)
int lastindexOf(int cp)
int lastindexOf(int cp, int fromIndex)
返回与字符串 str 或代码点 cp 匹配的最后一个子串的开始位置。这个位置从原始串尾端或 fromIndex 开始计算。int length( )
返回字符串的长度。int codePointCount(int startIndex, int endIndex)
5.0
返回 startIndex 和 endIudex-1 之间的代码点数量。没有配成对的代用字符将计入代码点。String replace(CharSequence oldString,CharSequence newString)
返回一个新字符串。这个字符串用 newString 代替原始字符串中所有的 oldString。可以用 String 或 StringBuilder 对象作为 CharSequence 参数。String substring(int beginIndex)
String substring(int beginIndex, int endIndex)
返回一个新字符串。这个字符串包含原始字符串中从 beginIndex 到串尾或 endIndex-1 的所有代码单元。(构建子串)String toLowerCase( )
String toUpperCase( )
返回一个新字符串。这个字符串将原始字符串中的大写字母改为小写,或者将原始字符串中的所有小写字母改成了大写字母。String trim( )
返回一个新字符串。这个字符串将删除原始字符串头部和尾部的空格。String join(CharSequence delimiter, CharSequence... elements)
8
返回一个新字符串,用给定的定界符连接所有元素。
构建字符串
如果需要用许多小段的字符串构建一个字符串,那么应该按照下列步骤进行。
首先,构建一个空的字符串构建器:
StringBuilder builder = new StringBuilder();
当每次需要添加一部分内容时,就调用 append 方法。
builder.append(ch); // appends a single character
builder.append(str); // appends a string
在需要将 字符串构建器 中的内容构建成字符串时,就调用 toString 方法,将得到一个 String 对象,其中包含了构建器中的字符序列。
String completedString = builder.toString();
Java的StringBuilder类中常用的方法
StringBuilder()
构造一个空的字符串构建器。int length()
返回构建器或缓冲器中的代码单元数量。StringBuilder append(String str)
追加一个字符串并返回 this。StringBuilder append(char c)
追加一个代码单元并返回 this。StringBuilder appendCodePoint(int cp)
追加一个代码点,并将其转换为一个或两个代码单元并返回 this。void setCharAt(int i,char c)
将第 i 个代码单元设置为 c。StringBuilder insert(int offset,String str)
在 offset 位置插入一个字符串并返回 this。StringBuilder insert(int offset,Char c)
在 offset 位置插入一个代码单元并返回 this。StringBuilder delete(1nt startindex,int endlndex)
删除偏移量从 startindex 到 endlndex-1 的代码单元并返回 this。String toString()
返回一个与构建器或缓冲器内容相同的字符串
输入输出
读取输入
Java的输入并没有输出那么简单,要想通过控制台进行输人,首先需要构造一个 Scanner 对象,并与“ 标准输人流 ” System.in 关联。
Scanner in = new Scanner(System.in);
现在,就可以使用 Scanner 类的各种方法实现输入操作了。例如,nextLine方法将输入一行:
String name = in.nextLine();
- 使用 nextLine 方法是因为在输人行中有可能包含空格。
读取一个单词(以空白符作为分隔符):
String firstName = in.next();
读取一个整数:
int age = in.nextInt();
读取一个浮点数:
int age = in.nextDouble();
- 要在程序的最开始添加上一行:
import java.util.*;
Scanner 类定义在 java.util 包中。当使用的类不是定义在基本 java.lang 包中时,一定要使用 import 指示字将相应的包加载进来。
格式化输出
Java SE 5.0 沿用了 C 语言库函数中的 printf 方法。例如,调用
System.out.printf("%8.2f", x);
可以用 8 个字符的宽度和小数点后两个字符的精度打印 x。
在 printf中,可以使用多个参数,例如:
System.out.printf("Hello, %s. Next year, you'll be %d", name, age);
每一个以 %字符开始的格式说明符都用相应的参数替换。所有的转换符:
另外,还可以给出控制格式化输出的各种标志。
可以同时使用多个标志,例如"%,(.2f"。
- 如果想用格式化的方法创建一个字符串,而不输出打印,可以用静态的 String.format 方法:
String message = String.format("Hello, %s. Next year, you'll be %d", name, age);
//Hello, 'name'. Next year, you'll be 'age'
- printf方法中日期与时间的格式化选项,格式包括两个字母,以 t 开始,以表 3-7 中的任意字母结束。 例如:
System.out.printf("%tc", new Date());
这条语句将用下面的格式打印当前的日期和时间:
Mon Feb 09 18:05:19 PST 2015
若想要以不同的格式打印出日期时间的不同部分,可以采用一 个格式化的字符串指出要被格式化的参数索引。索引必须紧跟在 % 后面, 并以 $ 终止。 例如:
System.out.printfC("%1$s %2$tB %2$te, %2$tY", "Due date:", new Date());
打印
Due date: February 9, 2015
还可以选择使用 < 标志它指示前面格式说明中的参数将被再次使用也就是说,下列语句将产生与前面语句同样的输出结果:
System.out.printf("%s %tB %<te, %<tY", "Due date:", new Date());
文件输入与输出
对文件进行读取,需要一个用 File 对象构造一个 Scanner 对象:
Scanner in = new Scanner(Paths.get("myfile.txt"), "UTF-8");
- 如果文件名中包含反斜杠符号,就要记住在每个反斜杠之前再加一个额外的反斜杠:
c:\\mydirectory\\myfile.txt”
- 这里指定的"UTF-8" 在互联网中比较常见。
对文件进行写入,就需要构造一个 PrintWriter 对象。在构造器中,只需要提供文件名:
PrintWriter out = new PrintWriter("myfile.txt", "UTF-8");
- 如果文件不存在,创建该文件。
- 可以像输出到 System.out—样使用 print、 println 以及 printf 命令。
要记住一点:
如果用一个不存在的文件构造一个 Scanner, 或者用一个不能被创建的文件名构造一个 PrintWriter, 那么就会发生异常。
应该告知编译器: 已经知道有可能出现“ 输人 / 输出” 异常。这需要在 main 方法中用 throws 子句标记,如下所示:public static void main(String[] args) throws IOException { Scanner in = new Scanner(Paths.get("myfile.txt"), "UTF-8"); ... }
Java的Scanner类中常用的方法
Scanner (InputStream in)
用给定的输人流创建一个 Scanner 对象。String nextLine( )
读取输入的下一行内容。String next( )
读取输入的下一个单词(以空格作为分隔符)。int nextInt( )
double nextDouble( )
读取并转换下一个表示整数或浮点数的字符序列。boolean hasNext( )
检测输人中是否还有其他单词。boolean hasNextInt( )
boolean hasNextDouble( )
检测是否还有表示整数或浮点数的下一个字符序列。Scanner(File f)
构造一个从给定文件读取数据的 Scanner。Scanner(String data)
构造一个从给定字符串读取数据的 Scanner。