蓝杰学习笔记备份1

 

 

 

 

 

    前一段时间一位同事的系统崩了,电脑上重要资料全部丢失,实在遗憾。鉴于此,我想把我学过的一些东西也备份一下,以防系统崩溃之痛。

    学过的东西很容易淡忘,有时候碰到问题明知道是以前解决过的,但现在却忘了如何解决这同样的问题,比较苦恼,所以我经常把自己写过的项目(可重用性高的模块)备份到U盘或者google托管上面,时不时温故一下,嘿嘿。

下面是胡总讲过的一课,我把课堂笔记写下了放这里共享一下:

 

字符串使用性能深入测试

一、 字符串池。

       Java String 是以对象的形式存在的,但是它却是值传递的。当要比较两个字符串的内容的时候,我们常采用的方法是 str1.equals(str2); ,先看下面的问题:

情况一:

String str1 = “abc”;

String str2 = “abc”;

System.out.println(str1==str2);

System.out.println(str1.equals(str2));

情况二:

String str1 = new String(“abc”);

String str2 = new String(“abc”);

System.out.println(str1==str2);

System.out.println(str1.equals(str2));

 

 

两种情况运行的结果分别是:

情况一结果:

           true

           true

情况二结果:

           false

           true

为什么会出现这种情况呢?两种字符串对象的创建之间有什么不同呢?

 

 

现在来看看 String.equals(); 方法的源代码:

 

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;
		char v2[] = anotherString.value;
		int i = offset;
		int j = anotherString.offset;
		while (n-- != 0) {
		    if (v1[i++] != v2[j++])
			return false;
		}
		return true;
	    }
	}
	return false;
 }

 

 

我们看到,它首先是进行“ = = ”比较,然后在将字符串打成原形 bytes ,逐个比较字节,得出结果。

我们可以使用 jdk bin 目录下面的 javap 工具查看以上代码运行的指令结构。

javap –c className 回车

 

 

 

二、 String StringBuffer StringBuilder 比较 àà “比较”思想的运用。

字符串是程序中最常用的一个数据类型或对象,可以用到的类有: String StringBuffer StringBuilder 。这三个之间是有一定区别的。

下面是一个简单的类 A.java

 

public class A{
  public static void main(String args[]) {
    String str = "abc";
    str+="z";
  }
}

 

   编译正确后,在命令行输入 javap –c A ,我们可以看到其执行的过程。如下图:

 

 

 

 

可以看到,我们在进行字符串尾部添加字符串时,其实是调用了 StringBuilder append() 方法。由此可见, String 连接字符串的效率是比较的低的。

StringBuilder append 方法如下:

public StringBuilder append (String str) {

        super .append(str);

        return this ;

      }

     继承了父类的 append 方法,那么它的父类是什么呢?看下面,

     public final class StringBuilder

       extends AbstractStringBuilder

      implements java.io.Serializable, CharSequence

现在我们知道了, StringBuilder 是一个不能被子类重写的一个类,并且继承了 AbstractStringBuilder 类,重写了父类 append() 方法。

那么 StringBuffer 又有什么特点呢?

请看它的定义:

 

 public final class StringBuffer
    extends AbstractStringBuilder
    implements java.io.Serializable, CharSequence
{
     … …
}

 

StringBuffer append() 方法如下:

public synchronized StringBuffer append(String str) {
	super.append(str);
        return this;
    }

 

请仔细对比 StringBuilder append() ,我们发现 StringBuffer append() 方法加了关键字 synchronized ,所以 StringBuffer 是线程同步的,而 StringBuilder 是非线程同步的。

接下来我们来测试一下它们的处理字符串连接速度,测试代码如下:

/**
 * 测试String、StringBuffer和StringBuilder
 * 字符串连接速度。
 * 首先介绍一下他们之间的区别:
 * 1,String在实现字符串连加时,其实是调用了StringBuilder中的append方法,所以性能上远远不及StringBuilder。
 * 2,StringBuffer是一种线程安全的类,它的append()方法有一个关键词sychronization。
 * 3,StringBuilder是非线程安全的,它的效率稍高于StringBuffer。
 * 总的来说,他们之间就是性能上的差别。
 * @author 波仔
 *
 */
public class StringTest {
	
	public static void main(String args[]) throws Exception{
		int count = 10000000;
		//测试String
		long start = System.currentTimeMillis();
		testString(count);
		System.out.println("String 连接花时:"+(System.currentTimeMillis()-start)+"毫秒。");
	    java.lang.Runtime.getRuntime().runFinalization();
		Thread.sleep(1000);
	    
	    
	    //测试StringBuffer
	    start = System.currentTimeMillis();
	    testStringBuffer(count);
	    System.out.println("StringBuffer连接花时:"+(System.currentTimeMillis()-start)+"毫秒。");
	    java.lang.Runtime.getRuntime().runFinalization();
	    Thread.sleep(1000);
 //测试StringBuilder
	    start = System.currentTimeMillis();
	    testStringBuilder(count);
	    System.out.println("StringBuilder连接花时:"+(System.currentTimeMillis()-start)+"毫秒。");
	    java.lang.Runtime.getRuntime().runFinalization();
	}
	
	/**
	 * 测试String对象字符串连接的速度。
	 * @param count 字符串连接次数
	 * @return 连接后的字符串对象
	 */
	public static String testString(int count){
//		String str = new String("abc");
		String str = "abc";
		for(int i = 0;i

 

测试结果如下

 

 

这样多次运行结果都不会相差太多。由此得知 StringBuilder StringBuffer 较之 String 向尾部添加字符串的效率要高很多。

 

小结:在测试不同类处理同一数据的效率时,我们应该有一个全面正确的测试方案,在上面的例子中我们的 count 值不能设的太小也不能太大(内存溢出),类似的,我们可以测试一下不同集合类( ArrayList LinkedList HashSet HashMap 等)的查询和添加数据的速度,由此你在以后的项目中根据具体情况使用。

 

 

 

姓名:肖波

时间: 2009-4-12

 

 

 

你可能感兴趣的:(Java基础)