黑馬程序員--Java基礎學習筆記【集合-List、泛型】

 

 ------Java培訓、Android培訓、iOS培訓、.Net培訓、期待與您交流! -------   

 

集合框架 Collection  java.util(interface)

集合 只能存儲引用類型,存儲對象,不存儲基本類型,長度可變

數組 存儲基本類型,存儲對象,長度固定

 

    集合中存儲的都是引用類型的元素,那麼引用類型變量實際上存儲的是對象的“地址”,所以實際上集合只存儲了元素對象在堆中的地址,而並不是將對象本身存入了集合中。

 

Collection 接口

是層次結構中的根接口,定義了集合相關的操作方法。

其有兩個子接口:List(可重複集)和Set(不可重複集)

元素是否重複,取決於元素的equals() 比較的結果

 

成員方法:

boolean add(E e) // 添加元素

boolean remove(E e) // 移除第一次出現的指定元素

void clear() // 清空集合

boolean contains(Object o) // 判斷是否包含指定對象

boolean isEmpty() // 判斷集合是否爲空

int size() // 返回集合的大小(容量),即集合中存儲元素的個數

boolean addAll(Collection c) // 添加指定集合中的所有元素

boolean removeAll(Collection c) // 移除指定集合中包含的所有元素

boolean containsAll(Collection c) // 判斷是否包含指定集合的所有元素

boolean retainAll(Collection c) // 保留與指定集合中相同的元素(獲取交集)

Object[] toArray() // 集合 --> 數組,可以實現集合的遍歷

Iterator<E> iterator() // 獲取迭代器,集合專用的遍歷方式

*  迭代器迭代結合,泛型跟隨集合

Iterator 迭代器

    集合專用遍歷方式,做集合中元素的獲取

    集合頂層接口Collection中,定義了一個抽象方法Iterator<E> iterator(),返回值是接口類型,返回的是該接口的實現類對象。

    迭代器接口的實現類是集合容器的內部類,Collection下面所有的實現類,都會重寫該方法。比如 ArrayList 實現 List 接口,而 List 繼承自Collection。

    迭代器類的成員方法:

    boolean hasNext() // 判斷集合中是否還有下一個元素

    <E> next() // 獲取迭代的下一個元素

    void remove() // 移除本次迭代後迭代器返回的最後一個元素

    迭代器的刪除方法是在原集合中刪除元素

  • ConcurrentModificationException

在使用迭代器遍歷集合時,不能通過集合的remove() 方法刪除集合元素,否則會拋出併發更改異常,可以通過迭代器自身提供的remove() 方法刪除通過next() 迭代出的元素。

在調用remove() 方法前必須通過迭代器的next() 方法迭代過元素,那麼刪除的就是這個元素。並且不能再次調用remove() 方法,除非再次調用next() 後方可再次調用。

 

  • 使用迭代器接口的兩種方式,一般使用 while 循環

Iterator iterator = collection.iterator();

// 調用迭代器接口方法判斷集合中有沒有下一個元素

while (iterator.hasNext()) {

    // 調用迭代器接口方法獲取出集合中的元素

    Object object = iterator.next();

    System.out.println(object);

}

for (Iteratoriterator = collection.iterator(); iterator.hasNext();){

    Object object = iterator.next();

    System.out.println(object);

}

 

增強型for循環

since JDK1.5,只用於遍歷集合或數組,也稱新循環

格式:

    for(元素類型 變量名 : 集合或數組) {

        循環體

    }

好處:減少代碼量,方便做遍歷;弊端:不能改動數組或集合中的元素

增強for循環並非新的語法,而是在編譯過程中,編譯器會將新循環轉換爲迭代器模式。所以新循環本質上是迭代器。

 

遍歷集合的 3 種方式:迭代器,增強 for 循環,普通for 循環(size() + get())

 

List 接口 繼承 Collection 接口

特點:有序集合,存取有序,有索引,允許重複

 

成員方法

void add(int index, E element) // 向指定索引處添加元素

E remove(int index) // 移除指定索引處的元素並返回該元素

E get(int index) // 獲取指定索引上的元素

E set(int index, E element) // 替換指定索引上的元素並返回之前的元素

ListIterator<E> listIterator() // 獲取迭代器

int lastIndexOf(Object o) // 返回指定元素出現的最後一個位置的索引

List<E> subList(int fromIndex, inttoIndex) // 獲取子List

--------------------------------------------------------------------

importjava.util.ArrayList;

importjava.util.List;

 

/*

 * 證明 subList 獲取的 List 與原 List 佔用相同的存儲空間,對子 List 的操作會影響原 List

 */

public classSubListDemo {

    public static void main(String[] args) {

       List<Integer> list = newArrayList<>();

       for (int i = 0; i < 10; i++) {

           list.add(i);

       }

       System.out.println("list " +list);

       // list [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

 

       List<Integer> subList =list.subList(3, 8);

       System.out.println("subList " +subList);

       // sublist [3, 4, 5, 6, 7]

 

       // subList 獲得的 List 和原 List 佔有相同的數據空間

       for (int i = 0; i < subList.size();i++) {

           subList.set(i, subList.get(i) * 10);

       }

       System.out.println("changedsubList" + subList);

       // changedsublist [30, 40, 50, 60, 70]

       System.out.println("unchangedlist" + list);

       // unchangedlist [0, 1, 2, 30, 40, 50,60, 70, 8, 9]

 

       list.subList(3, 8).clear(); // 可以用於刪除連續元素

       System.out.println(list);

       // [0, 1, 2, 8, 9]

    }

}

 

ListIterator 列表迭代器

    允許按任一方向遍歷列表,迭代期間可以修改列表

    void add(E e)

    booleanhasNext() // 正向遍歷

boolean hasPrevious() // 逆向遍歷

E next() // 返回列表中的下一個元素

int nextIndex() // 返回返回下一個索引

E previous() // 返回列表中的前一個元素

int previousIndex() // 返回前一個索引

void remove() // 移除本次迭代後迭代器返回的最後一個元素

void set(E e) // 替換此次迭代後迭代器返回的最後一個元素

 

  • 對 List 集合進行正向遍歷和逆向遍歷

List list= newArrayList<>();

       list.add("www");

       list.add("itcast.");

    list.add("cn");

       // 調用集合方法,獲取ListIterator接口的實現類對象

       ListIteratoriterator=list.listIterator();

      

       while (iterator.hasNext()) {

           Objectobject= (Object) iterator.next();

           if ("www".equals(object)) {

              // 調用迭代器的方法

              // 添加元素到迭代到元素的下一個位置

//            iterator.add("0807Java");// 添加和修改不能在同一次迭代中

              // 修改迭代到的元素

              iterator.set("www.");

           }

       }

       //迭代器指針到了最後,不能再次獲取,出現沒有元素被取出異常

      

       // 逆向遍歷逆向遍歷之前要先做一次正向遍歷

       while (iterator.hasPrevious()) {

           Objectobject= (Object) iterator.previous();

           System.out.print(object + " "); // cn itcast. www.

       }

 

  • 泛型機制 Generic since JDK5

泛型在集合中的應用

泛型的本質是參數化類型。在類、接口和方法的定義過程中,所操作的數據類型被傳入的參數指定,強制集合必須存儲指定的數據類型,保證程序的安全性。

Java泛型機制廣泛的應用在集合框架中,所有的集合類型都帶有泛型參數,這樣在創建集合時可以指定放入集合中元素的類型。Java編譯器可以據此進行類型檢查,這樣可以減少代碼在運行時出現錯誤的可能性。

集合類<存儲的數據類型> 變量名 = new 集合類<存儲的數據類型>();

好處:減少代碼量,避免類型強制轉換,安全問題由運行時期提前到了編譯時期。

Java中的泛型是僞泛型,只在編譯時期有效,編譯後的class文件中沒有泛型,編譯手段。

ArrayList類的定義中,<E> 中的 E 爲泛型參數(理解爲變量名,相當於定義了一個變量,負責接收數據類型),在創建對象時可以將類型作爲參數傳遞,此時,類定義所有的 E 將被替換成傳入的參數。

*注意:集合存儲八種基本類型,泛型必須寫包裝類;迭代器迭代結合,泛型跟隨集合

 

泛型類、泛型方法

 

package cn.itcast;

 

/*

 * 自定義泛型類

 *  自己寫的類上,加上泛型<變量>

 *

 * 定義成員變量,也是泛型

 *

 * E 變量,等待建立此類對象的時候,由調用者指定他的數據類型

 */

class GenericClass<E> {

    private E e;

 

    /*

     * 泛型方法

     *  方法參數上,使用了一個和類上一樣的泛型

     *  創建類的對象的時候,直接指定數據類型

     * 

     *  方法上泛型需要單獨的定義,定義在方法的聲明上

     *  創建類的對象同時,不能指定方法上泛型,調用者調用方法時直接指定

     * 

     * 靜態方法參數上的泛型,不能和類上的泛型一樣

     * 原因:靜態不能直接調用非靜態

     */

    publicvoid show(E e) {

       System.out.println(e);

    }

 

    public <W> void function(W w){

       System.out.println(w);

    }

   

    publicstatic <C> void method(C c){

       System.out.println(c);

    }

   

    public E getE() {

       returne;

    }

 

    publicvoid setE(E e) {

       this.e = e;

    }

 

}

 

publicclassGenericDefine {

 

    publicstaticvoid main(String[] args) {

       GenericClass<Integer>genericClass= newGenericClass<Integer>();

       genericClass.setE(123);

       Integerinteger= genericClass.getE();

       System.out.println(integer);

 

       GenericClass<String>genericClass2= newGenericClass<String>();

       genericClass2.setE("abc");

       Stringstring= genericClass2.getE();

       System.out.println(string + 1);

 

       System.out.println("--------------");

       genericClass2.show("傳智播客");

    }

 

}

 

泛型接口

 

package cn.itcast;

 

/*

 * 泛型接口

 *  接口上定義泛型,接口中方法全抽象,實現類

 *  在使用上兩種使用方式:

 *     實現類實現接口,不理會泛型

 *     實現類實現接口,同時也實現接口上的泛型

 */

interface Inter<T> {

    publicabstractvoid show(T t);

}

 

// 定義接口的實現類,實現接口,不理會接口上的泛型

// 泛型的指定,實現類沒有做,讓調用者來指定數據類型

class InterImpl<T> implements Inter<T> {

    @Override

    publicvoid show(T t) {

       System.out.println(t);

    }

}

 

// 定義接口的實現類,實現接口的同時,也實現泛型 -- 不靈活

class InterImpl2 implements Inter<String>{

    @Override

    publicvoid show(String t) {

       System.out.println(t);

    }

}

 

publicclassGenericInterfaceDemo {

 

    publicstaticvoid main(String[] args) {

       Inter<Integer>in = newInterImpl<Integer>();

       in.show(123);

      

       Inter<String>in2= newInterImpl<String>();

       in2.show("itcast");

    }

 

}

 

泛型的限定:泛型通配符 <?>

? extends E (向下限定,E及其子類)    ? super E (向上限定,E及其父類)

 

  • 線性表

    List接口是Collection的子接口,用於定義線性表數據結構,可以將List理解爲存放對象的數組,只不過其元素個數可以動態的增加或減少。

    List接口的兩個常用實現類爲 ArrayList LinkedList,分別用動態數組和鏈表的方式實現了List接口。

 

    List 三個子類的特點

共同特點:有序,索引,重複。

    ArrayList LinkedList在性能上有一定的差別。

    ArrayList 更適合於隨機訪問,而LinkedList 更適合於插入和刪除。

    ArrayList 底層數據結構是可變數組,元素查詢速度快,增刪慢

       線程不安全,不同步,運行速度快

       默認容量 10,增長率50%

    LinkedList 底層數據結構是雙向鏈表,元素查詢速度慢,增刪快

       線程不安全,不同步,運行速度快

       存儲和迭代器代碼,和 ArrayList 完全一樣

    Vector 底層數據結構是可變數組,元素查詢速度快,增刪慢

       線程安全,同步,運行速度慢

       默認容量 10,增長率 100%

 

Vector 特有方法:

    void addElement(E obj) // 將指定的組件添加到向量的末尾,容量+1

    E elementAt(int index) // 返回指定索引處的組件

    Enumeration elements() // 返回此向量的組件的枚舉

LinkedList 特有方法:

    void addFirst(E e)       voidaddLast(E e);

    E getFirst()         EgetLast()

    E removeFirst()      EremoveLast()

 

  • 去除集合中存儲的重複元素

 

package cn.itcast;

 

importjava.util.ArrayList;

importjava.util.Iterator;

 

/*

 * 去除集合中字符串的重複值 -- 去除數組中重複元素

 * 去除集合中自定義對象的重複值(需要重寫自定義對象的equals()方法

 * ArrayList集合實現,List允許重複

 * String 類重寫了equals() 方法,建立了自己的比較方式)

 * 如果原集合中元素沒有出現在新集合中,將該元素存儲到新集合中

 * 遍歷完畢,新集合保存的就是去掉重複後的元素

 * 將原集合的引用指向新集合

 */

public classArrayListTest {

 

    public static void main(String[] args) {

       ArrayList<String> list = new ArrayList<String>();

       list.add("www");

       list.add(".itcast");

       list.add(".cn");

       list.add("www");

       list.add(".itheima");

       list.add(".com");

 

       list = removeSame(list);

       System.out.println(list); // [www, .itcast, .cn, .itheima,.com]

 

    }

 

    // 返回的是去重複之後的新集合

    public static ArrayList<String>removeSame(ArrayList<String> arrayList) {

       // 創建新集合,保存去重複之後的元素

       ArrayList<String> newList = newArrayList<String>();

      

       // 迭代原集合

       Iterator<String> iterator = arrayList.iterator();

       while (iterator.hasNext()) {

           // 接收迭代元素的結果

           String string = iterator.next();

           // 判斷新集合中是否包含該元素,沒有則添加進去

           if (!newList.contains(string)) {

              newList.add(string);

           }

       }

       return newList;

    }

}

 

  • LinkedList 模擬棧數據結構的集合

 

package cn.itcast;

 

import java.util.LinkedList;

 

/*

 * LinkedList集合,模擬數據結構

 *

 * LinkedList集合中的功能封裝起來,調用者不直接面對集合,只能從外部調用

 * 表現爲先添加的元素後被取出,存儲和取出的順序是相反的

 */

publicclassLinkedListTest {

 

    publicstaticvoid main(String[] args) {

       LinkedListToollist= newLinkedListTool();

       list.add(0);

       list.add(1);

       list.add(2);

       list.add(3);

 

       // 當列表不爲空時,刪除元素並返回

       while (!list.isEmpty()) {

           System.out.println(list.remove());

       }

    }

 

}

 

// 自定義功能,封裝LinkedList類功能

class LinkedListTool {

    // 定義成員變量

    privateLinkedList<Object> list;

 

    // 構造方法用於新建對象

    public LinkedListTool() {

       list = newLinkedList<Object>();

    }

 

    // 添加元素到列表結尾

    publicvoid add(Object object) {

       list.add(object);

    }

 

    // 判斷列表是否爲空

    publicboolean isEmpty() {

       returnlist.isEmpty();

    }

 

    // 從列表結尾刪除元素並返回

    public Object remove() {

       returnlist.removeLast();

    }

 

}

 

List 集合 < == > 數組

List 轉換爲數組集合轉成數組,帶有泛型

    Object[] toArray()

    <T>T[] toArray(T[] a)

 

       List<String>strings = new ArrayList<>();

       strings.add("www");

       strings.add(".itcast");

       strings.add("cn");

       String[] str = strings.toArray(newString[strings.size()]);

       // 傳入一個指定類型的數組,該數組的元素類型應與集合的元素類型一致。

       // 返回值則是轉換後的數組,該數組會保存集合中所有的元素

       for (inti = 0; i< str.length; i++){

           System.out.print(str[i] + " ");

       }

 

數組轉換爲 List

    Arrays 類中提供了一個靜態方法 asList,使用該方法我們可以將一個數組轉換爲對應的 List 集合。其方法定義爲: static <T> List<T> asList<T… a>

    注意:返回的 List的集合元素類型由傳入的數組的元素類型決定;返回的集合不能對其增刪元素,否則會拋出異常,並且對集合的元素進行修改會影響數組對應的元素。

 

        String[] strArr = { "www", ".itcast", ".cn" };

        List<String>list =Arrays.asList(strArr); // fixed-size list

       System.out.println(list); // [www, .itcast, .cn]

       // 當前集合 list 的實際類型爲 java.util.Array$ArrayList

       //而不是 List 接口的實現類 java.util.ArrayList,所以不支持對其添加或刪除元素

 

       // list.add("IT"); // 會拋出 UnsupportedOperationException

      

       System.out.println(list.getClass().getName());

      

       list.set(0, "3w"); // 可以修改元素

       // 對集合元素的修改會影響原數組

       System.out.print("String[] ");

       for (String string : strArr) {

           System.out.print(string + " ");

       }

       System.out.println();

      

       // 如果想要添加元素,可以用如下方式:

       List<String>list2= newArrayList<>();

       list2.addAll(Arrays.asList(strArr));

       System.out.println(list2); // [3w, .itcast, .cn]

       list2.add("0807JavaSE");

       System.out.println(list2); // [3w, .itcast, .cn, 0807JavaSE]

 

可變參數 since JDK5

    如果定義方法的時候,參數類型明確但個數不明確,可使用可變參數

格式:修飾符返回值類型方法名(數據類型...變量名) {}

可變參數方法傳遞,傳遞實際參數,數量沒有限制

注意:一個方法中只能寫 1 個可變參數,如果有多個參數可變參數只能放在最後

 

package cn.itcast.arguments;

 

publicclassVarArgumentsDemo {

 

    publicstaticvoid main(String[] args) {

       intsum = getSum(0, 1,2, 3, 4, 5);

       System.out.println(sum);

    }

 

    publicstaticint getSum(int...is){

       intsum = 0;

       // 傳遞參數的個數,就是數組的長度

       // 如果不傳遞任何參數,可變參數的數組的長度就是 0

//     for(int i = 0; i < is.length; i++) {

//         sum+= is[i];

//     }

       for (inti : is) {

           sum += i;

       }

       returnsum;

    }

}

 

l  獲取101-20之間的隨機數,要求不能重複

 

package cn.itcast.test;

 

importjava.util.ArrayList;

import java.util.List;

importjava.util.Random;

 

/*

 * 獲取101-20之間的隨機數,要求不能重複

 */

public class ListTest {

 

    public static void main(String[] args) {

       Random r = new Random();

       List<Integer> list = new ArrayList<Integer>();

      

       while (true) {

           // 獲取隨機數

           int num = r.nextInt(20) + 1;

           // 判斷隨機數如果不在集合中,就存儲到集合

           if (!list.contains(num)) {

              list.add(num);

              // 判斷集合容量爲10就退出循環

              if (list.size() == 10) {

                  break;

              }

           }

       }

      

       for (Integer integer : list) {

           System.out.println(integer);

       }

    }

}

 

l  鍵盤錄入多個數據,以0結束,要求在控制檯輸出這多個數據中的最大值

package cn.itcast.test;

 

importjava.util.ArrayList;

import java.util.List;

importjava.util.Scanner;

 

/*

 * 鍵盤錄入多個數據,以0結束

 * 在控制檯輸出最大值:

 *  利用數組,將集合轉成數組

 *     1.升序排序,獲取最後一個元素

 *     2.獲取數組中的最大值

 *

 */

public classListScannerTest {

 

    public static void main(String[] args) {

       Scanner sc = new Scanner(System.in);

       List<Integer> list = new ArrayList<Integer>();

       while (true) {

           int num = sc.nextInt();

           if (num == 0) {

              break;

           }

           // 數據存儲到集合中

           list.add(num);

       }

       sc.close();

//     System.out.println(list);

      

       // 將集合轉成數組

       Integer[] integers = list.toArray(new Integer[list.size()]);

       // 選擇排序

       for (int i = 0; i < integers.length; i++) {

           for (int j = i + 1; j < integers.length; j++) {

              if (integers[i] > integers[j]) {

                  int temp = integers[i];

                  integers[i] = integers[j];

                  integers[j] = temp;

              }

           }

       }

       // 輸出數組中的最後一個索引

       System.out.println(integers[integers.length - 1]);

      

       // 求數組最值思想

//     int max = list.get(0);

//     for (Integer integer : integers) {

//         if (integer > max)

//            max = integer;

//     }

//     System.out.println(max);

      

    }

 

}

 

List 排序

Collections.sort() 方法實現排序

Collections 是集合的工具類,提供很多便於操作集合的方法。

void sort(List<T>list) // 該方法的作用是對給定的集合元素進行自然排序


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章