首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

Java之美[从初学者到高手演变]之一字符串的处理

2012-11-11 
Java之美[从菜鸟到高手演变]之一字符串的处理写程序就像生活,有酸甜苦辣,关键在于过程,任何事情的过程都是

Java之美[从菜鸟到高手演变]之一字符串的处理

写程序就像生活,有酸甜苦辣,关键在于过程,任何事情的过程都是美好的,是值得我们回味的!

有人说,编程是一种艺术,艺术出于生活却高于生活,每一个细节都值得细细品味...程序员无非就是两件事:学习和分享!

独乐乐与人乐乐,孰乐?于是,程序员对着电脑,开始写作。一盏台灯、一杯清茶,躺在旁边,默默的,听着。

从本次博文起,要进行Java之美[从菜鸟到高手演变]系列,本文系第一篇,Java字符串的处理。字符串在任何语言中都是一个非常重要的概念,我们有必要掌握她的一切!

本博客永久更新,如有转载,

请说明出处:http://blog.csdn.net/zhangerqing

如有问题,请联系本人: egg

邮箱:xtfggef@gmail.com

微博:http://weibo.com/xtfggef

Java中的字符串处理主要有下面三个类来处理的:

String

StringBuffer

[跳转到StringBuffer部分]

StringBuilder

一、String

1、String简介

初始化:

一般由String声明的字符串,长度是不可变的,这也是它与StringBuffer和StringBuilder最直观的一个区别。

一般初始化方式:String s = "hello world";经过这条语句,JVM的栈内存中产生一个s变量,堆内存中产生hello world字符串对象。s指向了hello world的地址。

像上面这种方式产生的字符串属于直接量字符串对象,JVM在处理这类字符串的时候,会进行缓存,产生时放入字符串池,当程序需要再次使用的时候,无需重新创建一个新的字符串,而是直接指向已存在的字符串。看下面程序:

package com.xtfggef.string;public class StringTest4 {public static void main(String[] args) {String s = "hello world";String s2 = "hello world";System.out.println(s == s2);}}

该程序输出:true 因为s和s2都指向了hello world字符串,他们的地址是同一个。

我们常说,String的一个很大的特点,就是它是一个“不可变的字符串”,就是说,当一个String对象完成创建后,该对象的内

容就固定下来了,但是为什么还会有下面这种情况呢?

package com.xtfggef.string;public class StringInit {public static void main(String[] args) {String str = "I like";//---------1--------System.out.println(System.identityHashCode(str));str = str + "java";//--------2---------System.out.println(System.identityHashCode(str));}}

该程序输出:

14576877
12677476

说明:str似乎是变了,这是为什么呢?
其实是这样的:str只是一个引用变量,当程序执行完1后,内存中的情况是这样的:

Java之美[从初学者到高手演变]之一字符串的处理

当程序执行完2之后,连接运算符会将两个字符串连在一起,并且让str指向新的串,如下图:

Java之美[从初学者到高手演变]之一字符串的处理

所以,从这里应该可以看得出来,最初的对象确实没有改变,只是str所指向的对象在不断改变。

String对象的另一种初始化方式,就是采用String类提供的构造方法进行初始化。String类提供了16种构造方法,常用的有五种:

String() --------- 初始化一个String对象,表示一个空字符序列

String(String value) --------- 利用一个直接量创建一个新串

String(char[] value) --------- 利用一个字符数组创建

String(char[] value,int offset,int count) --------- 截取字符数组,从offset开始count个字符创建

String(StringBuffer buffer) --------- 利用StringBuffer创建

形如:

String s = new String();

String s1 = new String(“hello”);

char[] c = {'h','e','l','l','o'};

String s2 = new String(c);

'String s3 = new String(c,1,3);

以上就是String类的基本初始化方法。

2、String类的一些常用方法

字符串是最常用的对象,所以,我们有必要彻底的了解下它,下面我会列举常用的字符串里的方法,因为有很多,就不一一列举。

-------public int length()--------

该方法用于获取字符串的长度,实现如下:

/**     * Returns the length of this string.     * The length is equal to the number of <a href="Character.html#unicode">Unicode     * code units</a> in the string.     *     * @return  the length of the sequence of characters represented by this     *          object.     */    public int length() {        return count;    }

这是JDK种的原始实现,count在String类里被定义为一个整型常量:private final int count;并且不论采用哪种构造方法,最终都会为count赋值。

使用方法:

String s = "hello world";int length = s.length();

这个比较简单。

-----------public boolean equals(Object anObject)-----------

该方法用于比较给定对象是否与String相等。

JDK里是这样实现的:

/**     * Compares this string to the specified object.  The result is {@code     * true} if and only if the argument is not {@code null} and is a {@code     * String} object that represents the same sequence of characters as this     * object.     *     * @param  anObject     *         The object to compare this {@code String} against     *     * @return  {@code true} if the given object represents a {@code String}     *          equivalent to this string, {@code false} otherwise     *     * @see  #compareTo(String)     * @see  #equalsIgnoreCase(String)     */    public boolean equals(Object anObject) {if (this == anObject) {    return true;}if (anObject instanceof String) {    String anotherString = (String)anObject;    int n = count;    if (n == anotherString.count) {char v1[] = value;  //---------1---------char v2[] = anotherString.value;//-------2----------int i = offset;int j = anotherString.offset;while (n-- != 0) {    if (v1[i++] != v2[j++])return false;}return true;    }}return false;    }

从1和2处也看出来,String的底层是基于字符数组的。我们可以像下面这种方式使用equals():

String s1 = new String("hello world");String s2 = new String("hello world");String s3 = new String("hello");System.out.println(s1.equals(s2));;System.out.println(s1.equals(s3));

结果输出:

true

false

此处插入一个很重要的知识点,重写equals()的一般步骤及注意事项:

1. 使用==操作符检查“实参是否为指向对象的一个引用”。
2. 使用instanceof操作符检查“实参是否为正确的类型”。
3. 把实参转换到正确的类型。
4. 对于该类中每一个“关键”域,检查实参中的域与当前对象中对应的域值是否匹配。

a.对于既不是float也不是double类型的基本类型的域,可以使用==操作符进行比较

b.对于对象引用类型的域,可以递归地调用所引用的对象的equals方法 
   c.对于float类型的域,先使用Float.floatToIntBits转换成int类型的值,然后使用==操作符比较int类型的值

d.对于double类型的域,先使用Double.doubleToLongBits转换成long类型的值,然后使用==操作符比较long类型的值。
5. 当你编写完成了equals方法之后,应该问自己三个问题:它是否是对称的、传递的、一致的?(其他两个特性通常会自行满足)    如果答案是否定的,那么请找到这些特性未能满足的原因,再修改equals方法的代码。

稍后我再做说明,请先再看个例子:

package com.xtfggef.string;/** * 字符串比较:equals()和==的区别 * @author 二青 * */public class StringInit {public static void main(String[] args) {String s = "hello world";String s1 = new String("hello world");String s2 = new String("hello world");String s3 = new String("hello");String s4 = "hello world";System.out.println(s.equals(s1));;System.out.println(s1.equals(s2));System.out.println(s1.equals(s3));System.out.println("------------------");System.out.println(s == s1);System.out.println(s == s3);System.out.println(s == s4);}}

输出:

true
true
false
------------------
false
false
true

此处验证了一个问题,就是比较方法equals()和==的区别,一句话:equals()比较的是对象的内容,也就是JVM堆内存中的内容,==比较的是地址,也就是栈内存中的内容。

如上述代码中,s、s1、s2、s4他们四个String对象的内容都是"hello world",所以,用equals()比较他们,返回的都是true。但是,当s和s1用==比较时,却返回false,因为二者在堆中开辟的地址不一样,所以,返回的肯定是false。而为什么s和s4用==比较时,返回的是true呢,因为上文中提到过,直接量的字符串会产生缓存池,所以,当声明s4的时候,编译器检测到缓存池中存在相同的字符串,所以就直接使用,只要将s4指向s所指向的字符串就行了,二者指向同一字符串,所以地址当然相等!

注意:此处隐藏着一个比较细的编程习惯,尤其是用==进行比较的时候,尽量将常量放在==的左边,因为我们有的时候,会不小心将==写成=,这样的话,如果将常量放在左边,编译器会报错,提醒你,但是,如果将变量放在左边,常量放右边,即使你写成了=,编译器默认为变量赋值了,因此也不会报错。

因为String类实现了public interface Comparable<T>,而Comparable接口里有唯一的方法:public int compareTo(T o)。所以,String类还有另一个字符串比较方法:compareTo()

-----------------public int compareTo(String anotherString)---------------

compareTo()可实现比较两个字符串的大小,源码如下:

public int compareTo(String anotherString) {int len1 = count;int len2 = anotherString.count;int n = Math.min(len1, len2);char v1[] = value;char v2[] = anotherString.value;int i = offset;int j = anotherString.offset;if (i == j) {    int k = i;    int lim = n + i;    while (k < lim) {char c1 = v1[k];char c2 = v2[k];if (c1 != c2) {    return c1 - c2;}k++;    }} else {    while (n-- != 0) {char c1 = v1[i++];char c2 = v2[j++];if (c1 != c2) {    return c1 - c2;}    }}return len1 - len2;    }

compareTo是怎么实现的呢?

首先,会对两个字符串左对齐,然后从左到右一次比较,如果相同,继续,如果不同,则计算不同的两个字符的ASCII值的差,返回就行了。与后面的其他字符没关系。

举个例子:

package com.xtfggef.string;/** * compareTo()测试 * @author 二青 * */public class CompareToTest {public static void main(String[] args) {String s = "hallo";String s2 = "ha";String s3 = "haeeo";int a = s.compareTo(s2);System.out.println("a:"+a);int b = s.compareTo(s3);System.out.println("b:"+b);int c = s2.compareTo(s3);System.out.println("c:"+c);}}

程序输出:

a:3
b:7
c:-3
s和s2相比,前两个相同,如果是这种情况,则直接返回length1-length2

s和s3相比,前两个相同,不用管,直接用第三个字符的ASCII码做差就行了。所以'l'-'a'=7

此处网友“handsomeman_wei”问我源码中的c1-c2理解不了,就是上面红字部分的解释。

s2和s3相比,同第一种情况一样,只是length1比length2小,因此值为负数。

-----------public char charAt(int index)-----------

获取指定位置的字符,比较容易理解,源码为:

public char charAt(int index) {        if ((index < 0) || (index >= count)) {            throw new StringIndexOutOfBoundsException(index);        }        return value[index + offset];    }

String s = "hallo";
char a = s.charAt(2);
System.out.println(a);
输出:l

注意:参数index的值从0到字符串的长度-1,所以,如果值不在这个范围内,如下:

String s = "hallo";
char a = s.charAt(8);
System.out.println(a);

则报错:

Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 8

at java.lang.String.charAt(String.java:686)
at com.xtfggef.string.CompareToTest.main(CompareToTest.java:20)

与charAt()相对应的是indexOf():根据给定的字符串,返回他的位置。

indexOf()有多个参数:

public int indexOf(int ch)

public int indexOf(int ch, int fromIndex)

public int indexOf(String str)

public int indexOf(String str, int fromIndex)

static int indexOf(char[] source, int sourceOffset, int sourceCount,
char[] target, int targetOffset, int targetCount,
int fromIndex)

有兴趣的自己去试试,这儿就不多阐述了。

-----------substring()------------

public String substring(int beginIndex) {return substring(beginIndex, count);    }

用于截取字符串,此处与另一个方法对比:

public String substring(int beginIndex, int endIndex) {if (beginIndex < 0) {    throw new StringIndexOutOfBoundsException(beginIndex);}if (endIndex > count) {    throw new StringIndexOutOfBoundsException(endIndex);}if (beginIndex > endIndex) {    throw new StringIndexOutOfBoundsException(endIndex - beginIndex);}return ((beginIndex == 0) && (endIndex == count)) ? this :    new String(offset + beginIndex, endIndex - beginIndex, value);    }

前者调用后者来实现,前者截取从指定位置到字符串结束的子字符串,后者截取从指定位置开始,到endIndex-1位置的子字符串。

public class CompareToTest {public static void main(String[] args) {String s = "helloworld";String s1 = s.substring(2);String s2 = s.substring(2, 7);String s3 = (String) s.subSequence(2, 7);System.out.print("s1:"+s1+"\n"+"s2:"+s2+"\n"+"s3:"+s3);}}

输出:

s1:lloworld
s2:llowo
s3:llowo

细心的读者应该看出来,该类里面包含一个subSequence(),而且该方法与substring(int,int)返回的结果一样,观察下源码,不难发现的区别:

 public CharSequence subSequence(int beginIndex, int endIndex) {        return this.substring(beginIndex, endIndex);    }    }

其实subSequence()内部就是调用的substring(beginIndex, endIndex),只是返回值不同。

subString返回的是String,subSequence返回的是实现了CharSequence接口的类,也就是说使用subSequence得到的结果,只能使用CharSequence接口中的方法。不过在String类中已经重写了subSequence,调用subSequence方法,可以直接转为String对象,如我们例子中的做法。

-----------------public String replace(char oldChar, char newChar)和public String replaceAll(String regex, String replacement)-------------------

public String replace(char oldChar, char newChar) {if (oldChar != newChar) {    int len = count;    int i = -1;    char[] val = value; /* avoid getfield opcode */    int off = offset;   /* avoid getfield opcode */    while (++i < len) {if (val[off + i] == oldChar) {    break;}    }    if (i < len) {char buf[] = new char[len];for (int j = 0 ; j < i ; j++) {    buf[j] = val[off+j];}while (i < len) {    char c = val[off + i];    buf[i] = (c == oldChar) ? newChar : c;    i++;}return new String(0, len, buf);    }}return this;    }

public String replaceAll(String regex, String replacement) { return Pattern.compile(regex).matcher(this).replaceAll(replacement);    }

前者参数为两个字符串,用newChar替换原串里的所有oldChar。

后者从第一个参数可以看出,需要替换的东西可以用正则表达式描述。例子如下:

package com.xtfggef.string;public class ReplaceTest {public static void main(String[] args) {String s = "hello world";String s1 = s.replace("l", "d");System.out.println(s1);String s2 = "a78e5opx587";String s3 = s2.replaceAll("[0-9]", "");//用空串替换原串里所有的0-9的数字System.out.println(s3);}}


输出:

heddo wordd
aeopx

-------------public String[] split(String regex)-----------

该方法用于分割字符串,得到一个String类型的数组,根据regex可知,参数是个正则表达式。请看下面的例子:

package com.xtfggef.string;public class SpiltTest {public static void main(String[] args) {String s = "hello world";String s1 = "hello.worldd";String[] s2 = s.split(" ");String[] s3 = s1.split("\\.");for(int i=0; i<s2.length; i++){System.out.print(s2[i]+" ");}System.out.println();for(int j=0; j<s3.length; j++){System.out.print(s3[j]+" ");}}}

输出:

hello world
hello worldd
关于spilt()的其他重载方法,可参见JDK的String类的实现。

spilt()需要注意的事项,就是当分隔符为 . 的话,处理起来不一样,必须写成\\.因为.是正则表达式里的一个特殊符号,必须进行转义

一般常见的字符串处理函数就这些,其它的还有很多,就不一一列举。

3、一些常见的问题,处理结果

在我们日常的开发中,总会遇到一些问题,在此我总结一下:

String s = "123" + "456"内存中产生几个字符串对象?

这是个比较有争议的问题,面试的时候,老师还挺喜欢问,论坛上大家说几个的也有,我给大家分析一下,因为我们前面有提到Java字符串的缓存机制,编译器在编译的时候会进行优化,所以在编译的过程中123和456被合成了一个字符串"123456",因此,如果缓存池中目前没有123456这个对象,那么会产生一个,即""123456",且栈中产生一个引用s指向它,如果缓存池中已经存在"123456",那么将产生0个对象,直接用s指向它。

如果spilt()函数的参数在要分割的字符串中没有怎么办?如String s = "helloworld" ,我现在调用String[] s2 = s.spilt("abc"),返回什么?

这个问题是我曾经参加红帽软件面试的时候遇到的相关题,当时懵了,像这样的题目,如果不亲自遇到过,或者看过源代码,很难准确的写出来。

做一个简单的测试,就可以看得出来:

package com.xtfggef.string;public class StringSpilt {public static void main(String[] args) {String s = "helloworld";String[] s2 = s.split("abc");for (int i = 0; i < s2.length; i++) {System.out.println(s2[i] + " " + i);}}}

输出:helloworld 0

说明当遇到源字符串中没有的字符时,会把它整个串放入到数组中。spilt()的内部实现还是挺复杂的,多层嵌套,不便于放到这儿分析。

关于字符串自动类型转换分析

首先看一下题的类型:

int i = 2;int j = 3;String s = "9";System.out.println(i+j+s);System.out.println("-----------------------");System.out.println(i+s+j);

以上运算各输出什么?不妨猜猜
59
-----------------------
293

首先i+j=5,然后5和9自然连接,这里涉及到java的自动类型转换,此处int型的直接转成String类型的。第二个依次连接,都转化为String类型的了。

个人的力量是有限的,欢迎大家积极补充,同时也欢迎读者随时批评指正!

有问题请联系:egg

邮箱:xtfggef@gmail.com

微博:http://weibo.com/xtfggef

4、String造成的内存泄露

You have to believe in yourself.That's the secretof success!

二、

StringBuffer、StringBuilder

  1、初始化

StringBuffer和StringBuilder就是所谓的可变字符串类,共四个构造方法:

StringBuffer()

public StringBuffer(int paramInt)

public StringBuffer(String paramString)

public StringBuffer(CharSequence paramCharSequence)

观察其源码发现,使用StringBuffer()时,默认开辟16个字符的长度的空间,使用public StringBuffer(int paramInt)时开辟指定大小的空间,使用public StringBuffer(String paramString)时,开辟paramString.length+16大小的空间。都是调用父类的构造器super()来开辟内存。这方面StringBuffer和StringBuilder都一样,且都实现AbstractStringBuilder类。

  2、主要方法

二者几乎没什么区别,基本都是在调用父类的各个方法,一个重要的区别就是StringBuffer是线程安全的,内部的大多数方法前面都有关键字synchronized,这样就会有一定的性能消耗,StringBuilder是非线程安全的,所以效率要高些。

public static void main(String[] args) throws Exception {String string = "0";int n = 100000;long begin = System.currentTimeMillis();for (int i = 1; i < n; i++) {string += i;}long end = System.currentTimeMillis();long between = end - begin;System.out.println("使用String类耗时:" + between+"ms");int n1 = 10000;StringBuffer sb = new StringBuffer("0");long begin1 = System.currentTimeMillis();for (int j = 1; j < n1; j++) {sb.append(j);}long end1 = System.currentTimeMillis();long between1 = end1 - begin1;System.out.println("使用StringBuffer类耗时:" + between1+"ms");int n2 = 10000;StringBuilder sb2 = new StringBuilder("0");long begin2 = System.currentTimeMillis();for (int k = 1; k < n2; k++) {sb2.append(k);}long end2 = System.currentTimeMillis();long between2 = end2 - begin2;System.out.println("使用StringBuilder类耗时:" + between2+"ms");}

输出:

使用String类耗时:982ms
使用StringBuffer类耗时:2ms
使用StringBuilder类耗时:1ms

虽然这个数字每次执行都不一样,而且每个机子的情况也不一样,但是有几点是确定的,String类消耗的明显比另外两个多得多。还有一点就是,StringBuffer要比StringBuilder消耗的多,尽管相差不明显。

接下来介绍一些常用的方法。

-----------------------public synchronized int length()--------------------------

-------------------------public synchronized int capacity()---------------------------

二者都是获取字符串的长度,length()获取的是当前字符串的长度,capacity()获取的是当前缓冲区的大小。举个简单的例子:

StringBuffer sb = new StringBuffer();System.out.println(sb.length());;System.out.println(sb.capacity());
输出:

0

16

StringBuffer sb = new StringBuffer("hello");System.out.println(sb.length());;System.out.println(sb.capacity());
输出:

5

21

因为默认分配16个字符大小的空间,所以不难解释上面的结果。

------------------public boolean equals(Object paramObject)---------------------

StringBuffer sb = new StringBuffer("hello");StringBuffer sb2 = new StringBuffer("hello");System.out.println(sb.equals(sb2));
以上程序输出false,是不是有点惊讶?记得之前我们的文章说过,equals()比较的是字符串的内容,按理说此处应该输出的是true才对。

究其原因,String类重写了Object的equals(),所以只需要看内容是否相等即可,但是StringBuffer没有重写equals(),此处的equals()仍然是调用的Object类的,所以,调用StringBuffer类的equals(),只有地址和内容都相等的字符串,结果才会返回true。

另外StringBuffer有一系列追加、插入、删除字符串的方法,首先append(),就是在原来的字符串后面直接追加一个新的串,和String类相比有明显的好处:

String类在追加的时候,源字符串不变(这就是为什么说String是不可变的字符串类型),和新串连接后,重新开辟一个内存。这样就会造成每次连接一个新串后,都会让之前的串报废,因此也造成了不可避免的内存泄露。

               //append()StringBuffer sb = new StringBuffer("helloworld, ");sb.append("I'm ").append("erqing ").append("who ").append("are you ?");System.out.println(sb);//public synchronized StringBuffer insert(int paramInt, Object paramObject)sb.insert(12, /*9*/"nice! ");System.out.println(sb);//public synchronized StringBuffer reverse()sb.reverse();System.out.println(sb);sb.reverse();System.out.println(sb);//public synchronized StringBuffer delete(int paramInt1, int paramInt2)//public synchronized StringBuffer deleteCharAt(int paramInt)sb.delete(12, 18);System.out.println(sb);sb.deleteCharAt(5);System.out.println(sb);
输出:

helloworld, I'm erqing who are you ?
helloworld, nice! I'm erqing who are you ?
? uoy era ohw gniqre m'I !ecin ,dlrowolleh
helloworld, nice! I'm erqing who are you ?
helloworld, I'm erqing who are you ?
helloorld, I'm erqing who are you ?

-----------------public synchronized void trimToSize()---------------------

该方法用于将多余的缓冲区空间释放出来。

                StringBuffer sb = new StringBuffer("hello erqing");System.out.println("length:"+sb.length());System.out.println("capacity:"+sb.capacity());sb.trimToSize();System.out.println("trimTosize:"+sb.capacity());
输出:

length:12
capacity:28
trimTosize:12

StringBuffer类还有很多方法,关于字符查找,截取,替换方面的方法,有兴趣的童鞋可以去研究研究源码,定会学到不少知识!

三、字符串处理类StringTokenizer

StringTokenizer是java.util包下的一个类,用来对字符串做简单的处理。

举个简单的例子:

String s = "Tonight is the answer !";StringTokenizer st = new StringTokenizer(s," ");int count = st.countTokens();System.out.println("个数为:"+count);while (st.hasMoreTokens()) {String token = st.nextToken();System.out.println(token); }
输出:

个数为:5
Tonight
is
the
answer
!

本章节完!后续会不断的增加。

本内容随时更新,如果大家有什么新的内容需要补充,希望留言!



5楼HandsomeMan_wei昨天 21:32
new GridLayout(5,2,3,6);翻看了所有的资料,找不到GridLayout布局管理器还有这样的构造函数,请帮忙解释一下这四个参数,谢谢
Re: zhangerqing昨天 21:46
回复HandsomeMan_wein这种问题,去看JDK源码,网上的资料很多都是抄来抄去。我随便看了一下,的确有这个构造函数,如下:n public GridLayout(int paramInt1, int paramInt2, int paramInt3, int paramInt4)n {n if ((paramInt1 == 0) && (paramInt2 == 0))n throw new IllegalArgumentException("rows and cols cannot both be zero");nn this.rows = paramInt1;n this.cols = paramInt2;n this.hgap = paramInt3;n this.vgap = paramInt4;n }n前两个是行数和列数,后两个你再研究研究,我现在忙,回头给你看看。
Re: HandsomeMan_wei昨天 22:01
谢啦,已经弄明白了,后两个是水平与竖直距离
Re: zhangerqing昨天 22:02
回复HandsomeMan_wein嗯,呵呵,我也是很久没有弄过GUI了,多看看源码。
4楼HandsomeMan_wei昨天 14:27
那compareTo()方法里count 和 value 以及offset 分别是什么,值等于多少?
Re: zhangerqing昨天 20:36
回复HandsomeMan_weincount是字符串里元素的个数,offset是起始位置,value是字符数组,这个你得结合着String类的源码来看。因为我那个是从源码中截取出来的,像你问的这些变量,String类里有定义,我这儿省略了。
3楼zhangerqing3天前 09:54
[quote=HandsomeMan_wei]我初学的,看了这篇文章,收获挺大的,String类的一些细节问题注意到了,还有一个小算法,就是Com...[/quote]n你是说哪个小算法?
2楼HandsomeMan_wei3天前 09:51
我初学的,看了这篇文章,收获挺大的,String类的一些细节问题注意到了,还有一个小算法,就是CompareTo方法里的……赶紧更新哈
1楼HandsomeMan_wei3天前 19:16
CompareTo()方法不太懂,既然这个方法的最后 return len1-len2; 那么if语句中 return c1 - c2 ;有什么用啊
Re: zhangerqing3天前 19:39
回复HandsomeMan_wein这个有不同的情况,如果两个字符串,一个是hello,一个是hellos,想这样的直接就是len1-len2.但是如果一个是hello,一个是hellp,这样返回的值就是c1-c2了,即'o'-'p'。用二者ASCII的值作差。

热点排行