String 类继承自 Object 超类,实现的接口有:Serializable、CharSequence、Comparable<String> 接口,具体如下图:

一、常用的String 类构造方法

 //1.由字符串original复制得到新的字符串
public String(String original) {
this.value = original.value;
this.hash = original.hash;
}
//2.得到值等于value的字符串
public String(char[] value) {
this.value = Arrays.copyOf(value, value.length);
}
//3.返回字符串从第i个位置起的前j个字符
public String(char[] value, int offset, int count) {
//判断索引i是否合法
if (offset < 0) {
throw new StringIndexOutOfBoundsException(offset);
}
//判断计数值是否合法
if (count <= 0) {
if (count < 0) {
throw new StringIndexOutOfBoundsException(count);
}
//如果计数值等于0,返回的是空字符
if (offset <= value.length) {
this.value = "".value;
return;
}
}
//索引值>字符串长度-计数值,抛异常
if (offset > value.length - count) {
throw new StringIndexOutOfBoundsException(offset + count);
}
//其余情况返回要求值
this.value = Arrays.copyOfRange(value, offset, offset+count);
}

二、关于equals方法的理解

  首先,我们看在Object类中equals方法如下这样写的,this指代调用者对象。

 public boolean equals(Object var1) {
return this == var1;
}

  接下来,我们瞅一下在String中equals方法是怎样的呢,好的上源代码:

    public boolean equals(Object anObject) {
//首先,直接比较两个对象是否相等,若相等就直接返回true
if (this == anObject) {
return true;
}
//判断传入的参数是否是String类的实例
if (anObject instanceof String) {
//如果是String的实例,直接强转为String
String anotherString = (String)anObject;
int n = value.length;
//判断传入的对象与比较的对象的长度是否一样
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
//逐个遍历两个对象中的对应位置的字符进行比较
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}

  由上面我们可以知道了,两个字符串的比较是通过equals方法进行的,比较的顺序是:

  首先,去比较两个字符串是否是同一个对象,如果是同一个对象则直接返回true;

  如果不是同一个对象,会再判断是否是一个String的实例,如果是就会再比较两个字符串的长度是否相等,若相等了,就会再去对两个字符对应位置的字符逐个进行比较,如果全部相等则返回true。

  这里提到了equals方法的比较,就要对 “==”来进行一个区分比较。

  “==”是用来进行操作数的值之间的比较,对基本数据类型,变量本身存储值,但是引用类型,变量本身存的是对象的地址,比较的是两个对象的地址是否相等。

  String类代表的字符串,Java中所有的字符串都是以它为模板创建的对象。字符串一经创建是不可改变的。也就是说“abc”不可以再变成“abcd”。这就要求我们使用String的时候应该注意:尽量不要做字符串频繁的拼接操作。因为字符串一旦创建不可改变,只要频繁拼接,就会在字符串常量池中创建大量的字符串对象,给垃圾回收带来问题。

  

为了提升字符串的访问效率,在程序中使用了缓冲技术,所有被双引号括起来的字符串都会在JVM运行时数据区的字符串常量池中新建一份,(字符串常量池存储在方法区中)。如果程序中用到“abc”,会先在字符串常量池中查找有没有该字符串,如果找到直接拿来用,找不到就在字符串常量池中新建一个"abc"。

如下的代码,判断两个字符串是否相等:

String A="a";
String B="a";
System.out.println(A==B); //true

前面提到过“==”是用来比较值相等。程序中第一次出现"a"时,先在字符串常量池中新建一个字符串"a"对象,A指向该对象,当程序中再次出现"a"时,会先在字符串常量池中查找,发现已经创建了"a",于是直接拿来用了,使用B指向,也就是A,B引用指向的是同一对象,所以打印输出true。

再来看看String中的构造方法:

这个方法是初始化新创建的String对象,使其表示与参数相同的字符序列,换句话说,新创建的字符串时参数字符串的副本。

看下面代码,判断是否相等:

String C=new String("a");
String D=new String("a");
System.out.println(C==D); //false

参数字符串“a”对象,创建之前先在字符串常量池中查找有没有该对象,没有则创建;然后构造方法String(String original)以"a"为参数,new出两个对象存在堆中,C和D引用分别指向这两个对象,很明显C和D引用指向的是两个不同的对象,即上面这两行代码创建了三个不同的对象,方法区中一个,堆中两个。

2.字符串的模式匹配

子串在主串中的定位操作称为串的模式匹配,串的模式匹配应该算串的重要操作之一。来看看朴素的模式匹配算法。

根据要求从主串的第i个位置开始遍历。子串从第0个位置开始,如果相应位置的字符相等,则主串子串各向后移动一位判断下一位字符,如果不等,主串回到匹配位置的下一位,子串从0位开始,循环遍历,直到找到子串,最后返回子串在主串中的索引。简单地说,就是对主串的每一个字符作为子串开头,与要匹配的字符串进行匹配,这种匹配方式称为朴素的模式匹配算法。实现代码如下:


package com.java.String;
/*
* 串的模式匹配
* */
public class IndexTest {
public static void main(String[] args){
int s=indexSearch("eateqweapple","app",8);
System.out.println(s);
}
//朴素的模式匹配算法,返回子串T在主串S中第pos个字符之后的位置
public static int indexSearch(String S,String T,int pos){
//默认值规定为0
int index=0;
int Slen=S.length();
int Tlen=T.length();
//S位置下标
int i=pos;
//T位置下标
int j=0;
while((i<Slen)&&(j<Tlen)){
char s=S.charAt(i);
char t=T.charAt(j);
if(s==t){
//如果当前位置的相等,都各加1比较下一位置
i=i+1;
j=j+1;
}else{
//否则回到主串S匹配的下一位置,子串从头开始
i=i+1;
j=0;
}
if(j>Tlen-1){
index=i-Tlen;
}
}
return index;
}
}

算法复杂度分析:

最好的情况,一开始就匹配成功,算法复杂度为O(1); 稍微差一些,每次匹配都是首字母不匹配,但遍历到主串的最后位置匹配成功,算法复杂度为O(n+m);最坏的情况,每次匹配不成功都是发生在子串的最后一个字符,时间复杂度为O((n-m+1)*m)。

朴素的模式匹配算法算很简单的解决子串定位问题的算法了。想一想Java底层那些封装好的方法,我们真是站在了巨人的肩膀上。

具体参考文章地址:

https://www.javazhiyin.com/28611.html

关于String类学习的一些笔记(本文参考来自程序员考拉的文章)的更多相关文章

  1. java中String类学习笔记

    1.String的两种实例化方式 String str="hello";//直接赋值的方式: String str=new String("hello");// ...

  2. 《C++ Primer Plus》16.1 string类 学习笔记

    16.1.1 构造字符串程序清单16.1使用了string的7个构造函数.程序清单16.1 str1.cpp---------------------------------------------- ...

  3. java中String类学习

    java中String类的相关操作如下: (1)初始化:例如,String s = “abc”; (2)length:返回字符串的长度. (3)charAT:字符操作,按照索引值获得字符串中的指定字符 ...

  4. C++ string类学习总结

    C++字符串技术 string类  string对象在大多数应用中被用来消除对char*指针的使用,支持所期望的一些操作; 可以转换成char*,保持和现代代码的兼容性,还能自动处理内存管理; 一些s ...

  5. 【阅读笔记】《C程序员 从校园到职场》第八章 算法和协议(Part 2)

    原文链接: 让你提前认识软件开发(19):C语言中的协议及单元测试示例 CSDN博客 https://blog.csdn.net/zhouzhaoxiong1227/article/details/2 ...

  6. Android群英传神兵利器读书笔记——第一章:程序员小窝——搭建高效的开发环境

    1.1 搭建高效的开发环境之操作系统 1.2 搭建开发环境之高效配置 基本环境配置 基本开发工具 1.3 搭建程序员的博客平台 开发者为什么要写作 写作平台 第三方博客平台 自建博客平台 开发论坛 1 ...

  7. 【阅读笔记】《C程序员 从校园到职场》第七章 指针和结构体

    原文地址:让你提前认识软件开发(13):指针及结构体的使用 CSDN博客 https://blog.csdn.net/zhouzhaoxiong1227/article/details/2387299 ...

  8. 【阅读笔记】《C程序员 从校园到职场》第五章 内存操作

    参考:   让你提前认识软件开发(8):memset()与memcpy()函数  https://blog.csdn.net/zhouzxi/article/details/22478081 让你提前 ...

  9. Android开发之数组类的面试题目,android工程师java程序员必备

    1,定义一个长度为5的数组 int [] arr=new int[5]; 2,写出静态初始化一个数组的方法 int [] arr={1,2,3,4}; 3,写出可变参数的使用规则    1,只能做为方 ...

随机推荐

  1. Linux命令:source

    语法 source filename 说明 . 的同义词

  2. 【Debug】IAR在线调试时报错,Warning: Stack pointer is setup to incorrect alignmentStack,芯片使用STM32F103ZET6

    解决办法: Option >Debugger >Download>勾选 Use flash loader 即可,后续取消勾也不再出现报错!

  3. repo

    repo init -b remoteBranchName repo sync repo start localBranchName --all 整体切分支 if error is tagger cl ...

  4. el-input的color修改无效问题

    相信很多前端初学者跟我一样也遇到过el-input的color修改无效问题 如下图:我想把el-input里面的文字改成蓝色,但是使用总是失败 修改方法:打开调试界面,找到el-input对应的sty ...

  5. Tomcat的三种安装方式:解压版、安装版、配置成Windows服务版

    https://blog.csdn.net/Jessica_XLF/article/details/81711429

  6. SpringCloud-day05-服务调用Ribbon

    6.服务调用Ribbon 6.1Ribbon简介 前面讲了eureka服务注册与发现,但是结合eureka集群的服务调用并没有谈到.这里就要用到Ribbon,结合eureka,来实现服务的调用: Ri ...

  7. Dubbo 的配置主要分为三大类

    服务发现.服务治理和性能调优:这三类配置不是独立存在的,而是贯穿在所有配置项中的,比如dubbo:service 标签中的interface 是服务发现类, timeout是性能调优类, mock 是 ...

  8. React Router的Route的使用

    Route 是 React Router中用于配置路由信息的组件,每当有一个组件需要根据 URL 决定是否渲染时,就需要创建一个 Route. 1) path 每个 Route 都需要定义一个 pat ...

  9. View控件跟随鼠标移动

    public boolean onTouch(View view, MotionEvent motionEvent) { if(motionEvent.getAction() == MotionEve ...

  10. 微信小程序获取二维码参数

    var scene = decodeURIComponent(options.scene)