一、不可变的String

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

/*** String是不可变的* @author LiangYu* 2018-01-20*/
public class ImmutableTest {@Testpublic void test() throws Exception {String text = "qwERtYuIOp";System.out.println(text);String text2 = text.toUpperCase();System.out.println(text2);System.out.println(text);}
}
复制代码

二、重载“+”和StringBuilder

String对象是不可变的,可以给String对象加任意多的别名。String对象具有只读特性,所以,指向它的任何引用都不会改变它的值。由此会带来效率问题。

例如: 为String对象重载的"+"操作符就是一个例子。

重载操作符的意思:一个操作符应用于特定的类时,被赋予了特殊意义。(用于String的+ 、+=是Java语言仅有的两个重载操作符)。

/*** String中的“+”* @author LiangYu* 2018-01-20*/
public class StringAppendTest {@Testpublic void test() throws Exception {String message = "Hello";String hw = message + " World"+"!"+55;System.out.println(hw);}
}
复制代码

输出结果: Hello World!55

底层的原理:

编译器自动引入了StringBuilder类,创建StringBuilder对象,用以构造最终的String。并为每个字符串调用一次StringBuilder的append()方法,总计四次。最后调用toString()生成结果。

即使编译器已经自动优化了性能,但是我们仍然要深入的看一下编译器为我们优化到了什么程度。

eg:通过两种方法来生成一个String。

(1) 使用多个String对象

(2) 在代码中使用StringBuilder

/*** 两种方式生成字符串* @author LiangYu* 2018-01-20*/
public class WhitherStringBuilderTest {String implicit(String[] field){String result = "";for(int i = 0 ; i < field.length ; i++){result += field[i];}return result;}String explicit(String[] field){StringBuilder sBuilder = new StringBuilder();for(int i = 0 ; i < field.length ; i++){sBuilder.append(field[i]);}return sBuilder.toString();}@Testpublic void test() throws Exception {String[] texts = {"Hello"," ","World","!","hahah"};System.out.println(implicit(texts));System.out.println(explicit(texts));}
}
复制代码

通过 javap -c WhitherStringBuilderTest查看两个方法的字节码

implicit():

在第5行到第35行构成了一个循环体

在第35行:比较栈顶两int型数值大小,当结果小于0时跳转到第8行,构造一个新的StringBuilder;

在第5行:返回到循环体的起始点(第32行)

可以看到,StringBuilder是在循环体中构造,即:每次循环都会生成一个新的StringBuilder

explicit():

可以看到,只会在第0行生成了一个StringBuilder。

同时,显式的使用StringBuilder还可以预先为其设定大小。如果已经知道最终的字符串大概有多长。那预先指定StringBuilder的大小可以避免多次重新分配缓冲。

三、无意识的递归

Java中的每一个类都是从Object继承而来的,标准容器类也不例外。因此,容器类都有toString()方法,并且覆盖了该方法,使得其生成的String结果能够表达容器自身。

如果希望toString()方法打印出对象的内存地址,不能够使用this关键字。

/*** 在toString方法中,不可以使用this来显示对象的内存地址* @author LiangYu* 2018-01-20*/
public class InfiniteRecursionTest {@Testpublic void test() throws Exception {ArrayList<InfiniteRecursionTest> infiniteRecursionTests = new ArrayList<InfiniteRecursionTest>();for(int i = 0 ; i < 5 ; i++){infiniteRecursionTests.add(new InfiniteRecursionTest());}System.out.println(infiniteRecursionTests);}@Overridepublic String toString() {return "address"+this;}
}
复制代码

此时会报错,因为在return "address"+this;运行的时候发生了强制类型转换,将InfiniteRecursionTest类型转换为String类型,此处调用this上的toString(),会造成无穷递归。

如果要打印对象的内存地址,应该调用Object中的toString().

四、String上的操作

4-1 构造方法

String(byte[ ] bytes):通过byte数组构造字符串对象。

String(char[ ] value):通过char数组构造字符串对象。

String(Sting original):构造一个original的副本。即:拷贝一个original。

String(StringBuffer buffer):通过StringBuffer数组构造字符串对象。

4-2 常用方法

  1. public char charAt(int index) 返回字符串中第index个字符;
  2. public int length() 返回字符串的长度;
  3. public int indexOf(String str) 返回字符串中第一次出现str的位置;
  4. public int indexOf(String str,int fromIndex) 返回字符串从fromIndex开始第一次出现str的位置;
  5. public boolean equalsIgnoreCase(String another) 比较字符串与another是否一样(忽略大小写);
  6. public String replace(char oldchar,char newChar) 在字符串中用newChar字符替换oldChar字符
  7. public boolean startsWith(String prefix) 判断字符串是否以prefix字符串开头;
  8. public boolean endsWith(String suffix) 判断一个字符串是否以suffix字符串结尾;
  9. public String toUpperCase() 返回一个字符串为该字符串的大写形式;
  10. public String toLowerCase() 返回一个字符串为该字符串的小写形式
  11. public String substring(int beginIndex) 返回该字符串从beginIndex开始到结尾的子字符串;
  12. public String substring(int beginIndex,int endIndex) 返回该字符串从beginIndex开始到endsIndex结尾的子字符串
  13. public String trim() 返回该字符串去掉开头和结尾空格后的字符串
  14. public String[] split(String regex) 将一个字符串按照指定的分隔符分隔,返回分隔后的字符串数组

五、格式化输出

printf() 和C语言类似,通过特殊的占位符来表示未来要显示的内容类型。

/*** 类似C语言的格式化输出* @author LiangYu* 2018-01-20*/
public class PrintfTest {@Testpublic void test() throws Exception {int x = 55;double y = 3.14;System.out.printf("Row 1:[%d,%f]",x,y);}
}
复制代码

System.out.format()

format()方法用于PrintStream或PrintWriter对象。模仿自C的printf(),与printf()方法等价。

Formatter类

在Java中,所有新的格式化功能都有java.util.Formatter处理。Formatter构造器经过重载可以接受多种输出目的地,最常用的还是PrintStream()\OutputStream和File。

/*** Formatter的使用* @author LiangYu* 2018-01-20*/
public class FormatterTest {@Testpublic void test() throws Exception {Hero hero1 = new Hero("百里守约", new Formatter(System.out));Hero hero2 = new Hero("百里玄策", new Formatter(System.out));hero1.move(3, 5);hero2.move(11, 7);hero1.move(4, 5);hero1.move(4, 6);hero2.move(10, 7);}
}class Hero{private String name;private Formatter formatter;public Hero(String name,Formatter formatter){this.name = name;this.formatter = formatter;}public void move(int x,int y){if(name != null && formatter != null){formatter.format("%s的位置在:[%d,%d]\n",name,x,y);}}
}
复制代码

格式化说明符

为了在插入数据是控制空格和对齐,需要更加精细的格式修饰符。格式如下:

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

flags表示左右对齐,默认是右对齐,如果想左对齐就使用“-”标志

width控制最小尺寸(宽度)至少该这么长,不够用空格替代。

在width后面加上"."后面表示精度precision。

用于String(%s)时,表示最多可写的字符数

用于浮点数(%f)表示小数点后面的位数,多了舍入,少了补0,默认是6位

用于整数(%d)时,不可用于整数,会触发异常

Formatter转换

常用的类型转换:

d 整型 (十进制)

c Unicode字符

b Boolean

s String

f 浮点型 (十进制)

e 浮点型(科学计数)

x 整数 (十六进制)

h 散列码(十六进制)

% 字符"%"

六、正则表达式

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

正则可以切分,替换,判断字符串,通过设定的regex规则。

基础

在Java中,\\的意思是“我要插入一个正则表达式的反斜线,所以其后字符含有特殊意义”

\\d 表示一位数字

\\W 表示非单词字符

\\w 表示单词字符

\\\\ 表示普通反斜线

\n 换行符

\t 制表符

+ 一个或多个前一位的表达式

| 或者

? 可能有

\\+ 正号(加号在正则表达式中有特殊的意义,必须用\\将其转译为一个普通字符)


/*** 正则表达式的简单应用* @author LiangYu* 2018-01-20*/
public class IntegerMatchTest {@Testpublic void test() throws Exception {System.out.println("-1234".matches("-?\\d+"));System.out.println("4596".matches("-?\\d+"));System.out.println("+911".matches("-?\\d+"));System.out.println("+911".matches("(-|\\+)?\\d+"));}
}
复制代码

创建正则表达式

B 指定字符B

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

\uhhhh 十六进制表示为0xhhhh的Unicode字符

\t 制表符

\n 换行符

\r 回车符

\f 转页符

\e 转义符

常用的字符类:

. 任意字符

[abc] 包含a、b、c的任何字符

[^abc] 除了a、b、c的任何字符

[a-zA-Z] 从a-z或者A-Z的所有字符

[abc[hij]] 包含a、b、c、h、i、j的所有字符

[a-z&&[hij]] 包含h、i、j(交集)

\s 空白符(空格、tab、换行、换页、回车)

\S 非空白符

\d 数字[0-9]

\D 非数字[^o-9]

\w 词字符[a-zA-Z_0-9]

\W 非词字符[^\w]

逻辑操作符:

XY X后面有Y

X|Y X或Y

(X) 捕获组。可以在表达式中用\i引用第i个捕获组

边界匹配符:

^一行的开始

$ 一行的结束

\b 单词的边界

\B 非单词的边界

\G 前一个匹配的结束

量词

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

贪婪型:贪婪表达式会为所有可能的模式发现尽可能多的匹配。假定我们的模式仅能匹配第一个可能的字符串组,如果表达式是贪婪的,那么它就会继续往下匹配。

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

占有型:这种类型的量词只有Java语言中才可用,并且更高级。当正则表达式被应用与字符串时,它会产生相当多的状态,以便在匹配失败时可以会说。而“占有的”量词并不保存这些中间状态,以防止他们回溯。他们常常用于防止正则表达式失控,因此可以使正则表达式执行起来更有效。

这部分太恶心了,暂时跳过,什么时候用什么时候看

《Java编程思想》笔记10------字符串相关推荐

  1. Java编程思想 (1~10)

    [注:此博客旨在从<Java编程思想>这本书的目录结构上来检验自己的Java基础知识,只为笔记之用] 第一章 对象导论 1.万物皆对象 2.程序就是对象的集合 3.每个对象都是由其它对象所 ...

  2. Java编程思想笔记——容器深入研究1

    完整的容器分类法 Java SE5新添加了: 1.Queue接口(LinkedList已经为实现该接口做了修改)及其实现PriorityQueue和各种风格的BlockingQueue. 2.Conc ...

  3. Java编程思想笔记(持有对象)

    1.泛型和类型安全的容器       2.基本概念       3.添加一组元素:Arrays.asList()方法接受一个数组或是一个用逗号分隔的元素列表(使用可变参数),并将其转换为一个LIst对 ...

  4. java 编程思想 笔记_java编程思想笔记20170215

    importjava.util.ArrayList;importjava.util.List;public classTest {public static voidmain(String[] arg ...

  5. 【Java编程思想笔记】-集合1

    1.为什么要用集合? 一般情况下,数组是保存一组对象(或基本数据类型)最有效的方式.但是数组有着固定的尺寸,而在更一般的情况下,我们在写程序时不知道将需要保存多少个对象,或者是否需要更复杂的存储结构来 ...

  6. Java中的移位操作——Java编程思想笔记

    欢迎转载,转载请务必注明出处: http://blog.csdn.net/alading2009/article/details/39968281 Java中的移位操作包括 <<(无符号左 ...

  7. Java编程思想笔记——并发3

    终结任务 装饰性花园 公园人数共享计数值递增: class Count {private int count = 0;private Random rand = new Random(47);// R ...

  8. JAVA编程思想笔记 : 并发 [ 一 ]

    程序中的所有事物,在任意时刻都只能执行一个步骤. 并发的多面性 并发解决的问题大体上可以分为"速度"和"设计可管理性"两种 并发通常是提高运行在单处理器上的程序 ...

  9. 《Java编程思想》10.6 匿名内部类奇怪的代码

    刚刚看到10.6关于匿名内部类的介绍,里面的代码真叫我头大,在电脑上竟然编译不过,IDE里直接标出错误了,拿10.6第一段代码来看: public class Parcel7 {public Cont ...

  10. java 编程思想笔记(七)——异常

    1.什么是异常 java中的异常指的是程序中的异常(不包括硬件异常(内存溢出等)),比如:语法错误(少写分号),除数为0,nullPoint等. 2.为啥需要异常 谁也不想代码在运行的时候,突然程序出 ...

最新文章

  1. xsl-mode属性用法
  2. 关于web程序中使用KindEditor向数据库插入带有格式的数据时出现的问题
  3. 【Qt】Qt5.12编译MySQl5.7驱动(亲自测试成功)
  4. Vi编辑器的使用方法
  5. 一个json格式转xml格式的java实现
  6. dll注入工具_UnmanagedPowerShell工具分析
  7. Redis单机和集群环境搭建
  8. macbook数据线连接手机_MacBook可以为iPhone进行快充吗?用MacBook为iPhone充电好不好?...
  9. 开源计算机视觉库 OpenCV 被曝两个严重的任意代码执行漏洞(详情)
  10. Xshell正版免费,再也不用找破解版了!
  11. 有这就够了小香港五味俱全——专升本高数
  12. visualroute 很棒的一款工具
  13. 网站自动跳转代码大合集
  14. 机器人编程按时巡线_活动回顾 丨巡线机器人编程活动带小朋友体验游戏设计的乐趣...
  15. pta 7-5 病毒变种 C语言
  16. 工商数据采集的10个经典方法
  17. yocto 编译与bb的语法
  18. Mono.Cecil
  19. 人工智能研究和应用领域
  20. 模型量化论文阅读#4----EWGS:Network Quantization with Element-wise Gradient Scaling

热门文章

  1. 从css3书写顺序引出来的border-radius参数
  2. JNIWrapper控件发布v3.8.4版本
  3. Wijmo 更优美的jQuery UI部件集:在安全站点使用Wijmo控件
  4. PuTTY/PSCP、PSFTP介绍及使用
  5. NET面试题:在C#中如何声明一个类不能被继承
  6. 2021年十大 web hacking 技术汇总
  7. PHP源代码后门事件后续:用户数据库遭泄露或是元凶
  8. Cloudera Certified Associate Administrator案例之Install篇
  9. JAVA入门到精通-第16讲-数组
  10. 前端自动化构建工具之webpack入门——简单入门