1. 程式人生 > >JAVA面試題整理-基礎

JAVA面試題整理-基礎

catch inflate 線程 cat serializa table lca sort str

1、List 和 Set 的區別

共同點:它們都是Collection的子接口

區別:

List:這個接口能夠精準的記錄每一個元素的插入位置(換句話說就是這個接口內容所有元素是按照順序去保存的),使用者可以通過索引的方式去取得某個元素的值,這個跟java中數組有點類似,List中保存的所有數據允許重復
Set:這個接口無法記錄每一個元素的具體位置,整個集合中所有元素是無序排列的,並且Set存儲數據集合是不允許有重復的元素的。

既然List和Set均為接口,那麽就不能直接實例化,需要借助實現他們接口的子類進行實例化,由此來使用接口中提供的各種方法。
實現List接口的子類中包括:ArrayList,LinkedList和Vector


其中ArrayList這個類是類似數組形式的集合實例化,而LinkedList類則是鏈表形式的實例化,具體的差別在於數據結構上面的不同。
Vector 類非常類似ArrayList,兩者的不同之處在於Vector是同步的方法,在多線程操作的時候可能會拋出ConcurrentModificationException。
實現Set接口的子類中包括:HasSet


2、HashSet 是如何保證不重復的

根據HashSet.add(E e)的JDK源碼,發現HashSet竟然是借助HashMap來實現的,利用HashMap中Key的唯一性,來保證HashSet中不出現重復值。

當調用add(E e)方法時候,首先會調用Object的hashCode方法判hashCode是否已經存在,如不存在則直接插入元素;

如果已存在則調用Object對象的equals方法判斷是否返回true,如果為true則說明元素已經存在,如為false則插入元素。

public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable
{
    static final long serialVersionUID = -5024744406713321676L;

    private transient HashMap<E,Object> map;

    
// Dummy value to associate with an Object in the backing Map private static final Object PRESENT = new Object(); /** * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has * default initial capacity (16) and load factor (0.75). */ public HashSet() { map = new HashMap<>(); } public HashSet(Collection<? extends E> c) { map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16)); addAll(c); } public HashSet(int initialCapacity, float loadFactor) { map = new HashMap<>(initialCapacity, loadFactor); } public HashSet(int initialCapacity) { map = new HashMap<>(initialCapacity); } HashSet(int initialCapacity, float loadFactor, boolean dummy) { map = new LinkedHashMap<>(initialCapacity, loadFactor); } public Iterator<E> iterator() { return map.keySet().iterator(); } public int size() { return map.size(); } public boolean isEmpty() { return map.isEmpty(); } public boolean contains(Object o) { return map.containsKey(o); } public boolean add(E e) { return map.put(e, PRESENT)==null; } public boolean remove(Object o) { return map.remove(o)==PRESENT; } public void clear() { map.clear(); } public Object clone() { try { HashSet<E> newSet = (HashSet<E>) super.clone(); newSet.map = (HashMap<E, Object>) map.clone(); return newSet; } catch (CloneNotSupportedException e) { throw new InternalError(); } } private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { // Write out any hidden serialization magic s.defaultWriteObject(); // Write out HashMap capacity and load factor s.writeInt(map.capacity()); s.writeFloat(map.loadFactor()); // Write out size s.writeInt(map.size()); // Write out all elements in the proper order. for (E e : map.keySet()) s.writeObject(e); } private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { // Read in any hidden serialization magic s.defaultReadObject(); // Read in HashMap capacity and load factor and create backing HashMap int capacity = s.readInt(); float loadFactor = s.readFloat(); map = (((HashSet)this) instanceof LinkedHashSet ? new LinkedHashMap<E,Object>(capacity, loadFactor) : new HashMap<E,Object>(capacity, loadFactor)); // Read in size int size = s.readInt(); // Read in all elements in the proper order. for (int i=0; i<size; i++) { E e = (E) s.readObject(); map.put(e, PRESENT); } } }
    /**
     * Associates the specified value with the specified key in this map.
     * If the map previously contained a mapping for the key, the old
     * value is replaced.
     *
     * @param key key with which the specified value is to be associated
     * @param value value to be associated with the specified key
     * @return the previous value associated with <tt>key</tt>, or
     *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
     *         (A <tt>null</tt> return can also indicate that the map
     *         previously associated <tt>null</tt> with <tt>key</tt>.)
     */
    public V put(K key, V value) {
        if (table == EMPTY_TABLE) {
            inflateTable(threshold);
        }
        if (key == null)
            return putForNullKey(value);
        int hash = hash(key);
        int i = indexFor(hash, table.length);
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }

        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }

3、HashMap 是線程安全的嗎,為什麽不是線程安全的(最好畫圖說明多線程環境下不安全)?

參考:http://www.importnew.com/22011.html

4、HashMap 的擴容過程
5、HashMap 1.7 與 1.8 的 區別,說明 1.8 做了哪些優化,如何優化的?
6、final finally finalize
7、強引用 、軟引用、 弱引用、虛引用
8、Java反射
9、Arrays.sort 實現原理和 Collection 實現原理
10、LinkedHashMap的應用
11、cloneable接口實現原理
12、異常分類以及處理機制
13、wait和sleep的區別
14、數組在內存中如何分配

答案待補充... ...

JAVA面試題整理-基礎