數組集合應用java
// ArraysList 增刪慢 查詢快 // 根據源碼 無參構造方法建立出來的是長度爲0的數組{} List<Integer> list = new ArrayList<>(); // 此時add方法進行源碼擴容 list.add(100); System.out.println(list.get(0));
public boolean add(E e) { // 不須要關注 modCount++; // e對象 elementData集合數組元素 size當前數組長度 add(e, elementData, size); // 無論成功失敗 均返回true return true; } private void add(E e, Object[] elementData, int s) { // 知足條件 進入擴容算法 否則就進行正常賦值操做 if (s == elementData.length) elementData = grow(); elementData[s] = e; size = s + 1; } private Object[] grow() { // 至少須要加一個長度 return grow(size + 1); } private Object[] grow(int minCapacity) { return elementData = Arrays.copyOf(elementData, newCapacity(minCapacity)); } private int newCapacity(int minCapacity) { // overflow-conscious code int oldCapacity = elementData.length; // 新長度加上舊長度的0.5倍 int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity <= 0) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) // DEFAULT_CAPACITY 默認長度10 return Math.max(DEFAULT_CAPACITY, minCapacity); // 超出最大二進制,符號會改變,會變爲負數 if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return minCapacity; } // MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8 return (newCapacity - MAX_ARRAY_SIZE <= 0) ? newCapacity : hugeCapacity(minCapacity); } private static int hugeCapacity(int minCapacity) { if (minCapacity < 0) // overflow throw new OutOfMemoryError(); return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE; }
// LinkedList: 使用雙向鏈表結構,增刪快,查找慢 // (這種結構和ArrayList的數組結構正好是互補狀態) LinkedList<Integer> ll = new LinkedList<>(); // 模擬棧結構 // 壓棧 ll.push(100); ll.push(200); // 彈棧 Integer i = ll.pop(); // 200 System.out.println(i); // 1 System.out.println(ll.size()); // 下面註釋參考 不建議使用 // 添加集合中第一個元素 // ll.addFirst(100); // ll.addFirst(200); // 移除集合中第一個元素 // Integer removeData = ll.removeFirst(); // 200 // System.out.println(removeData); // 1 // System.out.println(ll.size());
用法和ArrayList基本一致,是線程安全的。面試
// 10 初始化長度 20 擴容增量 此處是相較於ArrayList不一樣之處 List<Integer> v = new Vector<>(10, 20); v.add(100); v.add(200);
// Iterator 迭代器 做用遍歷集合 // Iterator迭代Collection下List和Set ListIterator迭代List下面的集合 List<Integer> list = new ArrayList<>(); list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); Iterator<Integer> iterator = list.iterator(); iterator.next(); // 必需要有值才能移除即前面調用next()方法,固然沒值也會報錯 iterator.remove();; // 4 System.out.println(list.size()); // 判斷迭代器下個是否有值 while(iterator.hasNext()) { // 迭代器往下走,並取值 Integer i = iterator.next(); // 輸出 2 3 4 5 System.out.println(i); } // 用法和iterator差很少 ListIterator<Integer> listIterator = list.listIterator(); // 獲取向上走的值 listIterator.hasPrevious(); // 添加 listIterator.add(10); // 設置 listIterator.next(); listIterator.set(200); listIterator.previous(); // 5 System.out.println(list.size()); while(listIterator.hasNext()) { // 輸出 200 3 4 5 System.out.println(listIterator.next()); }
Set集合是沒有重複的元素,包括null只會存在一個算法
// HashSet是散列存放的數據結構(哈希表) // 本質是 map = new HashMap<>() // 因爲已經存在雙值存儲的哈希表 因此這邊重複利用了造成如今的單值存儲的哈希表 Set<String> set = new HashSet<>(); // map.put(e, PRESENT) set.add("人有悲歡離合"); set.add("月有陰晴圓缺"); set.add("希望人長久"); set.add("希望人長久"); set.add("千里共嬋娟"); set.add("千里共嬋娟"); Iterator<String> iterator = set.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); }
public static void main(String[] args) { // TreeSet 使用二叉樹進行存儲的 有序(天然順序) Set<Person> set = new TreeSet<>(); Person p1 = new Person("張三", 13); Person p2 = new Person("李四", 14); Person p3 = new Person("麻五", 14); set.add(p1); set.add(p2); set.add(p3); // 遍歷前需制定本身的排序規則, 不然可能報錯 // Person{name='張三', age=13} // Person{name='李四', age=14} // 比較規則相同的值,不被儲存 for (Person p : set) { System.out.println(p); } // set.add("C"); // set.add("B"); // set.add("A"); // set.add("D"); // A B C D // Iterator<String> iterator = set.iterator(); // while(iterator.hasNext()) { // System.out.println(iterator.next()); // } } static class Person implements Comparable<Person> { private String name; private int age; @Override public int compareTo(Person o) { // this與0比較 // 返回this小/0/大 if (this.age > o.age) { return 1; } else if (this.age == o.age) { return 0; } return -1; } public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
Map(Mapping 映射)集合存儲的是 鍵值對 數據,Map的鍵不可重複。
影響HashMap的實例化性能的是初始容量和負載因子。
HashMap/Hashtable/ConcurrentHashMap TreeMap/LinkedHashMap使用方法基本一致。數組
HashMap是線程不安全,效率高。HashTable線程安全, 效率低。
ConcurrentHashMap採用分段鎖機制,保證線程安全,效率較高。安全
TreeMap是有序的排。
LinkedHashMap存儲有序。數據結構
Map<String, String> map = new HashMap<>(); // 存值 map.put("k1", "v1"); // 取值 v1 System.out.println(map.get("k1")); map.put("k2", "v2"); // 遍歷 Set<String> set = map.keySet(); for (String key : set) { // k1->v1 // k2->v2 System.out.println(key + "->" + map.get(key)); } // 轉爲Collection集合 Collection<String> c = map.values(); for (String s : c) { System.out.println(s); }
// 構造方法 public HashMap() { // 默認加載因子0.75f this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted } public V put(K key, V value) { // 先計算鍵的hash值,而後調用putVal return putVal(hash(key), key, value, false, true); } final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { // n是桶(數組)的長度 Node<K,V>[] tab; Node<K,V> p; int n, i; // table是默認的16個長度的數組賦值給tab if ((tab = table) == null || (n = tab.length) == 0) // resize擴容算法 n擴容以後的長度 n = (tab = resize()).length; // (n - 1) & hash 是取餘後的長度 數組下標沒有值直接賦值 if ((p = tab[i = (n - 1) & hash]) == null) tab[i] = newNode(hash, key, value, null); else { Node<K,V> e; K k; // key存在新值覆蓋老值 if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p; // 判斷是樹節點 按紅黑樹套路進行存儲 else if (p instanceof TreeNode) e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value); // 鏈表套路進行賦值 else { for (int binCount = 0; ; ++binCount) { // 非重複值操做 if ((e = p.next) == null) { p.next = newNode(hash, key, value, null); // 這邊是二叉樹操做 if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st treeifyBin(tab, hash); break; } // 重複值操做 if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; } } // 前面e被賦值,進入此方法 if (e != null) { // existing mapping for key V oldValue = e.value; if (!onlyIfAbsent || oldValue == null) e.value = value; afterNodeAccess(e); return oldValue; } } // 增長修改次數 ++modCount; // 判斷是否到了臨界值 if (++size > threshold) // 擴容 resize(); afterNodeInsertion(evict); return null; }
在文章的最後做者爲你們整理了不少資料!包括java核心知識點+全套架構師學習資料和視頻+一線大廠面試寶典+面試簡歷模板+阿里美團網易騰訊小米愛奇藝快手嗶哩嗶哩面試題+Spring源碼合集+Java架構實戰電子書等等!
歡迎關注公衆號:前程有光,領取!架構