Java集合之Collection與之子類回顧
Java學習這麽久,打算這幾天回顧下java的基本知識點,首先是集合。
一、常用集合類關系圖
Collection
|___List 有序,可重復
|___ArrayList 底層數據結構是數組,增刪慢,查詢快;線程不安全,效率高
|___LinkedList 底層數據結構是鏈表,增刪快,查詢慢;線程不安全,效率高
|___Vector 底層數據結構是數組,增刪慢,查詢快;線程安全,效率低
|___Set 無序,不可重復
|___HashSet
|___TreeSet
Map
|___HashMap
|___TreeMap
二、集合兩個問題(Why?Feature?)
1、Why?為什麽使用集合?
java是一種面向對象語言,為了方便對對象的操作,所以使用了集合。
2、Feature?集合有什麽特點?即它和數組的不同點。
集合:①存儲不同引用類型對象 ②長度可變
數組:①存儲相同基本類型(包括數據類型和引用類型) ②長度不可變
三、Collection概述
Collection的功能概述:
1:添加功能
boolean add(Object obj):添加一個元素 boolean addAll(Collection c):添加一個集合的元素
2:刪除功能
void clear():移除所有元素boolean remove(Object o):移除一個元素 boolean removeAll(Collection c):移除一個集合的元素(是一個還是所有) 註意:只要有一個元素被移除,就返回True
3:判斷功能
boolean contains(Object o):判斷集合中是否包含指定的元素 boolean containsAll(Collection c):判斷集合中是否包含指定的集合元素(是一個還是所有) 註意:要包含所有的元素,返回True boolean isEmpty():判斷集合是否為空
4:獲取功能
Iterator<E> iterator()(重點) 集合專用叠代器
1 //創建集合 2 3 Collection c= new ArrayList(); 4 5 //集合添加元素 6 7 c.add("Hello"); 8 9 c.add("World"); 10 11 //使用叠代器 12 13 Iterator it =c.iterator(); 14 15 While(it.hasNext ()){ 16 17 String s =(String) it.next(); 18 19 System.out.println(s); 20 21 }
1 //叠代器源碼 2 public interface Inteator { 3 boolean hasNext(); 4 Object next(); 5 } 6 7 public interface Iterable { 8 Iterator iterator(); 9 } 10 11 public interface Collection extends Iterable { 12 Iterator iterator(); 13 } 14 15 public interface List extends Collection { 16 Iterator iterator(); 17 } 18 19 public class ArrayList implements List { 20 public Iterator iterator() { 21 return new Itr(); 22 } 23 24 private class Itr implements Iterator { 25 public boolean hasNext() {} 26 public Object next(){} 27 } 28 }
5:長度功能
int size():元素的個數
面試題:數組有沒有length()方法呢?字符串有沒有length()方法呢?集合有沒有length()方法呢?
數組求長度用length屬性
字符串求長度用length()方法
集合求長度用size()方法
6:交集功能
boolean retainAll(Collection c)
兩個集合都有的元素?思考元素去哪了,返回的boolean又是什麽意思呢?
假設有兩個集合A,B。
A對B做交集,最終的結果保存在A中,B不變。
返回值表示的是A是否發生過改變。
7:把集合轉換為數組
Object[] toArray()
集合轉換成數組例子
1 //創建集合對象 2 3 Collection c = new ArrayList(); 4 5 //添加元素 6 7 c.add("Hello"); 8 9 c.add("World"); 10 11 //集合轉換成數組 12 13 Object[] obj = c.toArray(); 14 15 //遍歷集合 16 17 for(int x =0;x<obj.length;x++){ 18 19 System.out.println(obj[x]); 20 21 }
四、Collection下List特有功能
A:添加功能
void add(int index,Object element): 在指定位置添加元素
B:獲取功能
Object get(int index):獲取指定位置的元素
1 //List的特有遍歷---普通for 遍歷 2 //創建對象 3 List list = new ArrayList(); 4 //添加元素 5 list.add("Hello"); 6 list.add("World"); 7 //普通for遍歷 8 for(int x=0;x<list.size();x++){ 9 String s=(String)list.get(x); 10 System.out.println(s); 11 }
C:列表叠代器
ListIterator listIterator():List集合特有的叠代器
D:刪除功能
Object remove(int index):根據索引刪除元素,返回被刪除的元素
E:修改功能
Object set(int index,Object element):根據索引修改元素,返回被修飾的元素
五、引入泛型
泛型是將類型明確工作推遲到對象創建或者方法調用的時候。
泛型的格式:<數據類型> 註意:此處的數據類型只能是引用類型。int----Integer
泛型的好處:
A.將運行期間的錯誤提前到編譯期間
B.避免強制類型轉換
1 //創建集合對象加入泛型 2 ArrayList<String> list = new ArrayList<String>() 3 list.add("Hello"); 4 list.add("World"); 5 //使用叠代器 6 Iterator<String> it = list.iterator(); 7 While(it.hasNext()){ 8 //使用泛型後不用進行類型強制轉換 9 String s = list.next(); 10 System.out.println(s); 11 }
JDK7 新特性:泛型推斷。
ArrayList<Student> array = new ArrayList<>();
將泛型定義到類上
public class ObjectTool<T> { private T obj; public T getObj() { return obj; } public void setObj(T obj) { this.obj = obj; } }
將泛型定義到方法上
public class ObjectTool { public <T> void show(T t) { System.out.println(t); } }
將泛型定義到接口上
public interface Inter<T> { public abstract void show(T t); }
高級通配符
<?>:任意類型,沒有指定就是Object類型 <? extends E>:向下限定,E及其子類 <? super E>:向上限定,E及其父類
class Animal{} class Dog extends Animal{} class Cat extends Animal{} Collection<?> c = new ArrayList<Animal>(); Collection<?> c = new ArrayList<Dog>(); Collection<?> c= new ArrayList<Cat>(); Collection<? extends Animal> c =new ArrayList<Animal>(); Collection<? extends Animal> c =new ArrayList<Dog>(); Collection<? extends Animal> c = new ArrayList<Cat>(); Collection<? super Animal> c =new ArrayList<Animal>; Collection<? super Animal> c = new ArrayList<Object>;
六、JDK 5 新特性
增強for遍歷集合
格式:
for(數據類型 變量名:遍歷的集合或數組名){ }
好處:簡化了數組和集合的遍歷方式。
缺點:需要遍歷的集合或數組不能為空。
解決方案:遍歷之前做if判斷。
ArrayList<String> list = null; if(list!=null){ for(String s :list){ System.out.println(s); } }
至此List有三種遍歷方式
//創建集合對象 ArrayList<String> list = new ArrayList<String>(); list.add("Hello"); list.add("World"); //第一種:叠代器遍歷 Iterator<String> it =list.iterator(); While(it.hasNext()){ String s = list.next(); System.out.println(s); } //第二種:普通for遍歷 for(int x=0;x<list.size();x++){ String s = list.get(x); System.out.println(s); } //第三種:增強for遍歷 for(String s :list){ System.out.println(s); }
靜態導入
import static 包名.類名.方法名
可以直接導入到方法
註意事項:①方法必須是靜態的。②導入時有多個同名的靜態方法,使用時必須要加前綴(包名.類名.方法名)
可變參數
如果一個方法的參數不固定,那麽我們可以使用可變參數。
格式:
修飾符 返回值類型 方法名(數據類型... 變量名){ } //註意:這裏的...不是省略號 例如:設計一個求和方法,傳入的參數數量未知 public int sum(int...a){ int sum =0; for(int i :a){ sum+=i; } return sum; }
註意:①這裏的變量實際上是一個數組,所以可以使用增強for遍歷。
②如果一個方法除了可變參數還有別的參數,那麽可變參數一定要放到參數的最後。
數組轉集合
public static <T> List<T> asList(T... a):把數組轉成集合
List<String> list = Arrays.asList("hello","World","Java");
註意:雖然數組可以轉成集合,但是這個集合的長度不可變,固定
七、List下ArrayList、Vector、LinkedList特有功能
//Vector特有功能 //添加功能 public void addElement(Object obj) --------add() //獲取功能 public Object elementAt(int index) -------- get() public Enumeration elements() --------Iterator iterator() boolean hasMoreElements() --------hasNext() Object nextElement() --------next()
//LinkedList的特有功能: //添加功能 public void addFirst(Object e) public void addLast(Object e) //獲取功能 public Object getFirst() public Obejct getLast() //刪除功能 public Object removeFirst() public Object removeLast()
八、collection下set概述
set是一個元素無序且唯一的集合
HashSet:
HashSet為何存儲元素是唯一的呢?
原因:HashSet底層依靠的是hashCode()和equals()方法。
先比較hashCode(),如果相同繼續比較equals(),equals()返回true說明元素重復,返回false則添加進集合
HashSet 的add()源碼:
interface Collection { ... } interface Set extends Collection { ... } class HashSet implements Set { private static final Object PRESENT = new Object(); private transient HashMap<E,Object> map; public HashSet() { map = new HashMap<>(); } public boolean add(E e) { //e=hello,world return map.put(e, PRESENT)==null; } } class HashMap implements Map { public V put(K key, V value) { //key=e=hello,world //看哈希表是否為空,如果空,就開辟空間 if (table == EMPTY_TABLE) { inflateTable(threshold); } //判斷對象是否為null if (key == null) return putForNullKey(value); //和對象的hashCode()方法相關 int hash = hash(key); //在哈希表中查找hash值 int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) { //這次的e其實是第一次的world Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; //走這裏其實是沒有添加元素 } } modCount++; addEntry(hash, key, value, i); //把元素添加 return null; } transient int hashSeed = 0; final int hash(Object k) { //k=key=e=hello, int h = hashSeed; if (0 != h && k instanceof String) { return sun.misc.Hashing.stringHash32((String) k); } h ^= k.hashCode(); //這裏調用的是對象的hashCode()方法 // This function ensures that hashCodes that differ only by // constant multiples at each bit position have a bounded // number of collisions (approximately 8 at default load factor). h ^= (h >>> 20) ^ (h >>> 12); return h ^ (h >>> 7) ^ (h >>> 4); } } hs.add("hello"); hs.add("world"); hs.add("java"); hs.add("world");
LinkedHashSet:
存儲元素有序且唯一。
HashSet保證其存儲元素唯一;Linked保證其存儲元素有序(輸入和輸出元素有序)
TreeSet:
能夠對元素按照某種規律進行排序;
A 自然排序,如果沒有指定,則從小到大排序。
讓元素所屬的類實現自然排序接口 Comparable,重寫接口中compareTo ()方法。
B 比較器排序。
讓集合的構造方法接收一個比較器接口的子類對象 Comparator,此時可以使用匿名內部類方法實現排序。
//實現比較器排序的局部代碼 TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() { @Override public int compare(Student s1, Student s2) { // 姓名長度 int num = s1.getName().length() - s2.getName().length(); // 姓名內容 int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num; // 年齡 int num3 = num2 == 0 ? s1.getAge() - s2.getAge() : num2; return num3; } });
Java集合之Collection與之子類回顧