Java基础

来源:互联网 发布:网络it培训 编辑:程序博客网 时间:2024/05/29 00:32

一,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 = 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 = 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


0 0