首页编程java编程java equalsignorecase性能 javacomparator

java equalsignorecase性能 javacomparator

编程之家2026-06-041110次浏览

其实java equalsignorecase性能的问题并不复杂,但是又很多的朋友都不太了解javacomparator,因此呢,今天小编就来为大家分享java equalsignorecase性能的一些知识,希望可以帮助到大家,下面我们一起来看看这个问题的分析吧!

java equalsignorecase性能 javacomparator

使用Java 正则表达式精确验证 "true" 和 "false" 值

在 Java中,若需精确验证字符串是否为"true"或"false",推荐使用 String.equals()方法进行直接比较,而非正则表达式。这种方法简洁高效,能完全避免误判,且易于理解和维护。

核心实现方案public static Boolean isValidAcceptanceField(String acceptanceValue){ return"true".equals(acceptanceValue)||"false".equals(acceptanceValue);}"true".equals(acceptanceValue):严格检查输入是否完全匹配字符串"true"。"false".equals(acceptanceValue):严格检查输入是否完全匹配字符串"false"。||(逻辑或):任一条件满足即返回 true,否则返回 false。关键注意事项空指针异常(NullPointerException)若输入为 null,直接调用 equals()会抛出异常。需添加判空逻辑:

public static Boolean isValidAcceptanceField(String acceptanceValue){ if(acceptanceValue== null){ return false;//或根据需求抛出异常} return"true".equals(acceptanceValue)||"false".equals(acceptanceValue);}大小写敏感问题默认比较是大小写敏感的(如"True"或"FALSE"会返回 false)。若需忽略大小写,改用 equalsIgnoreCase():

public static Boolean isValidAcceptanceFieldIgnoreCase(String acceptanceValue){ if(acceptanceValue== null){ return false;} return"true".equalsIgnoreCase(acceptanceValue)||"false".equalsIgnoreCase(acceptanceValue);}为什么避免正则表达式?性能开销:正则表达式需编译和匹配,复杂度高于直接比较。误判风险:若正则设计不严谨(如 ^t.*e$),可能误匹配"tttrue"或"falseeee"。代码冗余:简单场景下,正则表达式会引入不必要的复杂性。完整示例代码public class BooleanValidator{//严格匹配(大小写敏感,处理null) public static Boolean isValidAcceptanceField(String acceptanceValue){ if(acceptanceValue== null){ return false;} return"true".equals(acceptanceValue)||"false".equals(acceptanceValue);}//忽略大小写匹配(处理null) public static Boolean isValidAcceptanceFieldIgnoreCase(String acceptanceValue){ if(acceptanceValue== null){ return false;} return"true".equalsIgnoreCase(acceptanceValue)||"false".equalsIgnoreCase(acceptanceValue);} public static void main(String[] args){//测试严格匹配 System.out.println(isValidAcceptanceField("true"));// true System.out.println(isValidAcceptanceField("false"));// true System.out.println(isValidAcceptanceField("tttrue"));// false System.out.println(isValidAcceptanceField(null));// false//测试忽略大小写 System.out.println(isValidAcceptanceFieldIgnoreCase("TRUE"));// true System.out.println(isValidAcceptanceFieldIgnoreCase("FaLse"));// true System.out.println(isValidAcceptanceFieldIgnoreCase("Truee"));// false}}总结优先使用 String.equals():适用于精确匹配"true"/"false"的场景,代码简洁且高效。处理边界情况:始终检查 null输入,避免异常。按需选择大小写敏感:根据业务需求决定是否使用 equalsIgnoreCase()。避免正则表达式:除非有特殊需求(如部分匹配、复杂模式),否则直接比较是最佳实践。

Java SE 6 新特性: Java DB&n

年底 Sun公司发布了 Java Standard Edition(Java SE)的最终正式版代号 Mustang(野马)跟 Tiger(Java SE)相比 Mustang在性能方面有了不错的提升与 Tiger在 API库方面的大幅度加强相比虽然 Mustang在 API库方面的新特性显得不太多但是也提供了许多实用和方便的功能在脚本 WebService XML编译器 API数据库 JMX网络和 Instrumentation方面都有不错的新特性和功能加强本系列文章主要介绍 Java SE在 API库方面的部分新特性通过一些例子和讲解帮助开发者在编程实践当中更好的运用 Java SE提高开发效率

本文是系列文章的第篇介绍了 Java SE在数据库编程方面的新特性

java equalsignorecase性能 javacomparator

Java DB Java里的数据库

新安装了 JDK的程序员们也许会发现除了传统的 bin jre等目录 JDK新增了一个名为 db的目录这便是 Java的新成员 Java DB这是一个纯 Java实现开源的数据库管理系统(DBMS)源于 Apache软件基金会(ASF)名下的项目 Derby它只有 MB大小对比动辄上 G的数据库来说可谓袖珍但这并不妨碍 Derby功能齐备支持几乎大部分的数据库应用所需要的特性更难能可贵的是依托于 ASF强大的社区力量 Derby得到了包括 IBM和 Sun等大公司以及全世界优秀程序员们的支持这也难怪 Sun公司会选择其版本纳入到 JDK中作为内嵌的数据库这就好像为 JDK注入了一股全新的活力 Java程序员不再需要耗费大量精力安装和配置数据库就能进行安全易用标准并且免费的数据库编程在这一章中我们将初窥 Java DB的世界来探究如何使用它编写出功能丰富的程序

Hello Java DB内嵌模式的Derby

既然有了内嵌(embedded)的数据库就让我们从一个简单的范例(代码在清单中列出)开始试着使用它吧这个程序做了大多数数据库应用都可能会做的操作在 DBMS中创建了一个名为 helloDB的数据库创建了一张数据表取名为 hellotable向表内插入了两条数据然后查询数据并将结果打印在控制台上最后删除表和数据库释放资源

清单 HelloJavaDB的代码

public class HelloJavaDB{ public static void main(String[] args){ try{// load the driver Class forName( apache derby jdbc EmbeddedDriver) newInstance(); System out println( Load the embedded driver); Connection conn= null; Properties props= new Properties(); props put( user user); props put( password user);//create and connect the database named helloDB conn=DriverManager getConnection( jdbc:derby:helloDB;create=true props); System out println( create and connect to helloDB); conn setAutoCommit(false);// create a table and insert o records Statement s= conn createStatement(); s execute( create table hellotable(name varchar() score int)); System out println( Created table hellotable); s execute( insert into hellotable values( Ruth Cao)); s execute( insert into hellotable values( Flora Shi));// list the o records ResultSet rs= s executeQuery( SELECT name score FROM hellotable ORDER BY score); System out println( name\t\tscore); while(rs next()){ StringBuilder builder= new StringBuilder(rs getString()); builder append( \t); builder append(rs getInt()); System out println(builder toString());}// delete the table s execute( drop table hellotable); System out println( Dropped table hellotable); rs close(); s close(); System out println( Closed result set and statement); mit(); conn close(); System out println( Committed transaction and closed connection); try{// perform a clean shutdown DriverManager getConnection( jdbc:derby:;shutdown=true);} catch(SQLException se){ System out println( Database shut down normally);}} catch(Throwable e){// handle the exception} System out println( SimpleApp finished);}}

java equalsignorecase性能 javacomparator

随后我们在命令行(本例为 Windows平台当然其它系统下稍作改动即可)下键入以下命令

清单运行 HelloJavaDB命令

java–cp;%JAVA_HOME%\db\lib\derby jar HelloJavaDB

程序将会按照我们预想的那样执行图是执行结果的一部分截屏

图 HelloJavaDB程序的执行结果

上述的程序和以往没什么区别不同的是我们不需要再为 DBMS的配置而劳神因为 Derby已经自动地在当前目录下新建了一个名为 helloDB的目录来物理地存储数据和日志需要做的只是注意命名问题在内嵌模式下驱动的名字应为 apache derby jdbc EmbeddedDriver创建一个新数据库时需要在协议后加入 create=true另外关闭所有数据库以及 Derby的引擎可以使用以下代码

清单关闭所有数据库及 Derby引擎

DriverManager getConnection( jdbc:derby:;shutdown=true);

如果只想关闭一个数据库那么则可以调用

清单关闭一个数据库

DriverManager getConnection( jdbc:derby:helloDB;shutdown=true);

这样使用嵌入模式的 Derby维护和管理数据库的成本接近于这对于希望专心写代码的人来说不失为一个好消息然而有人不禁要问既然有了内嵌模式为什么大多数的 DBMS都没有采取这样的模式呢?不妨做一个小实验当我们同时在两个命令行窗口下运行 HelloJavaDB程序结果一个的结果与刚才一致而另一个却出现了错误如图所示

图内嵌模式的局限

错误的原因其实很简单在使用内嵌模式时 Derby本身并不会在一个独立的进程中而是和应用程序一起在同一个 Java虚拟机(JVM)里运行因此 Derby如同应用所使用的其它 jar文件一样变成了应用的一部分这就不难理解为什么在 classpath中加入 derby的 jar文件我们的示例程序就能够顺利运行了这也说明了只有一个 JVM能够启动数据库而两个跑在不同 JVM实例里的应用自然就不能够访问同一个数据库了

鉴于上述的局限性和来自不同 JVM的多个连接想访问一个数据库的需求下一节将介绍 Derby的另一种模式网络服务器(Neork Server)

网络服务器模式

如上所述网络服务器模式是一种更为传统的客户端/服务器模式我们需要启动一个 Derby的网络服务器用于处理客户端的请求不论这些请求是来自同一个 JVM实例还是来自于网络上的另一台机器同时客户端使用 DRDA(Distributed Relational Database Architecture)协议连接到服务器端这是一个由 The Open Group倡导的数据库交互标准图说明了该模式的大体结构

由于 Derby的开发者们努力使得网络服务器模式与内嵌模式之间的差异变小使得我们只需简单地修改清单中的程序就可以实现如清单所示我们在 HelloJavaDB中增添了一个新的函数和一些字符串变量不难看出新的代码只是将一些在上一节中特别指出的字符串进行了更改驱动类为 apache derby jdbc ClientDriver而连接数据库的协议则变成了 jdbc:derby://localhost:/这是一个类似 URL的字符串而事实上 Derby网络的客户端的连接格式为 jdbc:derby://server[:port]/databaseName[;attributeKey=value]在这个例子中我们使用了最简单的本地机器作为服务器而端口则是 Derby默认的端口

图 Derby网络服务器模式架构

清单网络服务器模式下的 HelloJavaDB

public class HelloJavaDB{ public static String driver= apache derby jdbc EmbeddedDriver; public static String protocol= jdbc:derby:; public static void main(String[] args){// same as before} private static void parseArguments(String[] args){ if(args length==|| args length>){ return;} if(args[ ] equalsIgnoreCase( derbyclient)){ framework= derbyclient; driver= apache derby jdbc ClientDriver; protocol= jdbc:derby://localhost:/;}}}

当然仅仅有客户端是不够的我们还需要启动网络服务器 Derby中控制网络服务器的类是 apache derby drda NeorkServerControl因此键入以下命令即可如果想了解 NeorkServerControl更多的选项只要把 start参数去掉就可以看到帮助信息了关于网络服务器端的实现都被 Derby包含在 derbynet jar里

清单启动网络服务器

java cp; C:\Program Files\Java\jdk \db\lib\derby jar; C:\Program Files\Java\jdk \db\lib\derbynet jar apache derby drda NeorkServerControl start

相对应的网络客户端的实现被包含在 derbyclient jar中所以只需要在 classpath中加入该 jar文件修改后的客户端就可以顺利地读取数据了再一次尝试着使用两个命令行窗口去连接数据库就能够得到正确的结果了如果不再需要服务器那么使用 NeorkServerControl的 shutdown参数就能够关闭服务器

更多

至此文章介绍了 Java SE中的新成员 Java DB(Derby)也介绍了如何在内嵌模式以及网络服务器模式下使用 Java DB当然这只是浅尝辄止更多高级的选项还需要在 Sun和 Derby的文档中寻找在这一章的最后我们将简单介绍几个 Java DB的小工具来加快开发速度它们都位于 apache derby tools包内在开发过程中需要获取信息或者测试可以用到

ij一个用来运行 SQL脚本的工具 dblook为 Derby数据库作模式提取(Schema extraction)生成 DDL的工具 sysinfo显示系统以及 Derby信息的工具类 JDBC新功能新 API

如果说上一章介绍了 Java中的一个新成员它本来就存在但是没有被加入进 JDK那么这一章我们将关注在 JDBC中又增加了哪些新功能以及与之相对应的新 API

自动加载驱动

在 JDBC之前编写 JDBC程序都需要加上以下这句有点丑陋的代码

清单注册 JDBC驱动

Class forName( apache derby jdbc EmbeddedDriver) newInstance();

Java sql DriverManager的内部实现机制决定了这样代码的出现只有先通过 Class forName找到特定驱动的 class文件 DriverManager getConnection方法才能顺利地获得 Java应用和数据库的连接这样的代码为编写程序增加了不必要的负担 JDK的开发者也意识到了这一点从 Java开始应用程序不再需要显式地加载驱动程序了 DriverManager开始能够自动地承担这项任务作为试验我们可以将清单中的相关代码删除重新编译后在 JRE下运行结果和原先的程序一样

好奇的读者也许会问 DriverManager为什么能够做到自动加载呢?这就要归功于一种被称为 Service Provider的新机制熟悉 Java安全编程的程序员可能对其已经是司空见惯而它现在又出现在 JDBC模块中 JDBC的规范规定所有 JDBC的驱动 jar文件必须包含一个 java sql Driver它位于 jar文件的 META INF/services目录下这个文件里每一行便描述了一个对应的驱动类其实编写这个文件的方式和编写一个只有关键字(key)而没有值(value)的 properties文件类似同样地#之后的文字被认为是注释有了这样的描述 DriverManager就可以从当前在 CLASSPATH中的驱动文件中找到它应该去加载哪些类而如果我们在 CLASSPATH里没有任何 JDBC的驱动文件的情况下调用清单中的代码会输出一个 sun jdbc odbc JdbcOdbcDriver类型的对象而仔细浏览 JDK的目录这个类型正是在%JAVA_HOME%/jre/lib/resources jar的 META INF/services目录下的 java sql Driver文件中描述的也就是说这是 JDK中默认的驱动而如果开发人员想使得自己的驱动也能够被 DriverManager找到只需要将对应的 jar文件加入到 CLASSPATH中就可以了当然对于那些 JDBC之前的驱动文件我们还是只能显式地去加载了

清单罗列本地机器上的 JDBC驱动

Enumeration<Driver> drivers= DriverManager getDrivers();while(drivers hasMoreElements()){ System out println(drivers nextElement());}

RowId

熟悉 DB Oracle等大型 DBMS的人一定不会对 ROWID这个概念陌生它是数据表中一个隐藏的列是每一行独一无二的标识表明这一行的物理或者逻辑位置由于 ROWID类型的广泛使用 Java SE中新增了 java sql RowId的数据类型允许 JDBC程序能够访问 SQL中的 ROWID类型诚然不是所有的 DBMS都支持 ROWID类型即使支持不同的 ROWID也会有不同的生命周期因此使用 DatabaseMetaData getRowIdLifetime来判断类型的生命周期不失为一项良好的实践经验我们在清单的程序获得连接之后增加以下代码便可以了解 ROWID类型的支持情况

清单了解 ROWID类型的支持情况 DatabaseMetaData meta= conn getMetaData();System out println(meta getRowIdLifetime());

Java SE的 API规范中 java sql RowIdLifetime规定了种不同的生命周期 ROWID_UNSUPPORTED ROWID_VALID_FOREVER ROWID_VALID_OTHER ROWID_VALID_SESSION和 ROWID_VALID_TRANSACTION从字面上不难理解它们表示了不支持 ROWID ROWID永远有效等等具体的信息还可以参看相关的 JavaDoc读者可以尝试着连接 Derby进行试验会发现运行结果是 ROWID_UNSUPPORTED即 Derby并不支持 ROWID

既然提供了新的数据类型那么一些相应的获取更新数据表内容的新 API也在 Java中被添加进来和其它已有的类型一样在得到 ResultSet或者 CallableStatement之后调用 get/set/update方法得到/设置/更新 RowId对象示例的代码如清单所示

清单获得/设置 RowId对象

// Initialize a PreparedStatementPreparedStatement pstmt= connection prepareStatement( SELECT rowid name score FROM hellotable WHERE rowid=?);// Bind rowid into prepared statement pstmt setRowId( rowid);// Execute the statementResultSet rset= pstmt executeQuery();// List the recordswhile(rs next()){ RowId id= rs getRowId();// get the immutable rowid object String name= rs getString(); int score= rs getInt();}

鉴于不同 DBMS的不同实现 RowID对象通常在不同的数据源(datasource)之间并不是可移植的因此 JDBC的 API规范并不建议从连接 A取出一个 RowID对象将它用在连接 B中以避免不同系统的差异而带来的难以解释的错误而至于像 Derby这样不支持 RowId的 DBMS程序将直接在 setRowId方法处抛出 SQLFeatureNotSupportedException

SQLXML

SQL标准引入了 SQL/XML作为 SQL标准的扩展 SQL/XML定义了 SQL语言怎样和 XML交互如何创建 XML数据如何在 SQL语句中嵌入 XQuery表达式等等作为 JDBC的一部分 Java增加了 java sql SQLXML的类型 JDBC应用程序可以利用该类型初始化读取存储 XML数据 java sql Connection createSQLXML方法就可以创建一个空白的 SQLXML对象当获得这个对象之后便可以利用 setString setBinaryStream setCharacterStream或者 setResult等方法来初始化所表示的 XML数据以 setCharacterStream为例清单表示了一个 SQLXML对象如何获取 java io Writer对象从外部的 XML文件中逐行读取内容从而完成初始化

清单利用 setCharacterStream方法来初始化 SQLXML对象

SQLXML xml= con createSQLXML();Writer writer= xml setCharacterStream();BufferedReader reader= new BufferedReader(new FileReader( test xml));String line= null;while((line= reader readLine()!= null){ writer write(line);}

由于 SQLXML对象有可能与各种外部的资源有联系并且在一个事务中一直持有这些资源为了防止应用程序耗尽资源 Java提供了 free方法来释放其资源类似的设计在 java sql Array Clob中都有出现

至于如何使用 SQLXML与数据库进行交互其方法与其它的类型都十分相似可以参照 RowId一节中的例子在 Java SE的 API规范中找到 SQLXML中对应的 get/set/update方法构建类似的程序此处不再赘述

SQLExcpetion的增强

在 Java SE之前有关 JDBC的异常类型不超过个这似乎已经不足以描述日渐复杂的数据库异常情况因此 Java SE的设计人员对以 java sql SQLException为根的异常体系作了大幅度的改进首先 SQLException新实现了 Iterable<Throwable>接口清单实现了清单程序的异常处理机制这样简洁地遍历了每一个 SQLException和它潜在的原因(cause)

清单 SQLException的 for each loop

// Java codecatch(Throwable e){ if(e instanceof SQLException){ for(Throwable ex:(SQLException)e){ System err println(ex toString());}}}

此外图表示了全部的 SQLException异常体系除去原有的 SQLException的子类 Java中新增的异常类被分为种 SQLReoverableException SQLNonTransientException SQLTransientException在 SQLNonTransientException和 SQLTransientException之下还有若干子类详细地区分了 JDBC程序中可能出现的各种错误情况大多数子类都会有对应的标准 SQLState值很好地将 SQL标准和 Java类库结合在一起

图 SQLException异常体系

在众多的异常类中比较常见的有 SQLFeatureNotSupportedException用来表示 JDBC驱动不支持某项 JDBC的特性例如在 Derby下运行清单中的程序就可以发现 Derby的驱动并不支持 RowId的特性另外值得一提的是 SQLClientInfoException直接继承自 SQLException表示当一些客户端的属性不能被设置在一个数据库连接时所发生的异常

小结更多新特性与展望

在本文中我们已经向读者介绍了 Java SE中 JDBC最重要的一些新特性它们包括嵌在 JDK中的 Java DB(Derby)和 JDBC的一部分当然还有很多本文还没有覆盖到的新特性比如增加了对 SQL语言中 NCHAR NVARCHAR LONGNVARCHAR和 NCLOB类型的支持在数据库连接池的环境下为管理 Statement对象提供更多灵活便利的方法等

lishixinzhi/Article/program/Java/JSP/201311/19343

jave语言的string字符串有哪些特点

以主流的 JDK版本 1.8来说,String内部实际存储结构为 char数组,源码如下:

publicfinalclassString

implementsjava.io.Serializable,Comparable<String>,CharSequence{

//用于存储字符串的值privatefinalcharvalue[];

//缓存字符串的hashcodeprivateinthash;//Defaultto0

//......其他内容}

String源码中包含下面几个重要的方法。

1.多构造方法

String字符串有以下 4个重要的构造方法:

//String为参数的构造方法publicString(Stringoriginal){

this.value=original.value;

this.hash=original.hash;

}//char[]为参数构造方法publicString(charvalue[]){

this.value=Arrays.copyOf(value,value.length);

}//StringBuffer为参数的构造方法publicString(StringBufferbuffer){

synchronized(buffer){

this.value=Arrays.copyOf(buffer.getValue(),buffer.length());

}

}//StringBuilder为参数的构造方法publicString(StringBuilderbuilder){

this.value=Arrays.copyOf(builder.getValue(),builder.length());

}

其中,比较容易被我们忽略的是以 StringBuffer和 StringBuilder为参数的构造函数,因为这三种数据类型,我们通常都是单独使用的,所以这个小细节我们需要特别留意一下。

2. equals()比较两个字符串是否相等,源码如下:

publicbooleanequals(ObjectanObject){

//对象引用相同直接返回trueif(this==anObject){

returntrue;

}

//判断需要对比的值是否为String类型,如果不是则直接返回falseif(anObjectinstanceofString){

StringanotherString=(String)anObject;

intn=value.length;

if(n==anotherString.value.length){

//把两个字符串都转换为char数组对比charv1[]=value;

charv2[]=anotherString.value;

inti=0;

//循环比对两个字符串的每一个字符while(n--!=0){

//如果其中有一个字符不相等就truefalse,否则继续对比if(v1[i]!=v2[i])

returnfalse;

i++;

}

returntrue;

}

}

returnfalse;

}

String类型重写了 Object中的 equals()方法,equals()方法需要传递一个 Object类型的参数值,在比较时会先通过 instanceof判断是否为 String类型,如果不是则会直接返回 false,instanceof的使用如下:

ObjectoString="123";

ObjectoInt=123;

System.out.println(oStringinstanceofString);//返回trueSystem.out.println(oIntinstanceofString);//返回false

当判断参数为 String类型之后,会循环对比两个字符串中的每一个字符,当所有字符都相等时返回true,否则则返回 false。

还有一个和equals()比较类似的方法 equalsIgnoreCase(),它是用于忽略字符串的大小写之后进行字符串对比。

3. compareTo()比较两个字符串

compareTo()方法用于比较两个字符串,返回的结果为int类型的值,源码如下:

publicintcompareTo(StringanotherString){

intlen1=value.length;

intlen2=anotherString.value.length;

//获取到两个字符串长度最短的那个int值intlim=Math.min(len1,len2);

charv1[]=value;

charv2[]=anotherString.value;

intk=0;

//对比每一个字符while(k<lim){

charc1=v1[k];

charc2=v2[k];

if(c1!=c2){

//有字符不相等就返回差值returnc1-c2;

}

k++;

}

returnlen1-len2;

}

从源码中可以看出,compareTo()方法会循环对比所有的字符,当两个字符串中有任意一个字符不相同时,则 returnchar1-char2。比如,两个字符串分别存储的是 1和 2,返回的值是-1;如果存储的是 1和 1,则返回的值是 0,如果存储的是 2和 1,则返回的值是 1。

还有一个和compareTo()比较类似的方法 compareToIgnoreCase(),用于忽略大小写后比较两个字符串。

可以看出compareTo()方法和equals()方法都是用于比较两个字符串的,但它们有两点不同:

equals()可以接收一个 Object类型的参数,而 compareTo()只能接收一个String类型的参数;

equals()返回值为Boolean,而compareTo()的返回值则为int。

它们都可以用于两个字符串的比较,当equals()方法返回true时,或者是compareTo()方法返回 0时,则表示两个字符串完全相同。

4.其他重要方法

indexOf():查询字符串首次出现的下标位置

lastIndexOf():查询字符串最后出现的下标位置

contains():查询字符串中是否包含另一个字符串

toLowerCase():把字符串全部转换成小写

toUpperCase():把字符串全部转换成大写

length():查询字符串的长度

trim():去掉字符串首尾空格

replace():替换字符串中的某些字符

split():把字符串分割并返回字符串数组

join():把字符串数组转为字符串

知识扩展

1.==和equals的区别

==对于基本数据类型来说,是用于比较“值”是否相等的;而对于引用类型来说,是用于比较引用地址是否相同的。

查看源码我们可以知道 Object中也有equals()方法,源码如下:

publicbooleanequals(Objectobj){

return(this==obj);

}

可以看出,Object中的 equals()方法其实就是==,而 String重写了 equals()方法把它修改成比较两个字符串的值是否相等。

publicbooleanequals(ObjectanObject){

//对象引用相同直接返回trueif(this==anObject){

returntrue;

}

//判断需要对比的值是否为String类型,如果不是则直接返回falseif(anObjectinstanceofString){

StringanotherString=(String)anObject;

intn=value.length;

if(n==anotherString.value.length){

//把两个字符串都转换为char数组对比charv1[]=value;

charv2[]=anotherString.value;

inti=0;

//循环比对两个字符串的每一个字符while(n--!=0){

//如果其中有一个字符不相等就truefalse,否则继续对比if(v1[i]!=v2[i])

returnfalse;

i++;

}

returntrue;

}

}

returnfalse;

}

2.final修饰的好处

从String类的源码我们可以看出String是被final修饰的不可继承类,源码如下:

publicfinalclassString implementsjava.io.Serializable,Comparable<String>,CharSequence{//......}

那这样设计有什么好处呢?他会更倾向于使用 final,因为它能够缓存结果,当你在传参时不需要考虑谁会修改它的值;如果是可变类的话,则有可能需要重新拷贝出来一个新值进行传参,这样在性能上就会有一定的损失。

String类设计成不可变的另一个原因是安全,当你在调用其他方法时,比如调用一些系统级操作指令之前,可能会有一系列校验,如果是可变类的话,可能在你校验过后,它的内部的值又被改变了,这样有可能会引起严重的系统崩溃问题,这是迫使 String类设计成不可变类的一个重要原因。

总结来说,使用 final修饰的第一个好处是安全;第二个好处是高效,以 JVM中的字符串常量池来举例,如下两个变量:

Strings1="java";

Strings2="java";

只有字符串是不可变时,我们才能实现字符串常量池,字符串常量池可以为我们缓存字符串,提高程序的运行效率,如下图所示:

试想一下如果 String是可变的,那当 s1的值修改之后,s2的值也跟着改变了,这样就和我们预期的结果不相符了,因此也就没有办法实现字符串常量池的功能了。

3.String和StringBuilder、StringBuffer的区别

因为 String类型是不可变的,所以在字符串拼接的时候如果使用 String的话性能会很低,因此我们就需要使用另一个数据类型 StringBuffer,它提供了 append和 insert方法可用于字符串的拼接,它使用 synchronized来保证线程安全,如下源码所示:

@OverridepublicsynchronizedStringBufferappend(Objectobj){

toStringCache=null;

super.append(String.valueOf(obj));

returnthis;

}

@OverridepublicsynchronizedStringBufferappend(Stringstr){

toStringCache=null;

super.append(str);

returnthis;

}

因为它使用了 synchronized来保证线程安全,所以性能不是很高,于是在 JDK 1.5就有了StringBuilder,它同样提供了append和insert的拼接方法,但它没有使用 synchronized来修饰,因此在性能上要优于 StringBuffer,所以在非并发操作的环境下可使用 StringBuilder来进行字符串拼接。

4.String和JVM

String常见的创建方式有两种,new String()的方式和直接赋值的方式,直接赋值的方式会先去字符串常量池中查找是否已经有此值,如果有则把引用地址直接指向此值,否则会先在常量池中创建,然后再把引用指向此值;而 new String()的方式一定会先在堆上创建一个字符串对象,然后再去常量池中查询此字符串的值是否已经存在,如果不存在会先在常量池中创建此字符串,然后把引用的值指向此字符串,如下代码所示:

Strings1=newString("Java");

Strings2=s1.intern();

Strings3="Java";

System.out.println(s1==s2);//falseSystem.out.println(s2==s3);//true

它们在 JVM存储的位置,如下图所示:

除此之外编译器还会对String字符串做一些优化,例如以下代码:

Strings1="Ja"+"va";

Strings2="Java";

System.out.println(s1==s2);

虽然s1拼接了多个字符串,但对比的结果却是true,我们使用反编译工具,看到的结果如下:

Compiledfrom"StringExample.java"publicclasscom.lagou.interview.StringExample{

publiccom.lagou.interview.StringExample();

Code:

0:aload_0

1:invokespecial#1//Methodjava/lang/Object."<init>":()V4:returnLineNumberTable:

line3:0publicstaticvoidmain(java.lang.String[]);

Code:

0:ldc#2//StringJava2:astore_1

3:ldc#2//StringJava5:astore_2

6:getstatic#3//Fieldjava/lang/System.out:Ljava/io/PrintStream;9:aload_1

10:aload_2

11:if_acmpne1814:iconst_1

15:goto1918:iconst_0

19:invokevirtual#4//Methodjava/io/PrintStream.println:(Z)V22:returnLineNumberTable:

line5:0line6:3line7:6line8:22}

从编译代码#2可以看出,代码"Ja"+"va"被直接编译成了"Java",因此 s1==s2的结果才是 true,这就是编译器对字符串优化的结果。

关于java equalsignorecase性能到此分享完毕,希望能帮助到您。

数据分析师培训需要多少钱 数据分析需要学哪些c语言自定义函数,c语言代码大全及其含义