首页 > 代码库 > Java基础

Java基础

一,String,StringBuilder和StringBuffer的区别

同:三者都是final类,主要操作对象都是char[]

异:

1,继承结构,String继承自Object,实现了Serializable,Comparable,CharSequence,而StringBuilder和StringBuffer的父类是AbstractStringBuilder,实现接口Serializable, CharSequence;

2,在操作字符串时,String的"+"编译后会是new StringBuider(str)再.append(otherStr),最后把StringBuilder对象返回,在反编译文件中非常明显,而StringBuilder和StringBuffer的append方法,最后都是调用父类AbstracStringBuilder的append(String str)方法;

例如:

        static String getStr(){
		return "abc";
	}
	
	public static void main(String[] args) {
		
		String dist = "hello ";
		String tmp = dist + getStr();
        }
编译后是:

        static String getStr()
	{
		return "abc";
	}

	public static void main(String args[])
	{
                String dist = "hello ";
		String tmp = (new StringBuilder(String.valueOf(dist))).append(getStr()).toString();
         }


3,线程同步问题,由于String的"+"是和StringBuilder操作字符串的方式一致,从源代码看,StringBuilder的append方法不是线程安全,所以String和StringBuilder对字符串的操作不是线程安全,而StringBuiffer是线程安全。

源代码StringBuilder:

    @Override
    public StringBuilder append(String str) {
        super.append(str);
        return this;
    }
源代码StringBuffer:

    @Override
    public synchronized StringBuffer append(String str) {
        toStringCache = null;
        super.append(str);
        return this;
    }

4,效率问题,

a,在编译时可以确定字符对象的情况下,编译器会将"+"两边的字符串拼接后作为一个常量,不管是String+,还是StringBuilder().append(stri1+str2),这种情况下,String+的代码效率是最高的,因为jvm只需要操作常量池中的一个对象;

例如:

String tmp4 = "a" + "b" + "c";
System.out.println(tmp4);
编译后,在class文件中反编译过来是这样的:

String tmp4 = "abc";
System.out.println(tmp4);

b,在编译时不能确定字符对象的情况下,尽量用StringBuilder或者StringBuffer,如果有线程安全问题,采用StringBuffer,并且在创建StringBuffer和StringBuilder对象时,要注意传给构造器参数,在父类AbstractStringBuilder的类中,有一个构造器AbstractStringBuilder(int capacity),这个capacity对效率的影响非常大,默认是16,如果append()的字符长度超过了16,会capacity = << 1,即是16左移1位,新建一个容量capacity 为32的对象,再把之前的已经填满的char[16]的数组拷贝到新对象的前面16个下标中,然后再append后面的数据。所以,如果capacity 太小,会造成多次的resize,这个动作很费资源。

StringBuilder和StringBuffer构造器的源代码:

    /**
     * Constructs a string builder with no characters in it and an
     * initial capacity of 16 characters.
     */
    public StringBuilder() {
        super(16);
    }

    /**
     * Constructs a string builder with no characters in it and an
     * initial capacity specified by the {@code capacity} argument.
     *
     * @param      capacity  the initial capacity.
     * @throws     NegativeArraySizeException  if the {@code capacity}
     *               argument is less than {@code 0}.
     */
    public StringBuilder(int capacity) {
        super(capacity);
    }

AbstractStringBuilder的构造器:

    /**
     * Creates an AbstractStringBuilder of the specified capacity.
     */
    AbstractStringBuilder(int capacity) {
        value = http://www.mamicode.com/new char[capacity];>

append方法和那个resize的方法:

    public AbstractStringBuilder append(String str) {
        if (str == null)
            return appendNull();
        int len = str.length();
        ensureCapacityInternal(count + len);
        str.getChars(0, len, value, count);
        count += len;
        return this;
    }
    void expandCapacity(int minimumCapacity) {
        int newCapacity = value.length * 2 + 2;
        if (newCapacity - minimumCapacity < 0)
            newCapacity = minimumCapacity;
        if (newCapacity < 0) {
            if (minimumCapacity < 0) // overflow
                throw new OutOfMemoryError();
            newCapacity = Integer.MAX_VALUE;
        }
        value = http://www.mamicode.com/Arrays.copyOf(value, newCapacity);>
二,HashMap和HashTable的区别?

1,继承结构,都实现了Map接口,Cloneable和Serializable接口,但是HashMap继承自AbstractMap,Hashtable继承自Dictionary,从继承结构来看,Hashtable多了两个从Dictionary继承的方法keys和elements;

2,HashTable是线程安全的,HashMap是非线程安全;

3,HashMap可以有一个key为null,值任意,Hashtable不允许key为null

4,如果key存在,table不会覆盖旧值,map则会覆盖。

5,HashMap的set是一个TreeNode,HashTable是一个Synchornize


Java基础