Java学习笔记18——深入学习字符串

任何语言,编写的所有应用,大概都会用到大量字符串,以及对字符串进行处理,Java语言中,对与字符串的处理和Python等语言中不同。昨天学习JDBC内容,编写的一个类中比较两个字符串变量值,没有注意到这一点,浪费我好多时间,今天特深入学习和记录一下,避免以后犯错。

1、String类

Java中的字符串不是基本数据类型,而是引用型的,是String类的对象。当需要声明一个字符串变量时,就需要使用String类。比如:

String str;

要创建一个字符串对象也非常简单,直接给String变量赋字符串字面常量即可:

String str = "liuzx";

另外,还开使用Java中创建对象的关键字new来创建一个字符串对象:

String str = new String("liuzx");

String类有十多个重载的构造方法,可以使用byte数组、char数组或者另一个String对象来创建一个新的String对象。

查看Java中的String类的API文档,String类声明为final,意味着这个类不可继承,说明Java把String类作为一个标准的字符串操作类。

2、字符串的比较(==运算符与equal方法)

关系运算符==用于比较两个操作数是否相等,下面几个案例,将可以更好理解及如何比较两个String类型的变量是否相等。

package com.test;public class StringTest {public static void main(String[] args) {String str1 = "abcde";String str2 = "abcde";if (str1 == str2) {System.out.println("str1和str2相等");} else {System.out.println("str1和str2不相等");}}
}

上面代码运行的结果是:str1和str2相等

知识点:

  • 在Java中,boolean、byte、short、int、long、char、float和double是基本数据类型,其它都是引用类型。也就是说,所有的对象类型都是引用类型。
  • 所以,Java中的字符串都是String类型的对象,包括字符串字面常量,也就是说,“abc”是一个对象,是String类型的对象。
  • 另外,==元算符是比较两个变量的值是否相等。

分析上面代码中的声明字符串变量str1和str2的定义语句:

String str1 = "abcde";
String str2 = "abcde";

第一行代码中的"abcde"是字符串字面常量,也是一个String类型的对象,Java编译器在常量池中分配内存空间并存储字符串序列,然后将该对象的引用赋值给字符串变量str1;

第二行中的"abcde"是字符串字面常量,Java编译器发现常量池中已经存在该对象,于是直接将该对象的引用值赋给变量str2,换句话说,编译器会把在程序中出现的相同内容的字符串字面常量视作同一个String对象。对于对象类型的变量,其值就是引用值,也可以理解为是对象的地址,==比较运算符用于比较两个引用类型的变量时,比较的是它们的引用值是否相等。上面代码中的变量str1和str2指向的是同一个对象,那么==运算符比较的结果是相等的。

看如下的代码,修改变量str1和str2的定义方法,运算的结果是:str1和str2不相等

public class StringTest {public static void main(String[] args) {String str1 = new String("abcde");String str2 = new String("abcde");if (str1 == str2) {System.out.println("str1和str2相等");} else {System.out.println("str1和str2不相等");}}
}

分析上面代码,"abcde"是字符串字面常量,Java在常量池中分配内存并存储字符串序列,接下来new运算符要构造一个String类型的对象,于是用常量池中的字符串对象的内容在堆内存上构造一个新的String对象,并将新对象的引用值赋给变量。所以上面两行代码,两个new操作在堆内存上产生了两个不同的对象(有不同的内存空间),所以str1和str2指向的是不同的对象,故它们的引用值是不同的,用==运算符进行比较,比较的是引用值,结果自然是不相等的。

知识点:

  • 当我们声明一个引用类型变量时,系统只为该变量分配了引用空间,并为创建一个具体的对象;当使用new操作符,将为对象分配空间,之后将对象的引用赋值给变量。
  • 如果要比较两个对象的内容是否相等,需要使用对象的equals方法。在Java中,所有类都有一个共同的基类:java.lang.Object,在这个类中定义了一个方法equals,用于与另一个对象进行相等性判断,如果相等,返回true,否则返回false。
  • Object类中的equals方法只有在两个引用值所指向同一个对象时才返回真true,所以不能直接使用Object类的equals方法,一般都是子类重写Object类的equals方法,提供自己的比较逻辑,String类作为Object的子类,也重写了equals方法,用于比较字符串对象内部所存储的字符串序列是否相等,也就是说String类的equals方法用来比较两个字符串对象的内容是否相等。
public class StringTest {public static void main(String[] args) {String str1 ="abcde";String str2 = new String("abcde");String str3 = new String("abcde");if (str1.equals(str2)) {System.out.println("str1和str2相等");} else {System.out.println("str1和str2不相等");}if (str2.equals(str3)) {System.out.println("str2和str3相等");} else {System.out.println("str2和str3不相等");}}
}

上面代码运算的结果是:

str1和str2相等
str2和str3相等

3、compareTo方法

如果需要按照字典顺序(例如a小于b)来比较两个字符串的大小,可以使用String类的compareTo方法来比较两个字符串。如果当前字符串大于另一个字符串,compareTo方法返回一个正整数;如果相等,则返回0;如果小于则返回一个负整数。

public class StringCompareTo {public static void main(String[] args) {String str1 = "abc";String str2 = "abf";String str3 = new String("abc");System.out.println(str1.compareTo(str2));System.out.println(str2.compareTo(str1));System.out.println(str1.compareTo(str3));System.out.println(str3.compareTo(str1));}}

上面代码执行的结果如下:

-3
3
0
0

compareTo方法返回的是一个int值。这个方法会逐个比较两个字符串中各个字符的值,当遇到不同的字符时,它返回当前字符串减去另一个字符串在相同位置的字符值,也就是对相同位置的两个char类型的变量进行减法操作。

Java中,通常使用if语句中使用compareTo方法来判断两个字符串比较的结果,当结果小于0、大于0或者等于0时,分别执行对应操作。

4、字符串的拼接

在Java中,字符串的拼接是简单的,直接使用“+”运算符就可以了。还可以使用“+=”运算符。

String world = "World";
String res = "Hello " + world + "!";
String world = "World";
String res = "Hello";res += world;
res += "!";

 上面的操作,等同于调用String类的concat方法:

String world = "World";
String res = "Hello";res = res.concat(world);
res = res.concat("!");

 在Java中,“+”和“+=”运算符,除了可以应用于字符串对象,还可以应用其它的数据类型,例如:

String world = "World";
int i =3;
float f = 4.5f;
char ch = 'a';
boolean b = true;System.out.println(world + i + f + ch + b);

输出结果:World34.5atrue

5、操作字符串的常用方法:

(1)获取字符串的长度:调用String类的length()方法,注意返回的是字符的数量,不是该字符串占用内存的大小。

String str = "Java 从入门到精通";
System.out.println(str.length());

(2)查找字符或字符串

查找字符串中是否存在某个字符或者某个子字符串,使用String类重载的4个indexOf方法,如下:

public int indexOf(int ch)                    // 参数ch是要查找的字符
public int indexOf(int ch,int fromIndex)      // 参数fromIndex表示从哪个索引位置开始查找
public int indexOf(String str)                // 参数str是要查找的子字符串
public int indexOf(String str,int fromIndex)

 indexOf方法返回一个整数,默认从索引0位置开始查找,返回字符或者子字符串第一次出现的索引,如果没有找到,返回值是-1。

public class StringCompareTo {public static void main(String[] args) {String str = "Hello World";System.out.println(str.indexOf('o'));       // 输出4System.out.println(str.indexOf('o',5));     // 输出7System.out.println(str.indexOf("World"));   // 输出6System.out.println(str.indexOf("Welcome")); // 输出-1}
}

 String类也提供了反向查找字符或者子字符串的一组重载的lastIndexOf方法,如下所示:

public int lastIndexOf(int ch)                    // 参数ch是要查找的字符
public int lastIndexOf(int ch,int fromIndex)      // 参数fromIndex表示从哪个索引位置开始查找
public int lastIndexOf(String str)                // 参数str是要查找的子字符串
public int lastIndexOf(String str,int fromIndex)

将上面代码修改如下,结果将是:

public class StringCompareTo {public static void main(String[] args) {String str = "Hello World";System.out.println(str.lastIndexOf('o'));       // 输出7System.out.println(str.lastIndexOf('o',5));     // 输出4System.out.println(str.lastIndexOf("World"));   // 输出6System.out.println(str.lastIndexOf("Welcome")); // 输出-1}
}

请注意lastIndexOf()方法,是从字符串的最后一个字符开始,查找字符或者子字符串在字符串第一次出现的字符,返回这个字符在字符串中的索引位置(从正面开始,索引值从0开始)。

(3)判断字符串的开始和结尾:startsWith() / endsWith()方法

// 测试字符串是否以指定的前缀开始
public boolean startsWith(String prefix)  // 测试字符串从指定的索引开始的子字符串是否以指定前缀开始
// 参数toffset表示在字符串中开始查找的位置 
public boolean startsWith(String prefix,int toffset) // 测试字符串是否以指定的后缀结尾
public boolean endsWith(String suffix)String str = "代码test.jsp";System.out.println(str.stratsWith("代码"));  // true
System.out.println(str.endsWith(".jsp"));   // false

(4)获取指定索引位置的字符:charAt(int index)

String str = "hello";              // 定义并初始化字符串变量str
int len = str.length();            // 获取字符串变量str的长度
char[] chaArr = new char[len];     // 定义一个字符型数组对象chArr,并初始化长度为str的字符个数for (int i=0; i<len; i++) {chArr[i] = str.charAt(i);      // 给字符型数组变量chArr添加元素
}System.out.println(charArr);       // 输出:hello

另外,字符串转化为字符数组这个功能也经常会用到,Java中的String类提供了toCharArray()方法来实现。定义如下:

  • public char[] toCharArray() 

(5)截取子字符串

// 从指定索引位置截取子字符串,直到字符串的末尾
// public String substring(int beginIndex)String str = "Hello World";System.out.println(str.substring(6));   // 输出:World// 从指定索引位置截取子字符串,直到索引endIndex-1处的字符,不包含endIndex索引字符
// public String substring(int beginIndex,int endIndex)
System.out.println(str.substring(6,10));  // 输出:Worl

substring方法可以和indexOf方法结合使用,先查找是否存在特定的字符或子字符串,在得到索引后开始截取。

String str = "Will Smith";
int index = str.indexOf("Smith");  // indexOf方法查找到子字符串“Smith”存在,返回字符“S”的位置
if (index != -1) {System.out.println(str.substring(index,index+"Smith".length()));  // 输出Smith
}

(6)分割字符串

public String[] split(String regex)

参数regex是用于进行匹配的正则表达式字符串,split方法根据参数regex返回一个保存了拆分后的各个字符串的数组。

String str = "zhansan,lisi,wangwu,zhaoliu";
String[] names = str.split(",");for (String name : names) {System.out.println(name);
}

 输出如下:

zhansan
lisi
wangwu
zhaoliu

(7)替换字符或字符串

应用中替换字符串的部分内容是特别常见的。例如在某个字符串中含有敏感信息,或者不合规的字符串序列,在向用户显示时可以替换为*号。String类有两个重载的replace方法,一个用于替换字符,一个用于替换字符串。

  • public String replace(char oldChar,char newChar)

用newChar替换字符串中所有的oldChar,并返回替换后的字符串。如果oldChar在这个String对象表示的字符串序列中没有出现,则直接返回该对象的引用,否则返回一个替换后的新的String对象。

  • public String replace(CharSequence target , CharSequence replacement)

用replacement指定的字符序列替换字符串中出现的target字符序列。

String类中还有两个使用正则表达式来匹配要替换的字符串的方法:

  • public String replaceFirst(String regex,String replacement)

用replacement替换此字符串匹配给定的正则表达式(regax)的第一个子串。

  • public String replcceAll(String regex,String replacement)

用replacement替换此字符串匹配给定的正则表达式(regax)的所有子串。

String str = "habcjkmkabc";
Syttem.out.println(str.replaceFirst("abc","def");  // 输出:hdefjkmkabc
Syttem.out.println(str.replaceAll("abc","def");    // 输出:hdefjkmkdef

上面没有使用到正则表达式。

(8)合并字符串

在String类中有一个静态方法join,可以通过指定一个分隔符来合并字符串。

  • public static String join(CharSequence delimiter, CharSequence... elements)
  • delimited:分割字符串的分隔符
  • elements:是变长参数,可以传入任意多个字符串
String names = String.join(",", "张山","李四","王二");
System.out.println(names);   // 输出:张山,李四,王二

(9)重复字符串

String str = "abc";
System.out.println(str.repeat(5));  //输出abcabcabcabcabc
  • public String repeat(int count)

将字符串重复参数count指定的次数,并串联起来返回一个新的字符串。

(10)大小写转换

  • public String toLowerCase()  :把字符串全部字符都转换为小写
  • public String toUpperCase()  :把字符串全部字符都转换为大写

Java没有提供首字母转为大写或小写方法,可以使用substring()和上面的方法结合实现相应的功能:

public class Main {  public static void main(String[] args) {  String word = "hello";  System.out.println(capitalizeFirstLetter(word));  // 输出 "Hello"  System.out.println(uncapitalizeFirstLetter(word)); // 输出 "hello"  }  // 把首字母大写  public static String capitalizeFirstLetter(String original) {  if (original == null || original.length() == 0) {  return original;  }  return original.substring(0, 1).toUpperCase() + original.substring(1);  }  // 把首字母小写  public static String uncapitalizeFirstLetter(String original) {  if (original == null || original.length() == 0) {  return original;  }  return original.substring(0, 1).toLowerCase() + original.substring(1);  }  
}

(11)去掉字符串的首尾空白

空白包含空格、制表符、换行、换页和回车,在字符串中属于合法的字符,但是字符串首尾的空白通常是没有用的,一般是误输入产生的。调用String类的trim()方法可以去掉:

public String trim()    // 删除首尾空白

public String strip()   // 删除首尾空白

public String stripLeading()   // 删除首空白

public String stripTrailing()     // 删除尾空白

trim()方法删除的空白是其Unicode字符集中小于等于U+0020的任何字符,而strip方法删除的是java.lang.Character类的静态方法isWhiteSpace(int codePoint)判断为true的空白字符,略有不同。

(12)判断字符串是否为空

要判断一个字符串是否为空字符串(注意不是null,null代表一个变量未指向任何的对象),可以根据字符串的长度来判断,若长度为0,则为空字符串。String类提供了isEmpty、isBlank方法如下:

public boolean isEmpty()

public boolean isBlank()

如果字符串中只有空白字符,则isEmpty()返回的是false,即字符串不为空,因为是判断字符串的长度。

如果字符串为空,或者只是包含空白字符,isBlank()方法返回true

public class StringCompareTo {public static void main(String[] args) {String str1 = "\t \n";System.out.println(str1.length());    // 输出:3System.out.println(str1.isEmpty());   // 输出:falseSystem.out.println(str1.isBlank());   // 输出:true}
}

(13)提取字符串行流

某些字符串由多个子串组成,子串之间以行终止符分隔,行终止符可以是换行(\n)、回车(\r),或者回车换行(\r\n)。Java11新增了一个lines方法,可以根据行终止符从字符串中提取行流,该方法如下:

public Stream<String>  lines()

import java.util.stream.Stream;public class StringCompareTo {public static void main(String[] args) {String str = "zhangsan\nlisi\rwanger\r\nzhaoliu";Stream<String> stream = str.lines();stream.forEach(subStr -> System.out.println(subStr));}
}

输出结果是:

zhangsan
lisi
wanger
zhaoliu 

(14)与字节数组相互转换

在Java I/O和网络编程中,经常需要将字节数组和字符串进行相互转换,常用的转换方法如下:

public String(byte[] bytes)

使用平台默认字符集解码指定的字节数组来构造字符串

public String(byte[] bytes, int offset, int length)

使用平台默认的字符集解码bytes数组,从offset索引位置开始,length数量的字节来构造字符串

public byte[] getBytes()

使用平台默认字符集将此字符串编码为一个字节序列,并将结果存储到新的字节数组中。

public class StringCompareTo {public static void main(String[] args) {byte[] buf = new byte[]{97,98,99};String str = new String(buf);System.out.println(str);             // 输出abc//buf = str.getBytes();for (int i=0; i<buf.length; i++) {System.out.print(buf[i] + "\t");}}
}

输出:

abc

97    98    99 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/753636.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

.NET高级面试指南专题十八【 外观模式模式介绍,提供了简化的接口,隐藏系统的复杂性】

介绍&#xff1a; 外观模式是一种结构设计模式&#xff0c;它提供了一个统一的接口&#xff0c;用于访问子系统中的一组接口。外观模式定义了一个高层接口&#xff0c;使得子系统更容易使用。 原理&#xff1a; 外观类&#xff08;Facade Class&#xff09;&#xff1a;提供了一…

如何用Python搭建聊天室

项目实战&#xff08;服务器端&#xff09; 1.服务器类 首先需要一个聊天服务器&#xff0c;这里继承asyncore的dispatcher类来实现&#xff0c;代码如下 class ChatServer(dispatcher):"""聊天服务器"""def __init__(self, port):dispatcher…

使用verilog设计有限状态机实现的跳一跳游戏及其testbench仿真测试

设计跳一跳游戏的有限状态机可以分为以下几个主要步骤: 确定状态及状态转移条件: 确定游戏中可能存在的状态,如等待开始、准备跳跃、跳跃中、检查落地等。 确定不同状态之间的转移条件,例如何时从等待开始状态转移到准备跳跃状态,如何触发跳跃动作,跳跃是否成功等。 定…

可视化场景(5):生产监控,比摄像头好用多了。

hello&#xff0c;我是贝格前端工场&#xff0c;本期分享可视化大屏在生产监控场景的应用&#xff0c;如需要定制&#xff0c;可以与我们联络&#xff0c;开始了。 实时监控 可视化大屏可以实时展示生产线上的各种关键指标和数据&#xff0c;如生产速度、设备状态、产量、质量…

html密码访问单页自定义跳转页面源码

内容目录 一、详细介绍二、效果展示1.部分代码2.效果图展示 三、学习资料下载 一、详细介绍 密码访问单页自定义跳转页面&#xff0c;修改了的密码访问单页&#xff0c;添加了js自定义密码跳转页面。需要正确输入密码才能跳转目标网址。 二、效果展示 1.部分代码 代码如下&…

亚马逊、速卖通如何实现批量注册自动养号?

亚马逊和速卖通作为全球领先的跨境电商平台&#xff0c;其账号对于卖家而言具有重要的商业价值。随着跨境电商行业的蓬勃发展&#xff0c;越来越多的人对亚马逊、速卖通账号的需求日益增长&#xff0c;这也催生了批量注册和自动养号的需求。 跨境智星作为一款集成了批量注册账号…

JAVA基础 数组,字符串与正则表达式

数组 数组的概念 将相同类型的数据按一定顺序排列构成的大小确定的集合 数组元素类型可以为基本数据类型&#xff0c;也可以为引用类型 Java语言内存分配 栈内存&#xff1a;基本数据类型的变量或者引用类型的变量&#xff0c;超出作用域将自动释放 堆内存&#xff1a;存…

每日五道java面试题之mybatis篇(二)

目录&#xff1a; 第一题. Mybatis优缺点第二题. Hibernate 和 MyBatis 的区别?第三题. MyBatis编程步骤是什么样的&#xff1f;第四题. 请说说MyBatis的工作原理第五题. MyBatis的功能架构是怎样的? 第一题. Mybatis优缺点 优点 与传统的数据库访问技术相比&#xff0c;ORM…

Leetcode 3.18

Leetcode hot100 二叉树1.路径总和 III2.路径总和 II3.二叉树的所有路径4.二叉树的最近公共祖先 回溯1.电话号码的字母组合 二叉树 1.路径总和 III 路径总和 III 思路&#xff1a;我们访问每一个节点 node&#xff0c;检测以 node 为起始节点且向下延深的路径有多少种。递归遍…

【Linux】Ubuntu22.04中使用ssh、scp时报错:Their offer: ssh-rsa

1、问题描述 使用scp拷贝文件时报错: Unable to negotiate with xxx port 22: no matching host key type found. Their offer: ssh-rsa lost connection2、原因分析 查看OpenSSH版本 ssh -V OpenSSH_8.9p1 Ubuntu-3ubuntu0.6, OpenSSL 3.0.2 15 Mar 2022查看官网的说明:…

【ACL2023获奖论文】比你想的更弱:对弱监督学习的批判性审视

【ACL 2023获奖论文】主题论文奖&#xff1a;7.Weaker Than You Think: A Critical Look at Weakly Supervised Learning 写在最前面引言正文问题1&#xff1a;对WSL来说&#xff0c;clean data是否必要&#xff1f;问题2&#xff1a;WSL需要多少的clean data&#xff1f;问题3…

elasticsearch基础学习

elasticsearch简介 什么是elasticsearch elasticsearch&#xff08;简称es&#xff09;&#xff0c;其核心是 Elastic Stack&#xff0c;es是一个基于 Apache Lucene&#xff08;TM&#xff09;的开源的高扩展的分布式全文检索引擎&#xff0c;它可以近乎实时的存储、检索数据…

如何在开放麒麟系统安装cpolar内网穿透实现公网环境下SSH远程连接

文章目录 1. 安装SSH服务2. 本地SSH连接测试3. openKylin安装Cpolar4. 配置 SSH公网地址5. 公网远程SSH连接小结 6. 固定SSH公网地址7. SSH固定地址连接 openKylin是中国首个基于Linux 的桌面操作系统开发者平台&#xff0c;通过开放操作系统源代码的方式&#xff0c;打造具有自…

裸金属租赁的意义

裸金属&#xff0c;这个名词听起来好“硬核”&#xff0c;如果对于一个新手来讲&#xff0c;怎么也不会将这个概念和IT行业、计算机、服务器等内容进行关联&#xff0c;它可能更应该是工业领域的一种产品或者物质&#xff0c;可真正关联到其实际概念恰恰与当前的主流行业如&…

论文阅读——Align before Fuse

Align before Fuse: Vision and Language Representation Learning with Momentum Distillation image-text contrastive learning(ITC)用在单模态&#xff0c;masked language modeling (MLM) and image-text matching (ITM) 用在多模态。 单模态编码器的表示上引入了中间图像…

机器学习中的基础问题总结

介绍&#xff1a;总结面试经常问到的一些机器学习知识点&#xff08;必会&#x1f31f;&#xff09; 基础知识点梳理 模型评估一、L1、L2正则化1、L1正则与L2正则有何不同&#xff1f;2、为什么正则化可以防止过拟合&#xff1f;3、为什么L1正则具有稀疏性&#xff1f;&#xf…

JMeter之IP欺骗技术(模拟不同的IP地址并发请求)

我们在做压力测试时&#xff0c;有这样的场景和需求&#xff0c;希望模拟的批量用户来自不同的IP地址。如果小伙伴用LR是很容易实现的&#xff0c;用IP欺骗即可实现。那么对于用JMeter小伙伴是不是就不能享受这一技术了呢&#xff0c;答案是否定的&#xff0c;JMeter一样可以实…

【晴问算法】入门篇—贪心算法—整数配对

题目描述 有两个正整数集合S、T&#xff0c;其中S中有n个正整数&#xff0c;T中有m个正整数。定义一次配对操作为&#xff1a;从两个集合中各取出一个数a和b&#xff0c;满足a∈S、b∈T、a≤b&#xff0c;配对的数不能再放回集合。问最多可以进行多少次这样的配对操作。 输入描…

Elasticsearch:调整近似 kNN 搜索

在我之前的文章 “Elasticsearch&#xff1a;调整搜索速度”&#xff0c;我详细地描述了如何调整正常的 BM25 的搜索速度。在今天的文章里&#xff0c;我们来进一步探讨如何提高近似 kNN 的搜索速度。希望对广大的向量搜索开发者有一些启示。 Elasticsearch 支持近似 k 最近邻…

一、yocto 编译raspberrypi 4B并启动

yocto 编译raspberrypi 4B并启动 yocto 编译raspberrypi 4B并启动环境准备代码下载编译及配置烧录 yocto 编译raspberrypi 4B并启动 本篇文章为基于raspberrypi 4B单板的yocto实战系列的开篇之作。 环境准备 最近到手一个树莓派4B&#xff0c;准备拿来玩一玩&#xff0c;下面…