1. 程式人生 > >Java集合之Collection與之子類回顧

Java集合之Collection與之子類回顧

asn void 排序 dha 避免 bst 自然 我們 tip

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與之子類回顧