今天是星期六,没有课,我在床上睡觉
十一点多醒来,看了一下我祖传的手机,发现收到了一条qq信息,发的是我们软件工程专业的系花,之前一直苦苦追求我,但是都被我以各种理由婉拒:
“女人只会影响我敲代码的速度”
“女人是我敲代码路上的绊脚石”
“敲代码中,繁忙,闲人勿进”
我看了一下信息,原来学妹昨天刷一道算法题,做了一天,还是没做对,我看了一下题目,原来是leetcode上面一道字符串类型的题目。
我和学妹说,把你解题的代码发给我看看,学妹马上就发给我了
class Solution {
public boolean arrayStringsAreEqual(String[] word1, String[] word2) {
String sb1=new String();
String sb2=new String();
for (int i=0;i<word1.length;i++){
sb1+=word1[i];
}
for (int i=0;i<word2.length;i++){
sb2+=word2[i];
}
return sb1==sb2;
}
}
学妹说,她每次在编译器上面解题,都是对的,但是一旦提交leetcode,就会显示时间超时,她都气哭了三次。
看到这里,我忍不住笑出了声
我和学妹说,你显示时间超时,是很正常的,因为你没有了解String的原理,学妹马上问道:“学长,那么原理是什么呢?”
“别急,请听学长慢慢说”,我便开始装起逼来
首先,我们先点进Stirng源码里面看看
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -6849794470754667710L;
/**
* Class String is special cased within the Serialization Stream Protocol.
*
* A String instance is written into an ObjectOutputStream according to
* <a href="{@docRoot}/../platform/serialization/spec/output.html">
* Object Serialization Specification, Section 6.2, "Stream Elements"</a>
*/
private static final ObjectStreamField[] serialPersistentFields =
new ObjectStreamField[0];
/**
* Initializes a newly created {@code String} object so that it represents
* an empty character sequence. Note that use of this constructor is
* unnecessary since Strings are immutable.
*/
public String(StringBuffer buffer) {
synchronized(buffer) {
this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
}
}
public boolean contentEquals(CharSequence cs) {
// Argument is a StringBuffer, StringBuilder
if (cs instanceof AbstractStringBuilder) {
if (cs instanceof StringBuffer) {
synchronized(cs) {
return nonSyncContentEquals((AbstractStringBuilder)cs);
}
} else {
return nonSyncContentEquals((AbstractStringBuilder)cs);
}
}
// Argument is a String
if (cs instanceof String) {
return equals(cs);
}
// Argument is a generic CharSequence
char v1[] = value;
int n = v1.length;
if (n != cs.length()) {
return false;
}
for (int i = 0; i < n; i++) {
if (v1[i] != cs.charAt(i)) {
return false;
}
}
return true;
}
通过这我们可以看到String其实是由char数组组成,并且用synchronized修饰了,这样就确保了线程的安全,但是有一点不好的是,每一次String类型的变量需要改变的时候,都要重新创建一个Stirng,再把新的字符放进去,这样就极大的消耗了性能,所以在做这道题目的时候,学妹提交才会出现时间超时的错误,所以这里我们用StringBuffer会比较好。
学妹听后恍然大悟,说道:“原来如此,学长你好厉害哦,那我去试一下”
过了一分钟后
“呜呜呜学长,又出现问题了”
“不可能啊?时间超时了?把你代码给我看看”
class Solution {
public boolean arrayStringsAreEqual(String[] word1, String[] word2) {
StringBuffer sb1=new StringBuffer();
StringBuffer sb2=new StringBuffer();
for (int i=0;i<word1.length;i++){
sb1.append(word1[i]);
}
for (int i=0;i<word2.length;i++){
sb2.append(word2[i]);
}
return sb1==sb2;
}
}
学妹说:“这一次直接报错了,两个字符串明明一模一样,但是却返回false,学长你到底行不行啊?”
我去,居然怀疑我行不行,那我可不能忍了,于是我说道:
“这是你自己写错了,你没有理解String还有StringBuffer”
“怎么又怪我了?”学妹委屈的说道
那就听我慢慢的说完吧
- 首先我们要知道“==”与“equals”是不一样的
- “==”比较的是两个字符串的地址,不能比较内容
- String的“equals”重写了,所以可以比较两个字符串的内容
- StringBuffer因为没重写equals方法,直接继承了Object的equals方法,所以不行
怕学妹到时候又出错,我干脆给她写了一个
class Solution {
public boolean arrayStringsAreEqual(String[] word1, String[] word2) {
StringBuffer sb1=new StringBuffer();
StringBuffer sb2=new StringBuffer();
for (int i=0;i<word1.length;i++){
sb1.append(word1[i]);
}
for (int i=0;i<word2.length;i++){
sb2.append(word2[i]);
}
return sb1.toString().equals(sb2.toString());
}
}
果不其然,对了
“哇谢谢学长,学长好厉害啊,对了学长,今天我室友都出去了,我一个人在寝室好无聊,能不能陪我去看看电影啊,记得带一下身份证”
我就知道,她这么不爱学习的人怎么会问我算法题,肯定是另有企图
“对不起哦学妹,我要敲代码,因为…”
注意:
以上内容纯属扯淡