java 8 charsqquence_JAVA 第十三章

Loading...

# 第十三章 字符串

**可以证明,字符串操作是计算机程序设计中最常见的行为。**

-----

### 1. 不可变 String

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

```java

package Thirteen;

public class OneTest {

public static String upcase(String s){

return s.toUpperCase() ;

}

public static void main(String[] args) {

String q = "thirteen" ;

System.out.println(q);

String qq = upcase(q) ;

System.out.println(qq);

System.out.println(q);

}

}

output

thirteen

THIRTEEN

thirteen

```

* 当把 q 传给 upcase() 方法的时候,实际传递的是引用的一个拷贝。其实每当把 String 对象作为方法的参数的时候,都会复制一份引用,而该引用所指的对象其实一直待在单一的物理位置上,从未动过。

* 传入 upcase() 的引用有了名字 s ,只有 upcase() 运行的时候,局部引用 s 才存在,一旦 upcase() 运行结束, s 就消失了。 upcase() 的返回值,也只是最终结果的引用。这些都足以说明, upcase() 返回的引用已经指向了一个新的对象,而原本的 q 其实还在原地。

* 对一个方法而言,参数是为该方法提供信息的,而不是想让该方法改变自己的。

---

### 2. 重载 “ + ” 与 SringBuilder

* String 对象是不可变的 ,你可以给一个 String 对象加任意多的别名。 因为 String 对象具有只读特性,所以指向它的任何引用都不可能改变它的值,因此,也就不会对其他的引用有什么影响,

* 重载的意思是:一个操作符在应用于特定的类时,被赋予了特殊的意义。(用于 String 的 “ + ” 与 “ += ” 是 java 中仅有的两个重载过的操作符,而 java 并不允许程序员重载任何操作符 )

* 通过 “ + ” 操作符 连接 String:

```java

package Thirteen;

public class TwoTest {

public static void main(String[] args) {

String mango = "mango" ;

String s = "abc" + mango + "def" + 47 ;

System.out.println(s) ;

}

}

///output

abcmangodef47

```

* 可以使用 JDK 自带的工具 javap 来反编译以上代码: javap -c TwoTest , -c 表示将生成 JVM 字节码。

* 当使用 “ + ” 的时候,会自动使用 StringBuilder 类。为每个字符串调用一次 StringBuilder 的 append() 方法。最后调用 toString() 生成结果。

* 使用 StringBuilder 还允许你预先为其指定大小,如果想在 toString() 方法中使用循环,那么最好自己创建一个 StringBuilder 对象,用它来构造最终的结果

```java

package Thirteen;

import java.util.Random;

public class ThreeTest {

public static Random rand = new Random(47) ;

public String toString(){

StringBuilder result = new StringBuilder("[") ;

for(int i = 0 ; i< 25 ; i++){

result.append(rand.nextInt(100));

result.append(",") ;

}

result.delete(result.length()-1 , result.length()) ;

result.append("]") ;

return result.toString() ;

}

public static void main(String[] args) {

ThreeTest tts = new ThreeTest() ;

System.out.println(tts);

}

}

/// output

[58,55,93,61,61,29,68,0,22,7,88,28,51,89,9,78,98,61,20,58,16,40,11,22,4]

```

* StringBuffer 提供了丰富全面的方法。包括: insert() , repleace() , substring() , 甚至 reverse() , 但是最常用的还是 append() , toString() ,还有 delete() 方法。

----

### 3. 无意识的递归

* java 中的每个类从根本上都是继承自 Object , 标准类容器也不例外,因此容器类都有 toString() 方法,并且覆写了这个方法,使得生成的 String 结果能够表达容器本身,以及容器所包含的对象。

```java

......

return "xxxx " + this ;

.....

```

* 并不会返回想要的结果,因为编译器看到前面是一个 String 类型,后面跟一个 “ + ” ,会尝试把 this 换成 String 类型。想正确调用 this 需要调用 super.toString() 方法。

---

### 4. String 上的操作

以下是 String 对象的一些基本方法。

|方法 | 应用|

|:--|:--|

|构造器|创建 String 对象|

|length()|String 中字符的个数|

|charAt()|取得 String 中该索引位置上的 char|

|getChars(),getBytes()|复制 char 或者 byte 到一个目标数组中|

|toCharArray()|生成一个 char[] , 包含 String 的所有字符|

|equals(),equalsIgnoreCase()|比较两个 String 内容 是否相同|

|compareTo()|按词典顺序比较 String 的内容,比较结果为负数、零或正数。注意,大小写并不等价|

|contains()|如果该 String 对象包含参数的内容,则返回 true|

|contentEquals()|如果该 String 与参数内容完全一致,则返回 true|

|equalsIgnoreCase()|忽略大小写,如果两个 String 内容相同,则返回 true|

|regionMatcher()|返回 boolean 结果,已表明所比较区域是否相等|

|startsWith()|返回 boolean 结果,以表明该 String 是否 以此参数开始|

|endsWith()|返回 boolean 类型结果,以表明此参数是否该字符串的后缀|

|indexOf(),lastIndexOf()|如果该 String 并不包含此参数,就返回 -1 ;否则返回此参数在 String 中的起始索引。lastIndexOf() 是从后向前搜索|

|substring(subSequence())|返回一个新的 String ,以包含参数指定的子字符串|

|concat()|返回一个新的 String 对象,内容为原始 String 连接上参数 String|

|replace()|返回替换字符后的新 String 对象。如果替换没有发生,则返回原始的 String 对象|

|toLowerCasetoUpperCase()|将字符的大小写改变以后,返回一个新的 String 对象,如果没有改变发生,则返回原始的 String 对象|

|trim() | 将 String 两端的空白字符删除后,返回一个新的 String对象, 如果改变没有发生,则返回原始的 String 对象 |

|vaueOf()|返回一个表示参数内容的 String |

|intern| 为每个唯一的字符序列生成一个且仅生成一个 String 引用|

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

---

murong mengjie, [27.06.18 09:36]

### 5. 格式化输出

#### 5.1. printf()

* printf() 虽然不使用重载的 “ + ” 操作符,但是可以使用特殊的 占位符来表示数据将来的位置,还可以将插入格式化字符串的参数。这些占位符叫做 *格式修饰符*

printf("Row 1: [%d %f\n]" , x,y ) ;

---

#### 5.2. System.out.format()

* format 方法可用于 PrintStream 或者 PrintWriter 对象,其中也包括 System.out 对象。 format() 方法模仿自 C 的 printf()

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

---

#### 5.3. Formatter 类

* 所有的格式化功能都由 java.util.Formatter 处理,可以将 Formatter 看做一个翻译器,他将你的格式化字符串与数据翻译成需要的结果。

---

#### 5.4. 格式化说明符

* 如果想要控制空格与对齐等等,需要更加精细复杂的格式修饰符,同样是使用的 Formatter

```java

//语法:

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

```

---

####5. 5. Formatter 转换

* 下面的表格包含了最常用的类型转换:

|类型转换字符||

|--|--|

|d|整数型(十进制)|

|c|Unicode字符|

|b|boolean 值|

|s|String|

|f|浮点数(十进制)|

|e|浮点数(科学计数)|

|x|正数(十六进制)|

|h|散列码(十六进制)|

|%|字符“ % ”|

* 对于 b 转换,基本类型是 boolean 基本类型或者 Boolean 对象,其转换结果是对应的 true 或者 false ,但是对于其他类型的参数,只要不为 null ,全部都是 true ,即便是0 。

----

####5. 6. String.format

* String.format() 是一个 static 方法,接受和 Formatter。format() 方法一样的参数,但是返回一个 String 对象。

* 相当于 C 中的 sprintf() 方法。

* 一个十六进制转储( dump ) 工具:

```java

package Thirteen;

import java.io.File;

public class HexTest {

public static String format(byte[] date){

StringBuilder result = new StringBuilder() ;

int n = 0 ;

for(byte b : date){

if(n % 16 == 0){

result.append(String.format("%05X: ",n)) ;

}else{

result.append(String.format("%02X : " ,b)) ;

}

n++ ;

if(n % 16 == 0){

result.append("\n") ;

}

}

result.append("\n");

return result.toString() ;

}

public static void main(String[] args) throws Exception{

if(args.length == 0){

System.out.println(format(BinaryFile.read("xxx.class")));

}else{

System.out.println(format(BinaryFile.read(new File(args[0]))));

}

}

}

```

----

### 6.正则表达式

* 是用正则表达式可以使我们以编程的方式,构造复杂的文本模式,并对输入的字符串进行搜索。

---

#### 6.1 基础

* 一般来说,正则表达式就是以某种方式来描述字符串。也就是:如果一个字符串包含有这些东西,那么就正是我在找的东西。

* 找一个负号在前面的数字 : -?

* 用 \d 表示 一位数字

* 在 其他语言中 , \\\\ 表示我想在正则表达式中插入一个普通的 反斜线,请不要给它任何特殊的意义。在 java 中 \\\\ 的意思是我要插入一个正则表达式的反斜线,所以其后面的字符具有特殊的意义。比如像表示一位数字,那么正则表达式应该是:**\\\\d** ,如果想插入一个普通的反斜线,那么应该写成:**\\\\\\\\** 不过换行和制表符之类的东西只需使用单反斜线: \n\t 。

* 可能有一个负号,后面跟着一位或多位数字: -?\\\\d+

* 应用正则表达式的最简单的途径,就是使用 String 类内建 的 功能。

```java

package Thirteen;

public class IntegerMatch {

public static void main(String[] args) {

System.out.println("-1234".matches("-?\\d+"));

System.out.println("5678".matches("-?\\d+"));

System.out.println("+564".matches("-?\\d+"));

System.out.println("+911".matches("(-|\\+)?\\d+"));

}

}

// output

true

true

false

true

```

* 可能以一个加号或者减号开头,在正则表达式中,括号有着将表达式分组的效果,而竖直线 | 则表示或操作: ( -|\\\\+ )? ,表示字符串的起始字符可能是一个 - 或者 + 或者两个都没有,因为跟着 ? 修饰符 , 因为 + 在正则表达式中有着特殊的意义,所以必须使用转义字符 \\\\ 将其转义为普通字符

* split() 方法 ,功能是将字符串从正则表达式匹配的地方切开

* replaceFirst() 方法,只替换正则表达式第一个匹配的字串

* replaseAll() ,替换所有匹配的地方。

* \W 意思是非单词字符

* \w 意思是一个单词字符。

* f\\\\w+ 以字母 f 开头,后面跟 一个或多个字母。

---

#### 6.2 创建正则表达式

|字符||

|:-- |:-- |

|B|指定字符 B|

|\xhh|十六进制值为 oxhh 的字符|

|\uhhhh|十六进制表示为 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|非词字符[^\w]|

|逻辑操作符||

|:--|:--|

|XY|Y 跟在 X 后面|

|X\|Y|X 或 Y|

|(X)|捕获组(capturing group)|

|边界匹配符||

|:--|:--|

|^|一行的起始|

|$|一行的结束|

|\b|词的边界|

|\B|非词的边界|

|\G|前一个匹配的结束|

---

####6.3. 量词

量词描述了一个模式吸收输入文本的方式

* 贪婪型:量词总是贪婪的。贪婪表达式会为所有可能的模式发现尽可能多的匹配。

* 勉强型:用问号来指定,这个量词匹配满足模式所需的最少字符数,因此也被称作懒惰的、最少匹配的、不贪婪的。

* 占有型:防止正则表达式失控。

* 表达式应该用圆括号括起来,以便他能够按照我们期望的效果去执行。例如: abc+ ,看起来是:匹配一个或多个 abc 序列,但实际上表示的是:匹配 ab ,后面跟随一个或者多个 c。正确的应该这样写:( abc ) +

* CharSequence ,接口 CharSequence 从 CharBuffer 、String 、 StringBuffer 、 StringBuilder 类之中抽象出了字符序列的一般化定义:

```java

interface CharSeuence{

charAt(int i) ;

length();

subSequence(int start , int end );

toString() ;

}

```

----

#### 6.4 Pattern 和 Matcher

* 根据传入的 String 类型 生成一个 Pattern 对象。将要检索的字符串传入 Pattern 对象的 ,matcher() 方法。 matcher() 方法会生成一个 Matcher 对象。

java

Pattern p = Pattern.compile(arg) ;

Matcher m = p.matcher(args[0]) ;

* Matcher 对象上的方法:

1. boolean matchers() ; //判断整个输入字符串是否匹配正则表达式

2. boolean lookingAt() ; //判断字符串的始部分是否能够匹配模式

3. boolean find() ;

4. boolean find(int start) ;

* Matcher.find() 方法可以用来在 CharSequence 中查找多个匹配。

* \\\\w+ 可以将字符串划分为单词。

```java

package Thirteen;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

public class IntegerMatch {

public static void main(String[] args) {

Matcher m =Pattern.compile("\\w+").matcher("Evening is full of the linnet");

while(m.find()){

// 像迭代器那样前向遍历输入字符串

System.out.println(m.group()+"");

}

System.out.println();

int i = 0 ;

while(m.find(i)){

//接受一个整数作为参数,整数表示字符串中字符的位置,以此作为搜索的起点

System.out.println(m.group()+"");

i++ ;

}

}

}

```

* 组(Group) 是用括号划分的正则表达式,可以根据组的编号来引用某个组。组号为 0 表示整个表达式,组号 1 表示第一队括号括起来的组。以此类推。

A ( B ( C ) ) D

三个组 ,组0 是 ABCD , 组1 是 BC ,组 2是 C

* 在匹配操作成功后, strat() 返回先前匹配的起始位置的索引, end () 返回尝试所匹配的最后字符的索引加一的值。

---

#### 6.5 split()

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

---

#### 6.6 替换操作

* 正则表达式特别便于替换文本,提供了很多的方法。

---

### 7. 扫描输入

* Scanner类的构造器可以接受任何类型的输入对象。

* 默认情况下,Scanner 根据空白字符对输入的内容进行分词,但是你可以用正则表达式指定自己所需的定界符。

```java

Scanner scanner = new Scanner("12,13,14");

scanner.useDelimit("\\s*,\\s*") ;

* 使用正则表达式:

java

Scanner scanner = new Scanner("xxx");

String pattern = "(\\d+[.]\\d+[.])" ;

while(scanner.hasNext(pattern)){

/// Code

}

```

---

### 8. String Tokenizer

* 分隔字符串,不过有了 Scanner 之后已经废弃掉了。

-------

**由于时间原因,这本书之后就没再做什么笔记了**

-------

由本人从 Thinking in java ( java 编程思想 ) 整理而来

最后修改:2018 年 07 月 15 日 02 : 45 PM

© 允许规范转载

赞赏

打赏?不存在的= =

×Close

赞赏作者

扫一扫支付

png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAABS2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxMzggNzkuMTU5ODI0LCAyMDE2LzA5LzE0LTAxOjA5OjAxICAgICAgICAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIi8+CiA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgo8P3hwYWNrZXQgZW5kPSJyIj8+IEmuOgAAAA1JREFUCJljePfx038ACXMD0ZVlJAYAAAAASUVORK5CYII=

png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAABS2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxMzggNzkuMTU5ODI0LCAyMDE2LzA5LzE0LTAxOjA5OjAxICAgICAgICAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIi8+CiA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgo8P3hwYWNrZXQgZW5kPSJyIj8+IEmuOgAAAA1JREFUCJljePfx038ACXMD0ZVlJAYAAAAASUVORK5CYII=

支付宝支付

微信支付

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值