數組建立與初始化java
格式:className[] cn = new className[]{};
能夠省略{},但必須在[]裏代表長度(變量必須提供維度表達式或數組初始值設定項),能夠不用new,直接使用{}初始化,數組在建立時指定長度後只能一個一個的填充數組,不能使用{ }填充數組數組
優勢:訪問效率高安全
缺點:數組長度固定數據結構
數組在方法內能夠不初始化(自動初始化,例:int-->0)this
在建立數組時其類型與數組長度固定(編譯時檢查,這是與其餘容器類的不一樣之處)線程
可使用length查看數組的長度(這是數組惟一能夠調用的)code
數組能夠持有基本類型,容器的泛型不能夠,可是有自動包裝機制對象
數組引用指向堆中真實對象,對象中保存其餘對象的引用blog
可變參數列表排序
編譯器會把可變參數列表當作數組,因此能夠進行foreach,能夠對能夠參數列表傳入數組
Arrays
sort(T[] t); //必須是基本類型或者實現Comparable接口的類型,不然出現異常,基本類型使用快排,引用類型使用穩定歸併 asList(T... a); //接收的可變參數,返回的是List接口類型的數據,不能強轉爲List的其餘實現類 fill(); //用指定數據填充整個數組 binarySearch(); //對已排序的數組查找,使用二分查找 copyof(); //拷貝數組,底層使用的是 System.arraycopy(): 淺複製: 複製對象的引用, 比for循環快不少, 由於for循環是對對象自己的拷貝(用於ArrayList數組的擴容), System.arraycopy()方法是native方法, 沒法看到源碼(應該是C/C++實現的)
建立集合時不跟泛型
編譯器檢查不出元素的類型,取元素時須要強轉,若強轉類型不對則報異常
使用Arrays.asList()生成的List
進行add()或delet()操做運行時會出異常,由於Arrays.asList()的底層爲數組,長度不可改變
分類
Collection
List
ArrayList LinkedList
queue
map
特色
區別
ArrayList: 底層數據機構爲數組, 隨機訪問較快, 增刪操做較慢
LinkedList: 底層數據結構爲鏈表,增刪較快,隨機訪問較慢
ArrayList
隨機訪問元素較快, 不擅長操做插入刪除
add(int index, E element) 將指定的元素插入此列表中的指定位置。
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; }
初始化容量: 建立ArrayList時構造器初始化一個空數組, 當使用add()時, 把數組容量變爲靜態字段 DEFAULT_CAPACITY=10
private static int calculateCapacity(Object[] elementData, int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { return Math.max(DEFAULT_CAPACITY, minCapacity); } return minCapacity; } private void ensureCapacityInternal(int minCapacity) { ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)); } private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); }
1.5倍擴容 : 使用System.arraycopy進行擴容,每次擴容oldCapacity >> 1,位運算右移變爲oldCapacity的一半,因此擴容爲原來的1.5倍
private void grow(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // minCapacity is usually close to size, so this is a win: elementData = Arrays.copyOf(elementData, newCapacity); }
remove() 移除指定數據數-----底層使用System.arraycopy進行數據挪移
線程不安全:
List list = Collections.synchronizedList(new ArrayList(...));//進行同步
容量大小和元素個數的關係??-----ArrayList裏面有個int size代表當前的元素個數, 每次add元素就會進行size++, 當元素個數等於容量時就會擴容
default關鍵字(虛擬擴展方法), 能夠在接口裏對方法實現, List接口實現了sort()方法
Iterator
ArrayList迭代器以下
private class Itr implements Iterator<E> { int cursor; // index of next element to return int lastRet = -1; // index of last element returned; -1 if no such int expectedModCount = modCount; public boolean hasNext() { return cursor != size; } @SuppressWarnings("unchecked") public E next() { checkForComodification(); int i = cursor; if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i + 1; return (E) elementData[lastRet = i]; }
不容許在foreach裏刪除或添加(來自< <阿里巴巴java開發手冊> > )
List<String> a = new ArrayList<>(); a.add("1"); a.add("2"); for (String string : a) { if("2".equals(string)) { a.remove(string); } System.out.printlb(String); }
異常: java.util.ConcurrentModificationException
分析:
remove("1")
第一輪: cussor=0,size=2,取出"1"後cussor+1,刪除"1"後size=1
第二輪: cussor=1,size=1, 經hasNext()判斷結束循環,元素"2"沒有獲得遍歷
remove("2")
第一輪: cussor=0,size=2,取出"1"後cussor+1,size不變
第二輪: cussor=1,size=2, 取出"2"後cussor+1,刪除"2"後size=1
第三輪: cussor=2,size=1,hasNext()爲true不能結束循環,此時進入next()方法內的checkForComodification()方法就拋出異常
解決:
List<String> list = new ArrayList<>(); list.add("1"); list.add("2"); Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String item = iterator.next(); if (item.equals"2") { iterator.remove(); } }
LinkedList中的鏈表節點:
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; } }
方法:
普通增刪查: LinkedList的相比於ArrayList通常多First和Last方法
棧: 後進先出
push(): 往棧底(列表最後)壓入數據 pop(); 取出棧頂數據(列表開始) peek() 獲取列表第一個元素,peekFirst peekLast poll() 獲取第一個元素並移除改元素 pollFIrst pollLast