[十二]基础数据类型之String
在正式介绍String之前,我们先介绍下CharSequence
char + sequence 就是字符的序列的意思
Java中万事万物都是对象类型
而对于字符的序列,也就是多个char, 这么一种东西, 使用CharSequence这个接口来描述
既然是接口,自然规定了作为字符序列的基本协议
CharSequence简介
char charAt(int index); | 返回指定索引的char |
int length() | 返回字符序列的长度 |
CharSequence subSequence(int start, int end) | 返回子序列 |
String toString() | 返回一个包含此序列中字符的字符串该字符串与此序列的顺序相同 |
default IntStream chars() | 返回此序列的int stream,每个char零位扩展为int |
default IntStream codePoints() | 返回此序列的代码点的stream |
既然CharSequence表示了 字符序列这么一个概念
String简介
Java 语言提供对字符串串联符号("+")以及将其他对象转换为字符串的特殊支持
属性CASE_INSENSITIVE_ORDER
字符与字节数组
字符到字节,是一个编码的过程
字节到字符是一个解码的过程
|
同样的一个字符,在不同的字符集和编码方式下,实际存储的值,将是不同的
比如前面说的Unicode字符集,UTF8 和UTF16编码后的数据是不同的
这个编码后的数据,也就是字节 , 他们是不一样的
|
同样的一个编码值,在不同的字符集中,可能代表着不同的字符 |
所以字符与字节之间,必然有编码参与其中
这个编码环节是必然存在的,否则,你就没办法把字节与字符联系起来
|
一个字符可以根据 字符集编码 进行多种方式的编码 一个字节数组也可以根据 字符集编码 进行多种方式的解码 对于同一个字符,不管进行何种编码,当他们按照当初编码的方式进行解码时,必然对应的还是同样的那个字符 |
操作系统的文件都是以字节序列的形式存储的,所以任何一个文件都是有编码的 比如你在txt文件中输入了一个字符 这个字符 底层就会使用指定的编码存储到字节中 软件本身又把这个编码以字符的形式呈现出来 所以你才看得到是一个字符 比如这个文件中11111.txt中,存储了一个汉字春天的 " 春" 编码方式是UTF8 二进制软件查看是E6 98 A5 与我们进行UTF8 编码计算的结果是对应的 |
ANSI编码 不同的国家和地区制定了不同的标准 由此产生了 GB2312、GBK、Big5、Shift_JIS 等各自的编码标准 这些使用 1 至 4 个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码 在简体中文Windows操作系统中,ANSI 编码代表 GBK 编码; 在日文Windows操作系统中,ANSI 编码代表 Shift_JIS 编码 再看下面一个例子 |
任何一个文件,他其实有自带或者说默认的一个编码 凡是呈现字符的地方,都有一个编码在默默地支撑,才能够让你看得见,看得清楚字符 这个字符的保存 , 就是字符按照编码表 编码 成字节序列的过程 这个字符的呈现 , 就是字节序列按照编码表 解码 成字符的过程 当你使用计算机,进行字符处理工作的时候,无时无刻都在进行着编码与解码 |
String构造方法
String是常用类之一,所以提供了非常丰富的方法
String是字符序列 内部是char[] char就是一个十六进制的数 16位表示
所以char[] 可以用来构造String
|
char是16位数能够表示代码单元, int自然可以直接表示一个代码点了,所以也可以使用int来构造String |
另外再加上我们刚才关于字节数组与字符关系的介绍,也可以使用字节数组构造String |
String() | 空String ,没啥必要因为String是不可变的
|
String(char[])
String(char[], int, int)
|
借助于字符数组或者字符数组的一部分创建对象 内部本来就是字符数组 char[] 所以自然可以使用char[]构造 直接进行拷贝,所以对原有字符数组的修改不影响String对象
|
String(int[], int, int) | 使用代码点构造String public String(int[] codePoints, int offset, int count) offset 和 count为范围限制 |
String(String) | |
String(StringBuffer) | |
String(StringBuilder) |
getBytes 方法
先提一下另外一个方法,getBytes
使用指定的字符集将此 String 编码为 byte 序列
我的编辑器环境是UTF8编码的
"春" 的UTF8编码上面已经分析了
也就是说我这边有一个UTF8的字符"春" 源文件中保存的是 E6 98 A5
对于下面所有的getBytes来说,"春" 这个字符形状符号是不变的
获得的字节数组就是 这个字符形状符号 根据不同字符集编码方式, 编码而得到的字节数组
下面的各种转换换一个描述就是:UTF8的字符"春" ,在其他的字符集下面,编码都是多少啊?
|
为什么UTF-8 是-26 -104 -91 ? 而不是e6 98 a5?进制问题 |
getBytes总共三种形式 指定编码或者使用默认 getBytes(String)
getBytes(Charset)
getBytes()
还有一种已经弃用 了
|
通过字节数组 byte[] 构造
使用byte[] 字节数组构造String的过程是下图这样子的 字节数组,根据指定字符编码转换为那个字符 然后在把字符按照UTF16 进行编码 存储到String中的char[] 上面的例子可以很好地印证这一点,字节数组是[-76, -70] 也就是 : ffffffb4 ffffffba 也就是 B4 BA 明明是GBK的"春" 根本就不是6625 对应关系就是他们表示的是同一个字符 |
既然字节数组与字符的转换离不开编码,所以自然通过byte[] 构造String对象时,必须要有编码
不设定并不是没有,而是使用默认的
既然使用字节数组,那么有的时候可能需要指定范围,所以有两个根本的构造方法
|
然后还有默认字符编码的简化形式 |
再然后就是长度为整个字节数组的简化形式 |
这几个构造方法根本在于理解 字节数组与字符的转换 以及必须的byte[] 字节数组 以及 编码 |
valueOf
copyValueOf
copyValueOf方法内部就是直接调用的两个构造方法 还不如直接使用new创建来的直接,只不过使用这个方法有更好的可读性 |
获取指定位置代码单元和代码点的方法
charAt(int) 返回指定索引处的 char 值 索引范围为从 0 到 length() - 1 简单粗暴, 不管三七二十一就是代码单元 如果是辅助平面,那就可能是代理项 |
codePointAt(int) 返回指定索引处的代码点, 范围从 0 到 length() - 1 他跟Character中的codePointAt方法逻辑含义是一样的 如果是高代理,如果下一个也在掌控范围内,如果下一个是低代理,那么返回代码点 否则,返回代码单元 也就是一个char |
codePointBefore(int) 返回指定索引之前的字符(Unicode 代码点) 其范围从 1 到 length 他跟Character中的codePointBefore方法逻辑含义是一样的 如果index-1 是低代理,如果在往前一个index-2 也是有效范围内,如果他还恰好是一个高代理,返回代码点 否则,返回代码单元,也就是一个char |
codePointCount(int, int) 此 String 的指定文本范围中的 Unicode 代码点数 文本范围始于指定的 beginIndex,一直到索引 endIndex - 1 处的 char, 包含头不包含尾 该文本范围的长度(用 char 表示)是 endIndex-beginIndex 由于一个代码点的代码单元个数可能是1个可能是2个,所以代码点的个数需要计算,就不直观了 他跟Character中的codePointCount方法逻辑含义是一样的 |
offsetByCodePoints(int, int) 他跟Character中的offsetByCodePoints方法逻辑含义是一样的 返回此 String 中从给定的 index 处偏移 codePointOffset 个代码点的索引 根本原因还是一个代码点的代码单元个数可能是1个可能是2个 所以 偏移codePointOffset个代码点的 代码单元的个数不确定,需要调用方法计算 |
getChars(int, int, char[], int)复制
实例方法 就是一个复制方法,名字不太规范 复制String中指定索引开始的srcBegin 和 srcEnd 包含头不包含尾 到另一个字节数组 char dst[]中, 存放的起始位置为dstBegin public void getChars(int srcBegin, int srcEnd, char dst[], int dstBegin) |
需要注意的是,复制的是char 代码单元 就是String 内部char[] 的下标索引 |
开始结束匹配校验
startsWith(String, int)
startsWith(String)
|
实例方法 测试String是否以指定的前缀开始 还可以指定起始位置处开始比较 从源代码看得出来,挨个比较内部的char 单参数是双参数的简化版本 |
endsWith(String) | endwith就是从最后的指定参数长度的位置开始比较 |
indexOf 和lastIndexOf
int indexOf(int ch)
int indexOf(int ch, int fromIndex)
|
返回 指定字符 在此字符串中第一次出现处的索引 返回的匹配的第一个 也可以指定检索的起始位置, 如果指定了索引 换个说法: charAt(k) == ch 为 true 的最小 k 值
如果是辅助平面返回的是高代理位的代码单元的索引 |
int indexOf(String str)
int indexOf(String str, int fromIndex)
|
返回 指定子字符串 在此字符串中第一次出现处的索引
返回匹配的第一个
也可以指定检索的起始位置,如果指定了索引
那么返回值需要大于等于 指定的索引
匹配的含义为startsWith(str) 为true
如果指定检索开始的位置, 那么
不仅仅startsWith(str) 为true 还需要索引满足指定的下标范围
否则仍旧是返回-1
|
lastIndexOf(int)
lastIndexOf(int, int)
|
返回指定字符在此字符串中最后一次出现处的索引 返回匹配的最后一个 也可以指定检索位置,但是这个检索位置与indexOf不同 换个说法 如果是0号平面返回的是那个代码单元也就是代码点的索引
charAt(k) == ch 为 true 的最大 k 值
如果是辅助平面返回的是高代理位的代码单元的索引
codePointAt(k) == ch 为 true 的最大 k 值 并且 k 小于等于 指定的索引
|
lastIndexOf(String)
lastIndexOf(String, int)
|
返回指定 子字符串 在此字符串中最后一次出现处的索引
返回匹配的最后一个
也可以指定检索位置,检索索引的位置也是反向搜索
匹配的含义为startsWith(str) 为true
指定了索引就要求返回值 小于等于 指定索引
|
length
isEmpty()
hashCode
计算公式
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
|
字符串匹配包含
测试两个字符串区域是否相等
toffset 表示当前对象this 开始的位置
other 表示另外一个String对象
ooffset 表示另外对象开始的位置
len 要匹配的长度
两个方法其中一个可以指定是否忽略大小写
|
s1.regionMatches(1,s2,3,4); 读作: 把s1 从索引1开始 同 s2 从索引3开始,比较len个长度,查看这个区域是否相等 |
public boolean regionMatches( int toffset, String other, int ooffset,int len)
public boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len)
|
contains contains也是一种匹配 当且仅当此字符串包含指定的 char 值序列时,返回 true |
matches 此字符串是否匹配给定的正则表达式 public boolean matches(String regex) |
相等比较
equals(Object)
equals方法也进行了重写
比较的是内部的char 序列是否相等
先看是否同一个对象,否则看是否String类
然后再看长度,长度相同挨个比较
|
contentEquals(StringBuffer)
contentEquals(CharSequence)
这两个方法 分别针对参数StringBuffer 和 CharSequence
他们都是 当且仅当表示相同的 char 值序列时,结果才为 true
比较的也是内容
上面的equals方法也是比较的内容
|
equalsIgnoreCase(String) 比较忽略大小写,底层依赖的就是区域的比较 只不过区域是整个字符串而已 |
compareToIgnoreCase(String) 字典顺序比较两个字符串,不考虑大小写 |
compareTo(String) compareTo(String)方法是按照字典序进行排序的 如果字符本身全都相等,但是长度不同,返回长度差 |
子串获取
public String substring(int beginIndex) public String substring(int beginIndex, int endIndex) public CharSequence subSequence(int beginIndex, int endIndex) |
subSequence 就是调用的subString方法 为什么还需要呢?就是为了遵循CharSequence协议 |
subString也是处理的char的索引,不是字符的 所以一个好好地字符,可能被你截取后,就成为乱码了 所以如果你想要截取子串也会出现乱码,可以通过offsetByCodePoints 获取指定个代码点后的索引 那么截取的绝对不会是乱码 看一个例子 0x1f310的高代理位在Character简介中计算过,它的值跟十进制的55356一样的 |
大小写转换
大小写的转换 可以指定Locale 不指定,等价于 指定默认值Locale.getDefault() 大小写映射关系基于 Character 类指定的 Unicode 标准版 |
toLowerCase(Locale)
toLowerCase()
toUpperCase(Locale)
toUpperCase()
|
split
根据匹配给定的正则表达式来拆分此字符串 子字符串按它们在此字符串中出现的顺序排列 如果表达式不匹配输入的任何部分,那么所得数组只具有一个元素,那就是这个字符串 public String[] split(String regex, int limit) 如果该限制 n 大于 0,则模式将被最多应用 n - 1 次
数组的长度将不会大于 n,而且数组的最后一项将包含所有超出最后匹配的定界符的输入
如果 n 为非正,那么模式将被应用尽可能多的次数,而且数组可以是任何长度
如果 n 为 0,那么模式将被应用尽可能多的次数,数组可以是任何长度,并且结尾空字符串将被丢弃
例如,字符串 "boo:and:foo" 使用这些参数可生成以下结果:
|
split(String) 是split(String, int) 的简化形式 |
join
join用于将字符序列使用指定的符号进行拼接 需要注意的是,如果有元素为null ,那么"null" 将会被添加进来 |
public static String join(CharSequence delimiter,
CharSequence... elements)
public static String join(CharSequence delimiter,
Iterable<? extends CharSequence> elements)
|
替换
public String replace(char oldChar, char newChar) | 替换后,返回一个新的字符串 如果 oldChar 不存在,则返回这个 String 对象的引用 否则,创建一个新的 String 对象 所有的 oldChar 都被替换为 newChar |
public String replace(CharSequence target, CharSequence replacement) |
替换后,返回一个新的字符串 使用指定的字符序列进行替换 用 "b" 替换字符串 "aaa" 中的 "aa" 将生成 "ba" 而不是 "ab" |
replaceFirst(String, String)
|
|
replaceAll(String, String) |
concat 连接
将指定字符串连接到此字符串的结尾
如果参数字符串的长度为 0,则返回此 String 对象
否则,创建一个新的 String 对象,返回新创建的连接后的字符串
|
先复制一个到数组中 然后再把参数的复制到那个数组中 然后使用数组创建String |
trim
trim() |
最常用的String方法之一,去掉开头和结尾的空格 |
toString()
|
返回他自己本身 他本来就是一个String了 |
toCharArray() | 将此字符串转换为一个新的字符数组 内部本身就是一个char[] 所以自然可以轻松的转换为char数组 数组拷贝了下 |
format
format
使用指定的格式字符串和参数返回一个格式化字符串
可以指定语言环境
内部还是使用的Formatter
|
intern
intern()
String 私有地维护了, 一个初始为空的字符串池
当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(用 equals(Object) 方法确定),则返回池中的字符串
否则,将此 String 对象添加到池中,并返回此 String 对象的引用
它遵循以下规则:对于任意两个字符串 s 和 t,当且仅当 s.equals(t) 为 true 时,s.intern() == t.intern() 才为 true
|
对于直接定义的 "a" "ab" 会进入这个字符串池 如果是new 创建的字符串对象不进入字符串池 如果使用+ 得到的,两个都是字面的"a" "ab" 形式会进入字符串池,否则如果有变量也不会进入 str5 和 str3 内容相同,String重写了equals方法,比较的是内容,所以true str5 和 str3 一个是new出来的,所以地址不相等 false str5.intern() 查找池中是否有"ab" 有的话返回引用,显然就是str3 所以true str5.intern() 查找池中是否有"ab" 有的话返回引用,显然就是str3的地址 但是str4 是一个对象,他与str3 不是同一个对象所以不相等 false 最后一个都是获取"ab"的引用,显然是相等的 |
总结
[十二]基础数据类型之String的更多相关文章
- 「kuangbin带你飞」专题十二 基础DP
layout: post title: 「kuangbin带你飞」专题十二 基础DP author: "luowentaoaa" catalog: true tags: mathj ...
- 【算法系列学习】[kuangbin带你飞]专题十二 基础DP1 G - 免费馅饼
https://vjudge.net/contest/68966#problem/G 正解一: http://www.clanfei.com/2012/04/646.html #include< ...
- [二]基础数据类型之Long详解
Long Long 基本数据类型long 的包装类 Long 类型的对象包含一个 long类型的字段 属性简介 值为 263-1 的常量,它表示 long 类型能够表示的最大值 ...
- Vue.js 源码分析(十二) 基础篇 组件详解
组件是可复用的Vue实例,一个组件本质上是一个拥有预定义选项的一个Vue实例,组件和组件之间通过一些属性进行联系. 组件有两种注册方式,分别是全局注册和局部注册,前者通过Vue.component() ...
- [kuangbin带你飞]专题十二 基础DP1
ID Origin Title 167 / 465 Problem A HDU 1024 Max Sum Plus Plus 234 / 372 Problem B HDU 1 ...
- 【算法系列学习】[kuangbin带你飞]专题十二 基础DP1 F - Piggy-Bank 【完全背包问题】
https://vjudge.net/contest/68966#problem/F http://blog.csdn.net/libin56842/article/details/9048173 # ...
- 【算法系列学习】[kuangbin带你飞]专题十二 基础DP1 E - Super Jumping! Jumping! Jumping!
https://vjudge.net/contest/68966#problem/E http://blog.csdn.net/to_be_better/article/details/5056334 ...
- 【算法系列学习】状压dp [kuangbin带你飞]专题十二 基础DP1 D - Doing Homework
https://vjudge.net/contest/68966#problem/D http://blog.csdn.net/u010489389/article/details/19218795 ...
- 【算法系列学习】[kuangbin带你飞]专题十二 基础DP1 C - Monkey and Banana
https://vjudge.net/contest/68966#problem/C [参考]http://blog.csdn.net/qinmusiyan/article/details/79862 ...
随机推荐
- [转].Net-C#的委托(代理)和事件
一.代理 首先我们要弄清代理是个什么东西.别让一串翻译过来的概念把大家搞晕了头.有的文章把代理称委托.代表等,其实它们是一个东西,英文表述都是“Delegate”.由于没有一本权威的书来规范这个概念, ...
- [HACK] docker runtime 挂载宿主机目录
网上看到的很多所谓的挂载都是容器创建时期的挂载,而且参数都不清不楚,整理如下(--name别名自己加): docker run -v /src/path:/dest/path:rw ${IMAGE} ...
- Address already in use: make_sock: could not bind to address 0.0.0.0:80
网上查了很多资料都是要杀进程,但是并没有找到占用的进程. 最后解决的方案是在apache配置文件下,去掉Listen 80 即可
- Red and Black---POJ - 1979
There is a rectangular room, covered with square tiles. Each tile is colored either red or black. A ...
- xgboost 多gpu支持 编译
xgboost 多gpu支持 编译 Ubuntu 18.04.2Linux 4.15.0-46-genericgcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0 cuda ...
- ABP入门系列(17)——使用ABP集成的邮件系统发送邮件
ABP中对邮件的封装主要集成在Abp.Net.Mail和Abp.Net.Mail.Smtp命名空间下,相应源码在此. #一.Abp集成的邮件模块是如何实现的 分析可以看出主要由以下几个核心类组成: E ...
- 【转载】看StackOverflow如何用25台服务器撑起5.6亿的月PV
问答社区网络 StackExchange 由 100 多个网站构成,其中包括了 Alexa 排名第 54 的 StackOverflow.StackExchang 有 400 万用户,每月 5.6 亿 ...
- 安装与配置Flutter开发环境
这篇博客我们介绍了Flutter,并且对比了H5,React Native,Flutter. 由于Flutter是跨平台的开发框架,开发一次可以同时运行在Android和iOS上面,所以我们开发时最好 ...
- Java开发快速上手
Java开发快速上手 前言 1.我的大学 2.对初学者的建议 3.大牛的三大特点 4.与他人的差距 第一章 了解Java开发语言 前言 基础常识 1.1 什么是Java 1.1.1 跨平台性 1.2 ...
- [Swift]LeetCode199. 二叉树的右视图 | Binary Tree Right Side View
Given a binary tree, imagine yourself standing on the right side of it, return the values of the nod ...