大战熟女丰满人妻av-荡女精品导航-岛国aaaa级午夜福利片-岛国av动作片在线观看-岛国av无码免费无禁网站-岛国大片激情做爰视频

第一部分 Java基礎
第二部分 Java進階

Java集合面試題

1、HashMap排序題

已知一個 HashMap<Integer,User>集合, User 有 name(String)和 age(int)屬性。請寫一個方法實現對HashMap 的排序功能,該方法接收 HashMap<Integer,User>為形參,返回類型為 HashMap<Integer,User>,要求對 HashMap 中的 User 的 age 倒序進行排序。排序時 key=value 鍵值對不得拆散。

注意:要做出這道題必須對集合的體系結構非常的熟悉。HashMap本身就是不可排序的,但是該題偏偏讓HashMap排序,那我們就得想在API中有沒有這樣的 Map 結構是有序的,我們不難發現其中LinkedHashMap就具有這樣的結構,是鏈表結構有序的,更可喜的是他是  HashMap的子類,我們返回LinkedHashMap<Integer,User>即可,還符合面向接口編程的思想。

但凡是對集合的操作,我們應該保持一個原則就是能用JDK中的API就用JDK中的 API,比如排序算法我們不應該去用冒泡或者選擇,而是首先想到用 Collections 集合工具類。

import java.util.*;

class HashMapTest {
    public static void main(String[] args) {
        HashMap<Integer, User> users = new HashMap<>();
        users.put(1, new User("張三", 25));
        users.put(3,new User("李四",22));
        users.put(2, new User("王五", 28));
        System.out.println(users);
        HashMap<Integer, User> sortHashMap = sortHashMap(users);
        System.out.println(sortHashMap);
        /**
         * 控制臺輸出內容
         * {1=User [name=張三, age=25], 2=User [name=王五,age=28], 3=User [name=李四, age=22]}
         * {2=User [name=王五, age=28], 1=User [name=張三, age=25], 3=User [name=李四, age=22]}
         */
    }

    public static HashMap<Integer, User> sortHashMap(HashMap<Integer, User> map) {
        // 首先拿到 map 的鍵值對集合
        Set<Map.Entry<Integer, User>> entrySet = map.entrySet();
        // 將 set 集合轉為 List 集合,為什么,為了使用工具類的排序方法
        List<Map.Entry<Integer,User>> list = new ArrayList<Map.Entry<Integer, User>>(entrySet);
        // 使用 Collections 集合工具類對 list 進行排序,排序規則使用匿名內部類來實現
        Collections.sort(list, new Comparator<Map.Entry<Integer, User>>() {
            @Override
            public int compare(Map.Entry<Integer, User> o1, Map.Entry<Integer, User> o2) {
                //按照要求根據 User 的 age 的倒序進行排
                return o2.getValue().getAge() - o1.getValue().getAge();
            }
        });
        //創建一個新的有序的 HashMap 子類的集合
        LinkedHashMap<Integer, User> linkedHashMap = new LinkedHashMap<Integer, User>();
        //將 List 中的數據存儲在 LinkedHashMap 中
        for (Map.Entry<Integer,User> entry : list) {
            linkedHashMap.put(entry.getKey(), entry.getValue());
        }
        return linkedHashMap;
    }
}

class User {
    private String name;
    private int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

2、請問 ArrayList、HashSet、HashMap 是線程安全的嗎?如果不是怎么獲取線程安全的集合?

通過以上類的源碼進行分析,每個方法都沒有加鎖,顯然都是非線程安全的。在集合中Vector 和HashTable是線程安全的。打開源碼會發現其實就是把各自核心方法添加上了synchronized 關鍵字。Collections工具類提供了相關的 API,可以讓上面那3個不安全的集合變為安全的。

Collections.synchronizedCollection(c);
Collections.synchronizedList(list);
Collections.synchronizedMap(m);
Collections.synchronizedSet(s);

上面幾個函數都有對應的返回值類型,傳入什么類型返回什么類型。打開源碼其實原理非常簡單,就是將集合的核心方法添加上了synchronized關鍵字。

3、ArrayList內部用什么實現的?

回答這樣的問題,不要只回答個皮毛,可以再介紹一下ArrayList內部是如何實現數組的增加和刪除的,因為數組在創建的時候長度是固定的,那么就有個問題我們往ArrayList中不斷的添加對象,它是如何管理這些數組呢?通過源碼可以看到ArrayList內部是用Object[]實現的。接下來我們分別分析ArrayList的構造以及add()、remove()、clear()方法的實現原理。

● 無參數構造方法

/**
 * Constructs a new {@code ArrayList} instance with zero initial capacity.
 */
public ArrayList(){
    array=EmptyArray.OBJECT;
}

array 是一個 Object[]類型。當我們 new 一個空參構造時系統調用了 EmptyArray.OBJECT 屬性,EmptyArray 僅僅是一個系統的類庫,該類源碼如下:

public final class EmptyArray {
    private EmptyArray() {
    }
    public static final boolean[] BOOLEAN = new boolean[0];
    public static final byte[] BYTE = new byte[0];
    public static final char[] CHAR = new char[0];
    public static final double[] DOUBLE = new double[0];
    public static final int[] INT = new int[0];
    public static final Class<?>[] CLASS = new Class[0];
    public static final Object[] OBJECT = new Object[0];
    public static final String[] STRING = new String[0];
    public static final Throwable[] THROWABLE = new Throwable[0];
    public static final StackTraceElement[] STACK_TRACE_ELEMENT = new StackTraceElement[0];
}

也就是說當我們 new 一個空參 ArrayList 的時候,系統內部使用了一個 new Object[0]數組。

● 帶容量參數的構造器

/**
 * Constructs a new instance of {@code ArrayList} with the specified
 * initial capacity.
 * @param capacity the initial capacity of this {@code ArrayList}.
 */
public ArrayList(int capacity) {
    if (capacity < 0) {
        throw new IllegalArgumentException("capacity < 0: " + capacity);
    }
    array = (capacity == 0 ? EmptyArray.OBJECT : new Object[capacity]);
}

該構造函數傳入一個 int 值,該值作為數組的長度值。如果該值小于 0,則拋出一個運行時異常。如果等于 0,則使用一個空數組,如果大于 0,則創建一個長度為該值的新數組。

● 帶集合參數的構造器

/**
 * Constructs a new instance of {@code ArrayList} containing the elements of
 * the specified collection.
 *
 * @param collection the collection of elements to add.
 */
public ArrayList(Collection<? extends E> collection) {
    if (collection == null) {
        throw new NullPointerException("collection == null");
    }

    Object[] a = collection.toArray();
    if (a.getClass() != Object[].class) {
        Object[] newArray = new Object[a.length];
        System.arraycopy(a, 0, newArray, 0, a.length);
        a = newArray;
    }
    array = a;
    size = a.length;
}

如果調用構造函數的時候傳入了一個 Collection 的子類,那么先判斷該集合是否為 null,為 null 則拋出空指針異常。如果不是則將該集合轉換為數組 a,然后將該數組賦值為成員變量 array,將該數組的長度作為成員變量 size。

● add方法

/**
 * Adds the specified object at the end of this {@code ArrayList}.
 *
 * @param object the object to add.
 * @return always true
 */
@Override
public boolean add(E object) {
    Object[] a = array;
    int s = size;
    if (s == a.length) {
        Object[] newArray = new Object[s +
                (s < (MIN_CAPACITY_INCREMENT / 2) ? MIN_CAPACITY_INCREMENT : s >> 1)];
        System.arraycopy(a, 0, newArray, 0, s);
        array = a = newArray;
    }
    a[s] = object;
    size = s + 1;
    modCount++;
    return true;
}

● 第一:首先將成員變量 array 賦值給局部變量 a,將成員變量 size 賦值給局部變量 s。

● 第二:判斷集合的長度 s 是否等于數組的長度(如果集合的長度已經等于數組的長度了,說明數組已經滿了,該重新分 配 新 數 組 了 ) , 重 新 分 配 數 組 的 時 候 需 要 計 算 新 分 配 內 存 的 空 間 大 小 , 如 果 當 前 的 長 度 小 于MIN_CAPACITY_INCREMENT/2(這個常量值是 12,除以 2 就是 6,也就是如果當前集合長度小于 6)則分配 12 個長度,如果集合長度大于 6 則分配當前長度 s 的一半長度。這里面用到了三元運算符和位運算,s >> 1,意思就是將s 往右移 1 位,相當于 s=s/2,只不過位運算是效率最高的運算。

● 第三:將新添加的 object 對象作為數組的 a[s]個元素。

● 第四:修 改 集 合 長 度size為s+1。

● 第五:modCount++,該變量是父類中聲明的,用于記錄集合修改的次數,記錄集合修改的次數是為了防止在用迭代器迭代集合時避免并發修改異常,或者說用于判斷是否出現并發修改異常的。

● 第六:return true,這個返回值意義不大,因為一直返回 true,除非報了一個運行時異常。

● remove方法

/**
 * Removes the object at the specified location from this list.
 *
 * @param index the index of the object to remove.
 * @return the removed object.
 * @throws IndexOutOfBoundsException when {@code location < 0 || location >= size()}
 */
@Override
public E remove(int index) {
    Object[] a = array;
    int s = size;
    if (index >= s) {
        throwIndexOutOfBoundsException(index, s);
    }
    @SuppressWarnings("unchecked") E result = (E) a[index];
    System.arraycopy(a, index + 1, a, index, --s - index);
    a[s] = null; // Prevent memory leak
    size = s;
    modCount++;
    return result;
}

● 第一:先將成員變量 array 和 size 賦值給局部變量 a 和 s。

● 第二:判斷形參 index 是否大于等于集合的長度,如果成了則拋出運行時異常

● 第三:獲取數組中腳標為 index 的對象 result,該對象作為方法的返回值

● 第四:調用 System 的 arraycopy 函數完成數組拷貝。

● 第五:接下來就是很重要的一個工作,因為刪除了一個元素,而且集合整體向前移動了一位,因此需要將集合最后一個元素設置為 null,否則就可能內存泄露。

● 第六:重新給成員變量 array 和 size 賦值。

● 第七:記錄修改次數。

● 第八:返回刪除的元素。

● clear方法

/**
 * Removes all elements from this {@code ArrayList}, leaving it empty.
 *
 * @see #isEmpty
 * @see #size
 */
@Override
public void clear() {
    if (size != 0) {
        Arrays.fill(array, 0, size, null);
        size = 0;
        modCount++;
    }
}

如果集合長度不等于 0,則將所有數組的值都設置為 null,然后將成員變量 size 設置為 0 即可,最后讓修改記錄加 1。

4、并發集合和普通集合如何區別?

并發集合常見的有ConcurrentHashMap、ConcurrentLinkedQueue、ConcurrentLinkedDeque等。并發集合位于java.util.concurrent包下,是jdk1.5之后才有的,在 java 中有普通集合、同步(線程安全)的集合、并發集合。

普通集合通常性能最高,但是不保證多線程的安全性和并發的可靠性。線程安全集合僅僅是給集合添加了 synchronized 同步鎖,嚴重犧牲了性能,而且對并發的效率就更低了,并發集合則通過復雜的策略不僅保證了多線程的安全又提高的并發時的效率。

參考閱讀:ConcurrentHashMap 是線程安全的 HashMap 的實現,默認構造同樣有 initialCapacity 和 loadFactor 屬性, 不過還多了一個 concurrencyLevel 屬性,三屬性默認值分別為 16、0.75 及 16。其內部使用鎖分段技術,維持這鎖Segment 的數組,在 Segment 數組中又存放著 Entity[]數組,內部 hash 算法將數據較均勻分布在不同鎖中。put 操作:并沒有在此方法上加上 synchronized,首先對 key.hashcode 進行 hash 操作,得到 key 的 hash 值。hash 操作的算法和map 也不同,根據此hash 值計算并獲取其對應的數組中的Segment 對象(繼承自ReentrantLock),接著調用此 Segment 對象的 put 方法來完成當前操作。ConcurrentHashMap 基于 concurrencyLevel 劃分出了多個 Segment 來對 key-value 進行存儲,從而避免每次 put 操作都得鎖住整個數組。在默認的情況下,最佳情況時可允許 16 個線程并發無阻塞的操作集合對象,盡可能地減少并發時的阻塞現象。get(key)首先對 key.hashCode 進行 hash 操作,基于其值找到對應的 Segment 對象,調用其 get 方法完成當前操作。而 Segment 的 get 操作首先通過 hash 值和對象數組大小減1的值進行按位與操作來獲取數組上對應位置的HashEntry。在這個步驟中,可能會因為對象數組大小的改變,以及數組上對應位置的 HashEntry 產生不一致性,那么 ConcurrentHashMap 是如何保證的?對象數組大小的改變只有在 put 操作時有可能發生,由于 HashEntry 對象數組對應的變量是 volatile 類型的,因此可以保證如 HashEntry 對象數組大小發生改變,讀操作可看到最新的對象數組大小。在獲取到了 HashEntry 對象后,怎么能保證它及其 next 屬性構成的鏈表上的對象不會改變呢?這點ConcurrentHashMap 采用了一個簡單的方式,即 HashEntry 對象中的 hash、key、next 屬性都是 final 的,這也就意味著沒辦法插入一個 HashEntry 對象到基于 next 屬性構成的鏈表中間或末尾。這樣就可以保證當獲取到 HashEntry 對象后,其基于 next 屬性構建的鏈表是不會發生變化的。ConcurrentHashMap 默認情況下采用將數據分為 16 個段進行存儲,并且 16 個段分別持有各自不同的鎖Segment,鎖僅用于 put 和 remove 等改變集合對象的操作,基于 volatile 及 HashEntry 鏈表的不變性實現了讀取的不加鎖。這些方式使得 ConcurrentHashMap 能夠保持極好的并發支持,尤其是對于讀遠比插入和刪除頻繁的 Map 而言,而它采用的這些方法也可謂是對于 Java 內存模型、并發機制深刻掌握的體現。

5、List 和 Map、Set 的區別?

● 結構特點:List 和 Set 是存儲單列數據的集合,Map 是存儲鍵和值這樣的雙列數據的集合;List 中存儲的數據是有順序,并且允許重復;Map 中存儲的數據是沒有順序的,其鍵是不能重復的,它的值是可以有重復的,Set 中存儲的數據是無序的,且不允許有重復,但元素在集合中的位置由元素的 hashCode 決定,位置是固定的(Set 集合根據 hashCode 來進行數據的存儲,所以位置是固定的,但是位置不是用戶可以控制的,所以對于用戶來說 Set 中的元素還是無序的);

● 實現類:List 接口下的實現類(LinkedList:基于鏈表實現,鏈表內存是散亂的,每一個元素存儲本身內存地址的同時還存儲下一個元素的地址。鏈表增刪快,查找慢;ArrayList:基于數組實現,非線程安全的,效率高,便于索引,但不便于插入刪除;Vector:基于數組實現,線程安全的,效率低)。Map 接口下的實現類(HashMap:基于 hash 表的 Map 接口實現,非線程安全,高效,支持 null 值和 null 鍵;Hashtable:線程安全,低效,不支持 null 值和  null 鍵;LinkedHashMap:是HashMap 的一個子類,保存了記錄的插入順序;SortedMap 接口:TreeMap,能夠把它保存的記錄根據鍵排序,默認是鍵值的升序排序)。Set 接口下的實現類(HashSet:底層是由 HashMap 實現,不允許集合中有重復的值,使用該方式時需要重寫 equals()和 hashCode()方法;LinkedHashSet繼承與 HashSet,同時又基于LinkedHashMap 來進行實現,底層使用的是LinkedHashMp)。

● 區別:List集合中對象按照索引位置排序,可以有重復對象,允許按照對象在集合中的索引位置檢索對象,例如通過list.get(i)方法來獲取集合中的元素;Map中的每一個元素包含一個鍵和一個值,成對出現,鍵對象不可以重復,值對象可以重復;Set集合中的對象不按照特定的方式排序,并且沒有重復對象,但它的實現類能對集合中的對象按照特定的方式排序,例如 TreeSet類,可以按照默認順序,也可以通過實現 java.util.Comparator接口來自定義排序方式。

6、HashMap和Hashtable有什么區別?

HashMap是非線程安全的,HashMap是Map的一個實現類,是將鍵映射到值的對象,不允許鍵值重復。允許空鍵和空值;由于非線程安全,HashMap的效率要較 Hashtable 的效率高一些。Hashtable 是線程安全的一個集合,不允許 null 值作為一個 key 值或者value 值;Hashtable是sychronized,多個線程訪問時不需要自己為它的方法實現同步,而 HashMap 在被多個線程訪問的時候需要自己為它的方法實現同步。

7、數組和鏈表分別比較適合用于什么場景,為什么?

● 數組和鏈表的區別

數組是將元素在內存中連續存儲的;它的優點:因為數據是連續存儲的,內存地址連續,所以在查找數據的時候效率比較高;它的缺點:在存儲之前,我們需要申請一塊連續的內存空間,并且在編譯的時候就必須確定好它的空間的大小。在運行的時候空間的大小是無法隨著你的需要進行增加和減少而改變的,當數據兩比較大的時候,有可能會出現越界的情況,數據比較小的時候,又有可能會浪費掉內存空間。在改變數據個數時,增加、插入、刪除數據效率比較低。鏈表是動態申請內存空間,不需要像數組需要提前申請好內存的大小,鏈表只需在用的時候申請就可以,根據需要來動態申請或者刪除內存空間,對于數據增加和刪除以及插入比數組靈活。還有就是鏈表中數據在內存中可以在任意的位置,通過應用來關聯數據(就是通過存在元素的地址來聯系)

● 鏈表和數組使用場景

數組應用場景:數據比較少;經常做的運算是按序號訪問數據元素;數組更容易實現,任何高級語言都支持;構建的線性表較穩定。

鏈表應用場景:對線性表的長度或者規模難以估計;頻繁做插入刪除操作;構建動態性比較強的線性表。

8、Java中ArrayList和LinkedList區別?

ArrayList和Vector使用了數組的實現,可以認為 ArrayList 或者 Vector 封裝了對內部數組的操作,比如向數組中添加、刪除、插入新的元素或者數據的擴展和重定向。

LinkedList 使用了循環雙向鏈表數據結構。與基于數組的 ArrayList 相比,這是兩種截然不同的實現技術,這也決定了它們將適用于完全不同的工作場景。

LinkedList 鏈表由一系列表項連接而成。一個表項總是包含 3 個部分:元素內容,前驅表和后驅表,如圖所示:

在下圖展示了一個包含 3 個元素的 LinkedList 的各個表項間的連接關系。在 JDK 的實現中,無論 LikedList 是否為空,鏈表內部都有一個 header 表項,它既表示鏈表的開始,也表示鏈表的結尾。表項 header 的后驅表項便是鏈表中第一個元素,表項 header 的前驅表項便是鏈表中最后一個元素。

ArrayList 是實現了基于動態數組的數據結構,LinkedList 基于鏈表的數據結構。如果集合數據是對于集合隨機訪問 get 和 set,ArrayList 絕對優于 LinkedList,因為 LinkedList 要移動指針。如果集合數據是對于集合新增和刪除操作 add 和 remove,LinkedList 比較占優勢,因為ArrayList要移動數據。

ArrayList 和 LinkedList 是兩個集合類,用于存儲一系列的對象引用(references)。例如我們可以用 ArrayList 來存儲一系列的 String 或者 Integer。那么 ArrayList 和 LinkedList 在性能上有什么差別呢?什么時候應該用 ArrayList 什么時候又該用 LinkedList 呢?

● 時間復雜度

首先一點關鍵的是,ArrayList 的內部實現是基于基礎的對象數組的,因此,它使用 get 方法訪問列表中的任意一個元素時(random access),它的速度要比 LinkedList 快。LinkedList 中的 get 方法是按照順序從列表的一端開始檢查,直到另外一端。對 LinkedList 而言,訪問列表中的某個指定元素沒有更快的方法了。

假設我們有一個很大的列表,它里面的元素已經排好序了,這個列表可能是 ArrayList 類型的也可能是 LinkedList 類型的,現在我們對這個列表來進行二分查找(binary search),比較列表是 ArrayList 和 LinkedList 時的查詢速度,看下面的程序:

public class TestList {
    public static final int N = 50000;    //50000 個數
    public static List values; //要查找的集合
    //放入 50000 個數給 value;
    static {
        Integer vals[] = new Integer[N];
        Random r = new Random();
        for (int i = 0, currval = 0; i < N; i++) {
            vals = new Integer(currval);
            currval += r.nextInt(100) + 1;
        }
        values = Arrays.asList(vals);
    }
    //通過二分查找法查找
    static long timeList(List lst) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < N; i++) {
            int index = Collections.binarySearch(lst, values.get(i));
            if (index != i)
                System.out.println("***錯誤***");
        }
        return System.currentTimeMillis() - start;
    }
    public static void main(String args[]) {
        System.out.println("ArrayList 消耗時間:" + timeList(new ArrayList(values)));
        System.out.println("LinkedList 消耗時間:" + timeList(new LinkedList(values)));
    }
}

LinkedList 做隨機訪問所消耗的時間與這個 list 的大小是成比例的。而相應的,在 ArrayList 中進行隨機訪問所消耗的時間是固定的。

這是否表明 ArrayList 總是比 LinkedList 性能要好呢?這并不一定,在某些情況下 LinkedList 的表現要優于ArrayList,有些算法在 LinkedList 中實現時效率更高。比方說,利用 Collections.reverse 方法對列表進行反轉時,其性能就要好些。看這樣一個例子,加入我們有一個列表,要對其進行大量的插入和刪除操作,在這種情況下LinkedList 就是一個較好的選擇。請看如下一個極端的例子,我們重復的在一個列表的開端插入一個元素:

public class ListDemo {
    static final int N = 50000;
    static long timeList(List list) {
        long start = System.currentTimeMillis();
        Object o = new Object();
        for (int i = 0; i < N; i++)
            list.add(0, o);
        return System.currentTimeMillis() - start;
    }
    public static void main(String[] args) {
        System.out.println("ArrayList 耗時:" + timeList(new ArrayList()));
        System.out.println("LinkedList 耗時:" + timeList(new LinkedList()));
    }
}

輸出結果是:

ArrayList 耗時:2463

LinkedList 耗時:15

● 空間復雜度

在 LinkedList 中有一個私有的內部類,定義如下:

private static class Entry {
    Object element;
    Entry next;
    Entry previous;
}

每個 Entry對象reference列表中的一個元素,同時還有在 LinkedList 中它的上一個元素和下一個元素。一個有1000個元素的LinkedList 對象將有 1000 個鏈接在一起的 Entry 對象,每個對象都對應于列表中的一個元素。這樣的話,在一個 LinkedList 結構中將有一個很大的空間開銷,因為它要存儲這 1000 個 Entity 對象的相關信息。

ArrayList 使用一個內置的數組來存儲元素,這個數組的起始容量是10。當數組需要增長時,新的容量按如下公式獲得:新容量=(舊容量*3)/2+1,也就是說每一次容量大概會增長 50%。這就意味著,如果你有一個包含大量元素的 ArrayList 對象,那么最終將有很大的空間會被浪費掉,這個浪費是由ArrayList 的工作方式本身造成的。如果沒有足夠的空間來存放新的元素,數組將不得不被重新進行分配以便能夠增加新的元素。對數組進行重新分配,將會導致性能急劇下降。如果我們知道一個ArrayList將會有多少個元素,我們可以通過構造方法來指定容量。我們還可以通過 trimToSize 方法在 ArrayList 分配完畢之后去掉浪費掉的空間。

● 總結

ArrayList 和 LinkedList 在性能上各有優缺點,都有各自所適用的地方,總的說來可以描述如下:

第一:對 ArrayList 和 LinkedList 而言,在列表末尾增加一個元素所花的開銷都是固定的。對 ArrayList 而言,主要是在內部數組中增加一項,指向所添加的元素,偶爾可能會導致對數組重新進行分配;而對 LinkedList 而言,這個開銷是統一的,分配一個內部 Entry 對象。

第二:在 ArrayList 的中間插入或刪除一個元素意味著這個列表中剩余的元素都會被移動;而在 LinkedList 的中間插入或刪除一個元素的開銷是固定的。

第三:LinkedList 不支持高效的隨機元素訪問。

第四:ArrayList 的空間浪費主要體現在在 list 列表的結尾預留一定的容量空間,而 LinkedList 的空間花費則體現在它的每一個元素都需要消耗相當的空間。

可以這樣說:當操作是在一列數據的后面添加數據而不是在前面或中間,并且需要隨機地訪問其中的元素時,使用ArrayList 會提供比較好的性能;當你的操作是在一列數據的前面或中間添加或刪除數據,并且按照順序訪問其中的元素時,就應該使用LinkedList了。

9、List a=new ArrayList()和ArrayList a =new ArrayList()的區別?

List list = new ArrayList();這句創建了一個 ArrayList 的對象后賦給了List。此時它是一個 List 對象了,有些ArrayList 有但是 List 沒有的屬性和方法,它就不能再用了。而ArrayList list=new ArrayList();創建一對象則保留了ArrayList 的所有屬性。 所以需要用到 ArrayList 獨有的方法的時候不能用前者。實例代碼如下:

List list = new ArrayList();
ArrayList arrayList = new ArrayList();
list.trimToSize(); //錯誤,沒有該方法。
arrayList.trimToSize();    //ArrayList 里有該方法。

10、請用兩個隊列模擬堆棧結構?

兩個隊列模擬一個堆棧,隊列是先進先出,而堆棧是先進后出。模擬如下隊列 a 和 b:

● 入棧:a 隊列為空,b 為空。例:則將”a,b,c,d,e”需要入棧的元素先放 a 中,a 進棧為”a,b,c,d,e”出棧:a 隊列目前的元素為”a,b,c,d,e”。將 a 隊列依次加入 Arraylist 集合 a 中。以倒序的方法,將 a 中的集合取出,放入 b 隊列中,再將 b 隊列出列。代碼如下:

public static void main(String[] args) {
    Queue<String> queue = new LinkedList<String>(); //a 隊 列
    Queue<String> queue2 = new LinkedList<String>();    //b 隊列
    ArrayList<String> a = new ArrayList<String>();    //arrylist 集合是中間參數
    //往 a 隊列添加元素
    queue.offer("a");
    queue.offer("b");
    queue.offer("c");
    queue.offer("d");
    queue.offer("e");
    System.out.print("進棧:");    //a 隊列依次加入 list 集合之中
    for (String q : queue) {
        a.add(q);
        System.out.print(q);
    }
    //以倒序的方法取出(a 隊列依次加入 list 集合)之中的值,加入 b 對列
    for (int i = a.size() - 1; i >= 0; i--) {
        queue2.offer(a.get(i));
    }
    //打印出棧隊列
    System.out.println("");
    System.out.print("出棧:");
    for (String q : queue2) {
        System.out.print(q);
    }
}

運行結果為(遵循棧模式先進后出):

進棧:a b c d e

出棧:e d c b a

11、Map中的key和value可以為null?

HashMap 對象的 key、value 值均可為 null。Hahtable 對象的 key、value 值均不可為 null。且兩者的的 key 值均不能重復,若添加 key 相同的鍵值對,后面的 value 會自動覆蓋前面的 value,但不會報錯。測試代碼如下:

public class Test {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<String, String>();//HashMap 對象
        Map<String, String> tableMap = new Hashtable<String, String>();//Hashtable 對象
        map.put(null, null);
        System.out.println("hashMap 的[key]和[value]均可以為 null:" + map.get(null));
        try {
            tableMap.put(null, "3");
            System.out.println(tableMap.get(null));
        } catch (Exception e) {
            System.out.println("【ERROR】:hashtable 的[key]不能為 null");
        }
        try {
            tableMap.put("3", null);
            System.out.println(tableMap.get("3"));
        } catch (Exception e) {
            System.out.println("【ERROR】:hashtable的[value]不能為null");
        }
    }
}

運行結果:

hashMap 的[key]和[value]均可以為 null:null

【ERROR】:hashtable 的[key]不能為 null

【ERROR】:hashtable 的[value]不能為 null

全部教程
主站蜘蛛池模板: 五月天在线婷婷 | 亚洲在线国产 | 四虎影院官网 | 免费福利网站在线观看 | 一级毛片日韩 | 99久久免费国产精品热 | 国内精品综合九九久久精品 | 女十八毛片 | 四虎sihu新版影院亚洲精品 | 久久久国产精品免费看 | 91粉色视频在线观看 | 免费国产福利 | 久久亚洲综合伊人 | 亚洲一成人毛片 | 国产欧美成人一区二区三区 | 在线观看麻豆国产精品 | se成人国产精品 | 日日拍夜夜嗷嗷叫视频 | 超碰v| 奇米第四色在线视频 | 国产午夜精品久久理论片 | 成人a级特黄毛片 | 精品美女在线观看 | 香蕉18xxoo欧美夜视频 | 成年人国产网站 | 欧美一区二区三区东南亚 | 国产成人精品午夜免费 | 99精品国产三级在线观看 | 亚洲一区二区三区高清网 | 国产福利在线小视频 | 免费看日韩欧美一级毛片 | 91香蕉国产亚洲一区二区三区 | 亚洲国产韩国一区二区 | 91亚洲精品一区二区自 | 欧洲成人免费视频 | 综合视频网 | 国产亚洲精品美女久久久久 | 爱爱小视频免费体验区在线观看 | 女人18特级一级毛片免费视频 | 不卡的中文字幕 | 国产精品一区二区资源 |