Java核心技术卷I知识点总结二

 字符串String

 从概念上讲,Java字符串就是Unicode字符序列,例如,字符串“Java\u2122”由5个Unicode字符J a v a 和 ™组成。Java没有内置的字符串类型,而是在标准的Javal类库中提供了一个预定义类,很自然的叫做String。每个用双引号括起来的字符串都是String类的一个实例。

1.拼接

Java语言允许使用+号连接两个字符串

String a = "Expletive";
String b = "delete";
String message = a+b;

 

当一个字符串与一个非字符串的值进行拼接时,后者会变成字符串

int age = 13;
String rating = "PG"+age;

把多个字符串放在一起,用一个界定符分离,可以使用静态join方法

String all = String.join("/","S","M","L","XL");
//all is the string "S/M/L/XL"

在java11中,还提供了repeat方法

String repeated = "Java".repeat(3);
//repeated is "JavaJavaJava"

2.不可变字符串

Java中String类没有提供修改字符串中的某个字符的方法。不可变字符串的优势在于可以实现字符串的共享。各种字符串存放在公共的存储池中,字符串变量指向了存储池中相应的位置。如果复制一个字符串变量,原始字符串和复制的字符串共享相同的字符。

3.检测字符串是否相等

使用equals方法检测两个字符串是相等

s.equals(t)

要想检测两个字符是否相等,而不区分大小写,使用equalsIgnoreCase方法

s.equalsIgnoreCase(t)

一定不要使用==运算符检测 两个字符串是否相等,这个运算符只能确定两个字符是否存放在同一个位置上。如果字符串在同一个位置上,它们必然相等,但是完全有可能将内容相同的多个字符串副本符放在不同位置上。如果虚拟机始终将相同的字符串共享,皆可以使用==运算符检测是否相等。但实际上只有字符串字面量是共享的,而+ 或subString 等操作得到的字符串并不共享。

4.空串与Null串

空串“”是长度为0的字符串。空串是一个Java 对象,有自己的串长度(0)和内容(空)。不过,String变量还是可以存放一个特殊的值,名为null,表示目前没有任何对象与该变量关联。要检查一个字符串是否为null,要使用以下条件:

if(str == null)

有时候要检查一个字符串既不是null,也不是空串要使用一下条件:

if(str != null  &&  str.length()  !=0)

使用&&运算可确保str.length()不会报空指针,因为如果&& 左边为假就不会验证右边的结果。如果使用 & 运算,当左边为假,即str==null,右边的算式就会报空指针的异常。

5.码点与码点单元

Java字符串由char值序列组成。char数据类型是由一个采用UTF-16编码表示Unicode码点的代码单元。最常用的Unicode字符使用一个代码单元就可以表示,而辅助字符需要一对代码单元表示。

//length方法返回采用UTF-16编码表示给定字符串所需的码点单元数量
String greeting  = "Hello";
int n = greeting.length();//is 5
		
//要想得到实际长度,即码点数量 可以调用:
int cpCount = greeting.codePointCount(0, greeting.length());
		
//调用s.charAt(n)将返回位置n的代码单元,n介于0~s.length()-1之间
char first = greeting.charAt(0);//first is 'H'
char last = greeting.charAt(4);//last is 'o'
		
//想要得到第i个码点,应该使用下列语句
int i = 4;
int index = greeting.offsetByCodePoints(0, i);
int  cp = greeting.codePointAt(index);
char a = (char) cp;
System.out.println(a);// a  is 'o'

6.String 常用API

  • char charAt(int index)  ​返回指定位置的代码单元
  • int codePointAt(int  index) 返回从给定位置开始码点
  • int offsetByCodePoints(int startIndex,int cpCount) 返回从startIndex码点开始  cpCount个码点后的码点索引
  • int comparTo(String othre) 按照字典顺序比较每一位字符,如果字符串位于other 之前则返回一个负数,如果字符串位于other之后,返回一个正数;如果两个字符串相等,返回0
  • InStream codePoints() 将这个字符串的码点作为一个流返回,调用toArray将它们放在同一个数组中
  • new String(int [] codePoints, int offset ,int count) 用数组中的offset 开始的count个码点构造一个字符串
  • boolean isEmpty() 此方法只能判断当前字符串的长度是否为0
  • boolean isBlank() 如果字符串为空或者由空格组成,返回true
  • boolean equals(Object other ) 如果字符串与other相等,返回true 说明:通过查看方法源码可以知道,判断当前两个字符串是否相等,首先会判断两个字符串的引用地址是否相等,如果引用地址相等则返回true,如果当前两个字符串的引用地址不相等,则会比较两个字符串中的马点单元是否相等,如果所有的码点单元都相等则返回true。
  • boolean euqalsIgnoreCase(String other) 如果字符串与other相等(忽略大小写),返回true
  • boolean startsWith(String prefix) 如果字符串以prefix开头则返回true
  • boolean endsWidth(String suffix) 如果字符串以suffix 结尾则返回true
  • int  indexOf(String str) 返回与字符串str匹配的第一个子串的开始位置,如果不存在则返回-1
  • int  indexOf(String str,int fromIndex) 返回从索引fromIndex开始与str匹配的第一个子串的开始位置,不存在返回 -1
  • int  indexOf(int cp) 返回与码点cp匹配的第一个子串的开始位置,不存在返回 -1
  • int  indexOf(int  cp,int fromIndex) 返回从索引fromIndex开始与cp匹配的第一个子串的开始位置,不存在返回 -1
  • int lastIndexOf(String str) 返回与字符串str匹配的最后一个子串的开始位置,如果不存在则返回 -1
  • int lastIdnexOf(String str,int fromIndex)  返回从索引fromIndex 开始于str匹配的最后一个子串的开始位置,不存在返回-1
  • int lastIndexOf(int cp) 返回与码点cp匹配的最后一个子串的位置,不存在返回-1
  • int lastIndexOf(int cp,intfomIndex) 返回从索引fromIndex开始与cp匹配的最后一个子串的开始位置,不存在返回 -1
  • int length()   返回字符串代码单元的个数
  • int codePointCount(int startIndex ,int endIndex)  返回startIndex 和endIndex-1之间的码点个数
  • String replace(CharSequence oldString ,CharSequence newString)  返回一个新字符串。这个字符串用newString 代替原始字符串中所有的oldString,可用String 或者StringBuilder ,StringBuffer 对象作为CharSequence
  • String subString(int beginIndex) 返回一个新的字符串,这个字符串从原始字符串beginIndex位置开始的所有代码单元
  • String subString(int beginIndex ,int endIndex) 返回一个新的字符串,这个字符串包含原始字符串从beginIndex到字符串endIndex -1的所有代码单元
  • String toLowerCase()  返回一个新的字符串,这个字符串把原始的字符串中的大写字母改为小写字母
  • String toUpperCase()  返回一个新的字符串,这个字符串把原始的字符串中的小写字母改为大写字母
  • String trim()   返回一个新的字符串,这个字符串删除原始字符串头部和尾部小于等于U+0020的字符
  • String strip()  返回一个新的字符串,这个字符串删除原始字符串中的空格 jdk11新增
  • String join(CharSequence delimiter,CharSequence ...elements) 返回一个字符串用给定的定界符链接所有的元素、
  • String repeat(int count ) 返回一个字符串 ,将当前字符串重复count次

7.构建字符串

有些时候,需要有较短的字符串构建字符串,例如按键或者来自文件的单词,如果使用字符串拼接的方式来达到目的,效率会比较低。因为每次拼接字符串时,都会创建一个新的String对象,即耗时又浪费空间。如果使用StringBuilder类就可以避免这个问题的发生。

通过查看源码来分析为什么SringBuilder拼接字符串能节省空间和时间

//查看append(Objec obj)方法中调用了appen(String str)方法
//String.valueOf(obj) 如果当前obj为null 则返回"null"字符串,返回obj.toString();
public AbstractStringBuilder append(Object obj) {
    return append(String.valueOf(obj));
}



 public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();//如果str为null则拼接"null"字符串
        int len = str.length();
        ensureCapacityInternal(count + len);//确保当前StringBuilder字符数组能放下Str ,如果放不下则进行扩容
        str.getChars(0, len, value, count);//将str中的字符数组数据复制到StringBuilder中
        count += len;//改变当前StringBuilder 的长度
        return this;
 }



private AbstractStringBuilder appendNull() {
        int c = count;
        ensureCapacityInternal(c + 4);
        final char[] value = this.value;
        value[c++] = 'n';
        value[c++] = 'u';
        value[c++] = 'l';
        value[c++] = 'l';
        count = c;
        return this;
}


private void ensureCapacityInternal(int minimumCapacity) {
        // overflow-conscious code
        if (minimumCapacity - value.length > 0) {
            value = Arrays.copyOf(value,
                    newCapacity(minimumCapacity));
        }
}



public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) {
        if (srcBegin < 0) {
            throw new StringIndexOutOfBoundsException(srcBegin);
        }
        if (srcEnd > value.length) {
            throw new StringIndexOutOfBoundsException(srcEnd);
        }
        if (srcBegin > srcEnd) {
            throw new StringIndexOutOfBoundsException(srcEnd - srcBegin);
        }
        System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin);
}

StringBuilder继承自AbstractStringBuilder类, 通过append(Object obj)方法可以看出,拼接的是append(String str)方法。 在append(String str)方法中首先会判断当前str是否为null,如果为null 则通过appendNull()把null“”字符串拼接起来。Stringbuiler每次拼接前都会通过ensureCapacityInternal方法比较当前存储字符数组的长度length 与要拼接的字符长度,如果不够则通过进行扩容。最后通过String的getChars方法把当前的要拼接的字符串复制到StringBuilder的字符数组中。所以SringBuilder 是通过复制字符数组来进行拼接的, 在调用toString()方法之前并没有频繁的创建字符串对象。

8.格式化输出

 每一个以%字符开始的格式说明符都用相应的参数替换。格式说明符尾部的转换符指示要格式化的数值类型:f表示浮点数,s表示字符串,d表示十进制整数。

String  name = "Tom";
int age = 10;
System.out.printf("hello ,%s Next year ,you will be %d",name,age);
//结果为:hello ,Tom Next year ,you will be 10

转换符

转换符类型示例
d十进制整数159
x十六进制整数9f
o八进制整数237
f定点浮点数15.9
e指数浮点数1.59e+01
g通用浮点数(e和f中较短得的一个) 
a十六进制浮点数0x1.fccdp3
s字符串Hello
c字符H
b布尔true
h散列码42628b2
tx或Tx日期时间(T强制大写)已经过时应当改为使用java,Time类
%百分号%
n与平台有关的行分隔符

 

 

控制格式化输出外观的标志

逗号标志可以添加分组分隔符,例如:Sysytem.out.println("%,.2f",10000.0/3.0);

打印结果为:3,333.33

标志目的示例
+打印正数或负数的符号+3333.33
空格在正数之前添加空格| 3333.33|
0在数字面前补0003333.333
-左对齐|3333.33 |
将负数括在括号内(3333.33)
添加分组分割符3,3333.33
#(对于f格式)包含小数点3,333.
#(对于x或者0格式)添加前缀0x或00xcafe
$

指定要格式化的参数索引。

例如:%1$d %1$x将以十进制和16进制打印第一个参数

159 9F
<

格式化前面说明的数值,

例如:%d%<x将以十进制和十六进制打印同一个数值

159 9

 

可以使用s转换格式化任意的对象。对于实现了Formattable接口的任意对象,将调用这个对象的FormatTo方法,否则调用toString方法将这个对象转换为字符串。

可以使用静态String.format 方法创建一个格式化的字符串,而不打印输出:

String message = String.format("Hello,%s. Next year ,you will be %d",name age);

基于完整性的考虑,下面简略的介绍printf方法中日期与时间格式化选项。对于新的代码,应当使用卷Ⅱ第6章中介绍的java.time包的方法。不过你可能会在遗留的代码中看到Date类相关的格式化选项。这个格式包括两个字母,以t开始,以以下表中任意字符结束

例如:

system.out.printf("%tc",new Date()); 这条语句将用下面的格式打印当前的日期和时间

打印结果为:周六 7月 25 18:05:51 CST 2020

Tip:经过测试部分转换符,有些会替换成中文,例如B, b/h都只会打印7月,没有缩写,缩写只有美国佬的月份

日期时间转换符

转换符类型示例
c完整日期和时间Mon Feb 09 18:05:19 PST 2015
FISO 8601 日期2015-02-09
D美国格式的日期(月/日/年)02/09/2015
T24小时时间18:05:19
r12小时时间06:05:19 pm
R24小时时间没有秒18:05
Y四位数字的年(前面补0)2015
y年的后面两位数字(前面补0)15
C年的前面两位数字(前面补0)20
B月的完整拼写February
b或h月的缩写Feb
m两位数字的月(前面补0)02
d两位数字的日(前面补0)09
e两位数字的日(前面不补0)9
A星期几的完成拼写MonDay
a星期几的缩写Mon
j三位数的年中第几天(前面补0)在001到366之间069
H两位数字的小时(前面补0),在0到23之间18
k两位数字的小时(前面不补0),在0到23之间18
两位数字的小时(前面补0)在1到12之间06
l两位数字的小时(前面不补0)在1到12之间6
M两位数字的分钟(前面补0)05
S两位数字的秒(前面补0)19
L三位数字的毫秒(前面补0)047
N九位数子的毫秒047000000
P上午和下午的标志pm
z从GMT起,RFC 822 数字位移-0800
Z时区PST
s从格林尼治时间1970-01-01 00:00:00起的秒数1595674319
Q从格林尼治时间1970-01-01 00:00:00起的秒数1595674332216

 

某些格式只给出了指定日期的部分信息,因此,可以用一个格式字符串指示要格式化的参数。

System.out.printf("%1$s  %2$tB  %2$te ,%2$ty","Due date:",new Date());

打印结果为:Due date:  七月  25 ,20

 

 

本文章均摘录于Java核心技术卷Ⅰ 用作知识点记录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值