移除集合效率高还是add高_List、set集合接口分析
一、List接口詳解
1、List接口有三個實現類,ArrayList、LinkedList、Vector
2、三個實現類的異同點:
(1)ArrayList: 作為list接口的主要實現類;線程不安全,效率高;底層使用Object[]存儲
(2)LinkedList: 對于頻繁的插入、刪除操作,使用此類效率比ArrayList高;底層使用雙 向鏈表存儲
(3)Vector: 作為list接口的古老實現類;線程安全的,效率低;底層使用Object[]存儲
相同點:
三個類都是實現了list接口,存儲數據特點相同:存儲有序的、可重復的數據
3、ArrayList的源碼分析:
(1)jdk 1.7下的情況:
ArrayList list = new ArrayList(); // 底層創建了長度是10的Object[]數elementDate
list.add(123); //elementDate[0] = new Tnteger(123);
.....
list.add(111); // 如果此次的添加導致底層elementDate數組容量不夠,則擴容。默認情況下,擴容為原來的容量的1.5倍,同時需要將原來數組中的數據復制到新的數組中。
結論: 建議開發中使用帶參的構造器: ArrayList list = new ArrayList(int capacity)
(2)jdk1 1.8下的情況:
ArrayList list = new ArrayList(); // 底層Object[] elementDate初始化為{},并沒有創建長度為10的數組
list.add(123); // 第一次調用add()方法,底層才創建了長度為10的數組,并將數據123添加到elementDate[]數組中, 后續的添加和擴容操作和jdk 1.7一樣
(3) jdk7中的ArrayList的對象的創建類似于單例模式中的餓漢式,而jdk8中的ArrayList的對象的創建類似于單例模式中的懶漢式,延遲了數組的創建,節省內存。
4、ArrayList中常用的方法
增:add(Object obj)
刪:remove(int index) / remove(Object obj)
改:set(int index, Object ele)
查: get(int index)
插:add(int index, Object obj)
獲取長度: size()
遍歷:① Iterator迭代器方式
② 增強for循環
③ 普通的循環
5、LinkedList的源碼分析:
LinkedList list = new LinkedList(); // 內部聲明了Node類型的first和last屬性,默認值為null
list.add(123); //將123封裝到Node中,創建了Node對象。
其中,Node定義為:體現了LinkdList的雙向鏈表的說法
private static class Node<E> {* E item;* Node<E> next;* Node<E> prev;** Node(Node<E> prev, E element, Node<E> next) {* this.item = element;* this.next = next;* this.prev = prev;* }* }6、Vector的源碼分析:jdk7和jdk8中通過Vector()構造器創建對象時,底層都創建了長度為10的數組,在擴容方面,默認擴容為原來數組長度的2倍。
7、List接口中常用的方法
public class ArrayListTest {/*** ?void add(int index, Object ele):在index位置插入ele元素* ?boolean addAll(int index, Collection eles):從index位置開始將eles中 的所有元素添加進來* ?Object get(int index):獲取指定index位置的元素* ?int indexOf(Object obj):返回obj在集合中首次出現的位置* ?int lastIndexOf(Object obj):返回obj在當前集合中末次出現的位置* ?Object remove(int index):移除指定index位置的元素,并返回此元素* ?Object set(int index, Object ele):設置指定index位置的元素為ele* ?List subList(int fromIndex, int toIndex):返回從fromIndex到toIndex 位置的子集合*/public static void test01() {ArrayList list = new ArrayList();list.add(123);list.add(456);list.add("MM");list.add(false);System.out.println(list); // [123, 456, MM, false]//1、void add(int index, Object ele):在index位置插入ele元素list.add(1, "aaa");System.out.println(list); // [123, aaa, 456, MM, false]//2、boolean addAll(int index, Collection eles):從index位置開始將eles中 的所有元素添加進來List<Integer> list1 = Arrays.asList(1, 2, 3);list.addAll(list1);System.out.println(list.size()); // 8//3、Object get(int index):獲取指定index位置的元素System.out.println(list.get(1));}public static void test02() {ArrayList list = new ArrayList();list.add(123);list.add(456);list.add("MM");list.add(false);//4、int indexOf(Object obj):返回obj在集合中首次出現的位置.如果不存在,返回-1int indexOf = list.indexOf(456);System.out.println(indexOf);//5、Object remove(int index):移除指定index位置的元素,并返回此元素Object remove = list.remove(0);System.out.println(remove); // 返回刪除的數據System.out.println(list); // [456, MM, false]//6、Object set(int index, Object ele):設置指定index位置的元素為elelist.set(1, "CC");System.out.println(list); // [456, CC, false]}/*** ArrayList中三種遍歷方式:* 1、使用迭代器;* 2、for增強;* 3、普通for循環*/public static void test03() {ArrayList list = new ArrayList();list.add(123);list.add(456);list.add("MM");list.add(false);//1、使用迭代器Iterator iterator = list.iterator();while (iterator.hasNext()) {System.out.println(iterator.next());}System.out.println("**************");//2、for增強for (Object obj : list) {System.out.println(obj);}System.out.println("**************");//3、普通for循環for (int i = 0; i < list.size(); i++) {System.out.println(list.get(i));}}}二、set接口
1、set接口的特點:存儲無序的、不可重復的數據
2、set接口的幾個實現類:
(1)HashSet: 作為Set接口的主要實現類;線程不安全的:可以存儲null值;HashSet底層:數組 + 鏈表的結構
-- LinkedHashSet: 作為HashSet的子類:遍歷其內部數據時,可以按照添加的順序遍歷
(2) TreeSet: 可以按照添加對象的指定屬性,進行排序。
3、set接口的特點:存儲無序的、不可重復的數據說明
以HashSet為例說明:
(1)無序性: 不等于隨機性。存儲的數據在底層數組中并非按照數組索引的順序添加的,而是根據數據的哈希值
(2)不可重復性:保證添加的元素按照equals判斷時,不能反悔true,即:相同的元素只能添加一個。
public void test1(){Set hashSet = new HashSet();hashSet.add("123");hashSet.add(false);hashSet.add(567);hashSet.add(new User("Tom",23));hashSet.add(new User("Tom",23));hashSet.add(98);Iterator iterator = hashSet.iterator();while(iterator.hasNext()){System.out.println(iterator.next());}}4、LinkedHashSet使用
作為HashSet的子類,在添加數據的同時,每個數據還維護了兩個引用,記錄此數據前一個數據和后一個數據
優點:對于頻繁的遍歷操作,LinkedHashSet效率高于HashSet
5、Set接口中的添加方法的執行過程:(以HashSet為例)
向HashSet中添加元素a,首先調用元素a所在類的hashCode()方法,計算元素a的哈希值,此哈希值接著通過某種算法計算出在HashSet底層數組中的存放位置(即為:索引位置),判斷數組此位置上是否已經有元素
如果此位置上沒有其他元素,則元素a添加成功。 --- 情況1
如果此位置上有其他元素b(或以鏈表形式存在的多個元素)。則比較元素a與元素b的hash值:
如果hash值不相同,則元素a添加成功。 --- 情況2
如果hash值相同,進而需要調用元素a所在類的equals()方法:
equals()返回true,則元素a添加失敗
equals()返回false,則元素a添加成功 --- 情況3
對于添加成功的情況2和情況3而言:元素a與已經存在指定索引位置上數據以鏈表的方式存儲。
jdk 7: 元素a放在數組中,指向原來的元素
jdk 8: 原來的元素在數組中,指向元素a
總結:七上八下
總結
以上是生活随笔為你收集整理的移除集合效率高还是add高_List、set集合接口分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 中信白条联名卡能刷超市饭店吗
- 下一篇: 蓝图中实现人物移动1