常用集合類:
1、iterator便利:
所有的集合父類collection實現了Iterable。該集合裡有三個方法 其中一個重要的方法 iterator()方法。在所有集合的實現類重寫了這個方法。
ArrayList list= new ArrayList(); list.add(1); list.add(2); list.add(3); list.add(4); Integer integer = new Integer(2); list.remove(integer); Iterator iterator= list.iterator(); // ListIterator iterator = list.listIterator(); while(iterator.hasNext()){ Object o = iterator.next(); if(o.equals(1)){ iterator.remove(); //此處遍歷器已經不支援刪除操作 也不zhichilist.remove(o) 所以用list。listIterator() } System.out.println(o); } }
但是通過便利刪除list.remove()會資料上移,造成遊標的混亂判斷。所以會報異常,那麼可以用通過iterator 的remove方法實現,通過原始碼可以看到此處丟擲了一個異常,不支援這個方法。
那麼可以通過arraylIst的listIterator()來進行便利實現。
在使用iterator進行迭代的過程中如果刪除其中的某個元素會報錯,併發操作異常,因此 * 如果遍歷的同時需要修改元素,建議使用listIterator(), * ListIterator迭代器提供了向前和向後兩種遍歷的方式 * 始終是通過cursor和lastret的指標來獲取元素值及向下的遍歷索引* 當使用向前遍歷的時候必須要保證指標在迭代器的結果,否則無法獲取結果值
Iterator iterator = list.iterator(); // ListIterator iterator = list.listIterator(); while(iterator.hasNext()){ Object o = iterator.next(); if(o.equals(1)){ iterator.remove(); } System.out.println(o); } // System.out.println("-------------"); // while (iterator.hasPrevious()){ // System.out.println(iterator.previous()); // } // for(Object i : list){ // System.out.println(i); // }
如上圖:此時向前便利,向後便利。如果指標在最後面獲取不到元素。
2、vector也是list的實現類,他是執行緒安全的。
3、list的實現類主要有arrayList和LinkList兩類。arraylist底層是陣列實現,那麼查詢會快一些。linkList底層是連結串列實現。刪除和插入快一些。修改的查詢話都需要逐個便利元素。
4、以後儘量減少使用增強for迴圈,不變與對資料的操作。
5、摘要
ListIterator的作用解決併發操作異常 ▪ 在迭代時,丌可能通過集合物件的方法(al.add(?))操作集合中的元素, ▪ 會發生併發修改異常。 ▪ 所以,在迭代時只能通過迭代器的方法操作元素,但是Iterator的方法 ▪ 是有限的,只能進行判斷(hasNext),取出(next),刪除(remove)的操作, ▪ 如果想要在迭代的過程中進行向集合中新增,修改元素等就需要使用 ▪ ListIterator介面中的方法
ListIterator li=al.listIterator(); while(li.hasNext()){ Object obj=li.next(); if ("java2".equals(obj)) { li.add("java9994"); li.set("java002"); } }
6、迭代器會維持到方法體結束,消耗記憶體空間。迭代器從建立一開始,一直到方法結束。所以建議用第二種方法。寫在for 迴圈裡作用域是這個迴圈內。
建議用第二中反方法,放到for迴圈裡實現。
二、set set是無序的且不重複的集合。常見的實現有hashSet和TreeSet和LinkHashSet。
通過底層程式碼,我們可以看到hashSet就是hashMap。是通過計算新增資料的hashcode值。在比較equas方法,通過演算法去重,資料雜湊,實現無序且不可重複的集合。好的演算法可以減少資料的雜湊。
TreeSet可以確保資料的一致性,底層是TreeMap 紅黑樹。查詢速度快一些。紅黑樹與平衡樹最大的區別就是減少了自旋所帶來的效能消耗,提升了插入效率。
1、hashSet和TreeSet的區別:
Set介面中的實現類
▪HashSet:採用Hashtable雜湊表儲存結構
–優點:新增速度快,查詢速度快,刪除速度快
–缺點:無序
–LinkedHashSet
▪ 採用雜湊表儲存結構,同時使用連結串列維護次序
▪有序(新增順序)
▪TreeSet
–採用二叉樹(紅黑樹)的儲存結構
–優點:有序(排序後的升序)查詢速度比List快
–缺點:查詢速度沒有HashSet快
不同點:treeSet新增資料的時候,必須要新增同一型別,並且有可以排序的資料比較。
內部比較器:實現compareable介面。
外部比較器的使用:
在當前類中實現 Comparator介面,並重寫了 compare方法。然後把該比較器傳入到集合中。
public class SetDemo implements Comparator<Person> { public static void main(String[] args) { TreeSet treeSet = new TreeSet(new SetDemo()); treeSet.add(new Person("lisi",15)); treeSet.add(new Person("wangwu",13)); treeSet.add(new Person("maliu",12)); treeSet.add(new Person("zhangsan",19)); treeSet.add(new Person("zhangsan",12)); System.out.println(treeSet); } @Override public int compare(Person o1, Person o2) { if(o1.getAge()>o2.getAge()){ return -1; }else if(o1.getAge() < o2.getAge()){ return 1; }else{ return 0; } }
set內容總結:
* 1、set中存放的是無序,唯一的資料 * 2、set不可以通過下標獲取對應位置的元素的值,因為無序的特點 * 3、使用treeset底層的實現是treemap,利用紅黑樹來進行實現 * 4、設定元素的時候,如果是自定義物件,會查詢物件中的equals和hashcode的方法,如果沒有,比較的是地址 * 5、樹中的元素是要預設進行排序操作的,如果是基本資料型別,自動比較,如果是引用型別的話,需要自定義比較器 * 比較器分類: * 內部比較器 * 定義在元素的類中,通過實現comparable介面來進行實現 * 外部比較器 * 定義在當前類中,通過實現comparator介面來實現,但是要將該比較器傳遞到集合中 * 注意:外部比較器可以定義成一個工具類,此時所有需要比較的規則如果一致的話,可以複用,而 * 內部比較器只有在儲存當前物件的時候才可以使用 * 如果兩者同時存在,使用外部比較器 * 當使用比較器的時候,不會呼叫equals方法
當使用比較器的時候,如果比較的值相當,那麼會進行去重操作。
三、泛型
泛型的使用:
泛型的高階應用: * 1、泛型類 * 在定義類的時候在類名的後面新增<E,K,V,A,B>,起到佔位的作用,類中的方法的返回值型別和屬性的型別都可以使用 * 2、泛型介面 * 在定義介面的時候,在介面的名稱後新增<E,K,V,A,B>, * 1、子類在進行實現的時候,可以不填寫泛型的型別,此時在建立具體的子類物件的時候才決定使用什麼型別 * 2、子類在實現泛型介面的時候,只在實現父類的介面的時候指定父類的泛型型別即可,此時,測試方法中的泛型型別必須要跟子類保持一致 * 3、泛型方法 * 在定義方法的時候,指定方法的返回值和引數是自定義的佔位符,可以是類名中的T,也可以是自定義的Q,只不過在使用Q的時候需要使用< * Q>定義在返回值的前面 * 4、泛型的上限(工作中不用) * 如果父類確定了,所有的子類都可以直接使用 * 5、泛型的下限(工作中不用) * 如果子類確定了,子類的所有父類都可以直接傳遞引數使用 *
1、定義泛型類 預設E代表element k是key v是value
public class FanXingClass<A> { private int id; private A a; public int getId() { return id; } public void setId(int id) { this.id = id; } public A getA() { return a; } public void setA(A a) { this.a = a; } public void show(){ System.out.println("id : "+id+" ,A : "+a); } public A get(){ return a; } public void set(A a){ System.out.println("執行set方法:" + a); }
2、定義泛型的介面實現:
package _05_第五章泛型.E202_05_02_資料相加; public class Test { public static void main(String[] args) { Point p1 = new Point(1,1); Point p2 = new Point(3,2); Circle circle = new Circle(p1,2); Circle circle2 = new Circle(p2,3); System.out.printf("兩個 圓 相加結果:\n"); System.out.println(circle2.add(circle)); Complex complex = new Complex(1,1); Complex complex2 = new Complex(2,2); System.out.printf("兩個 複數 相加結果:\n"); complex2.Print(complex2.add(complex)); } } package _05_第五章泛型.E202_05_02_資料相加; public interface Add<T> { public T add(T t); } package _05_第五章泛型.E202_05_02_資料相加; public class Circle implements Add<Circle> { private Point p;//圓心 private float r;//半徑 public Circle(Point p, float r) { this.p = p; this.r = r; } public Circle add(Circle circle2){ circle2.p =this.p.add(circle2.p); circle2.r =this.r + circle2.r ; return circle2; } @Override public String toString() { return String.format("圓心:(%f,%f) 半徑:%f",p.x,p.y,r); } }
3、泛型的方法比較特殊,如果沒有返回值,那麼需要新增哥泛型。
public class FanXingMethod<T> { private T t; public T getT() { return t; } public void setT(T t) { this.t = t; } public <Q> void show(Q q){ System.out.println(q); System.out.println(t); }
三、Map類
1、hashmap跟hashtable的區別:
1、hashmap執行緒不安全,效率比較高,hashtable執行緒安全,效率低
2、hashmap中key和value都可以為空,hashtable不允許為空
map儲存的是k-v鍵值對對映的資料 * 實現子類: * HashMap:資料+連結串列(1.7) 陣列+連結串列+紅黑樹(1.8) * LinkedHashMap:連結串列 * TreeMap:紅黑樹
2、常見的hashMap便利操作
//遍歷操作 Set<String> keys = map.keySet(); for(String key:keys){ System.out.println(key+"="+map.get(key)); } //只能獲取對應的value值,不能根據value來獲取key Collection<Integer> values = map.values(); for (Integer i:values){ System.out.println(i); } //迭代器 Set<String> keys2 = map.keySet(); Iterator<String> iterator = keys2.iterator(); while(iterator.hasNext()){ String key = iterator.next(); System.out.println(key+"="+map.get(key)); } //Map.entry Set<Map.Entry<String, Integer>> entries = map.entrySet(); Iterator<Map.Entry<String, Integer>> iterator1 = entries.iterator(); while (iterator1.hasNext()){ Map.Entry<String, Integer> next = iterator1.next(); System.out.println(next.getKey()+"--"+next.getValue()); }
Map.ENtry格式型別:有key和value和hashCode值 有指標
在java8以後hashMap是什麼時候使用紅黑樹的?在大於8的時候。
hashMap初始化的陣列長度為2的N次冪。這樣便於位移運算擴容。