1. 程式人生 > >Java入門系列-19-泛型集合

Java入門系列-19-泛型集合

集合

如何儲存每天的新聞資訊?每天的新聞總數是不固定的,太少浪費空間,太多空間不足。 如果並不知道程式執行時會需要多少物件,或者需要更復雜方式儲存物件,可以使用Java集合框架。

Java 集合框架提供了一套效能優良、使用方便的介面和類,位於 java.util 包中。

介面 Collection 儲存一組不唯一,無序的物件,它有兩個子介面 List和Set。List 介面儲存一組不唯一,有序(插入順序)的物件。Set 介面儲存一組唯一,無序的物件。

介面 Map 儲存一組鍵值物件,提供 key 到 value 的對映

List 介面的實現類

ArrayList

ArrayList 實現了長度可變的陣列,在記憶體中分配連續的空間。遍歷元素和隨機訪問元素的效率比較高。

下面演示使用及常用方法

//Book類儲存書的資訊
public class Book {

    private String name;//書名
    private float price;//價格
    
    public Book() {
        super();
    }
    
    public Book(String name, float price) {
        super();
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public float getPrice() {
        return price;
    }
    public void setPrice(float price) {
        this.price = price;
    }
}

測試類

import java.util.ArrayList;
import java.util.List;

public class TestArrayList {
    public static void main(String[] args) {
        List books=new ArrayList();//建立集合
        //向集合中新增元素
        books.add(new Book("80天環遊世界",34.6f));
        books.add(new Book("Java核心技術",88));
        books.add(new Book("Java程式設計思想",122));
        //獲取集合的長度
        System.out.println("集合的長度:"+books.size());
        //指定索引移除一個元素
        books.remove(0);
        System.out.println("移除後集合的長度:"+books.size());
        //for迴圈遍歷 ArrayList
        for (int i = 0; i < books.size(); i++) {
            Book book=(Book) books.get(i);
            System.out.println("書名:"+book.getName()+" 價格:"+book.getPrice());
        }
        //foreach 遍歷 ArrayList
        for (Object object : books) {
            Book book=(Book) object;
            System.out.println("書名:"+book.getName()+" 價格:"+book.getPrice());
        }
        //插入元素到指定索引,其餘元素自動後移
        books.add(0, new Book("明朝那些事兒",55));
        //移除指定索引元素
        books.remove(2);
        //清空所有元素
        books.clear();
        System.out.println("清空集合的長度:"+books.size());
    }
}

這裡面的方法在 Java API 文件中都能查到,一定要學會檢視幫助文件。

LinkedList

LinkedList 採用連結串列儲存方法。插入、刪除元素時效率比較高。LinkedList提供了對頭部和尾部元素進行新增和刪除的方法。

下面看一下操作連結串列集合

import java.util.LinkedList;

public class TestLinkedList {
    public static void main(String[] args) {
        
        LinkedList books=new LinkedList();//建立連結串列集合
        //向集合中新增元素
        books.add(new Book("80天環遊世界",34.6f));
        //向集合首部新增元素
        books.addFirst(new Book("Java核心技術",88));
        //向集合尾部新增元素
        books.addLast(new Book("Java程式設計思想",122));
        System.out.println(books.size());
        //獲取第一個
        Book book1=(Book) books.getFirst();
        System.out.println("書的名字:"+book1.getName());
        //獲取最後一個
        Book lastBook=(Book) books.getLast();
        System.out.println("最後一本書的名字:"+lastBook.getName());
        //移除第一個元素
        books.removeFirst();
        System.out.println("集合長度:"+books.size());
        //移除最後一個元素
        books.removeLast();
        System.out.println("集合長度:"+books.size());
    }
}

LinkedList也實現於List介面,所以在ArrayList示例中使用的方法LinkedList都有,LinkedList獨有的方法在上例中,單獨記憶即可。

Map

Map介面專門處理鍵值對映資料的儲存,可以根據鍵實現對值得操作,最常用的實現類是HashMap,Map的鍵不允許重複。

import java.util.HashMap;
import java.util.Map;

public class TestMap {
    public static void main(String[] args) {
        Map map=new HashMap();
        map.put("h", "hello");//向集合中新增鍵和值的對映
        map.put("b1", new Book("Java核心技術",88));
        System.out.println("集合長度:"+map.size());
        map.remove("h");//通過指定的鍵移除鍵和值
        //根據鍵獲取指定的值
        Book book=(Book) map.get("b1");
        System.out.println("書名:"+book.getName());
        //遍歷Map的值的集合
        for (Object temp : map.values()) {
            System.out.println(temp);
        }
        //清空集合
        map.clear();
        System.out.println("集合長度:"+map.size());
    }
}

泛型集合

下面程式碼在使用時有沒有問題:

Book book=(Book) books.get(i);

List和Map新增元素時都是Object型別,在強制型別轉換時容易發生異常。JDK1.5使用泛型改寫了集合框架中的介面和類。

使用泛型時要加上一對“<>”,在尖括號內寫上限定的資料型別。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Test {
    public static void main(String[] args) {
        List<String> names=new ArrayList<String>();
        names.add("張三");//只能新增 String 型別元素
        names.get(0).substring(0);//返回的型別也是指定的型別
        //Map在使用時需要同時指定鍵和值的型別
        Map<String,String> map=new HashMap<String,String>();
        map.put("h", "hello");//鍵和值都只能是指定的型別
    }
}

指定完型別後,元素就是指定的型別的元素,那這樣在存資料和取資料都是指定型別,不需要型別轉換。

使用泛型後,集合的遍歷也更加方便,其中演示了foreach遍歷Map的三種方法。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public class TestEach {
    public static void main(String[] args) {
        //List的遍歷
        List<Book> books=new ArrayList<Book>();
        books.add(new Book("80天環遊世界",34.6f));
        books.add(new Book("Java核心技術",88));
        books.add(new Book("Java程式設計思想",122));
        //books.add("aaa");//去掉註釋試試
        for (Book book : books) {
            System.out.println(book.getName());
        }
        //Map的遍歷
        Map<String,Book> bookMap=new HashMap<String,Book>();
        bookMap.put("java", new Book("Java入門到精通",122));
        bookMap.put("docker", new Book("docker入門到精通",122));
        //1.遍歷鍵獲取值
        for (String key : bookMap.keySet()) {
            Book book=bookMap.get(key);
            System.out.println(book.getName());
        }
        System.out.println("==============");
        //2.遍歷值
        for (Book book : bookMap.values()) {
            System.out.println(book.getName());
        }
        System.out.println("--------------");
        //3.同時遍歷鍵和值
        for (Entry<String, Book> entry : bookMap.entrySet()) {
            String key=entry.getKey();
            Book value=entry.getValue();
            System.out.println("key:"+key+" value:"+value.getName());
        }
    }
}

map.keySet() 返回的是一個 Set 集合,這也是Map的鍵不能重複的原因。entrySet()方法返回了Entry的集合,Entry包含了鍵和值。

迭代器 Iterator

迭代器用來迭代集合,常用的兩個方法:hasNext()返回布林值,判斷是否存在另一個可訪問的元素。next()返回要訪問的下一個元素,可以指定為泛型,這樣不需要型別轉換。

下面看一下 List 集合和 Map 使用迭代器。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class TestIterator {

    public static void main(String[] args) {
        List<Book> books=new ArrayList<Book>();
        books.add(new Book("80天環遊世界",34.6f));
        books.add(new Book("Java核心技術",88));
        books.add(new Book("Java程式設計思想",122));
        //獲取迭代器
        Iterator<Book> i=books.iterator();
        while(i.hasNext()) {
            Book book=i.next();
            System.out.println("圖書名字:"+book.getName());
        }
        //Map可以迭代鍵或值
        Map<String,Book> bookMap=new HashMap<String,Book>();
        bookMap.put("java", new Book("Java入門到精通",122));
        bookMap.put("docker", new Book("docker入門到精通",122));
        //獲取鍵的迭代器
        Iterator<String> iKey=bookMap.keySet().iterator();
        while(iKey.hasNext()) {
            String key=iKey.next();
            System.out.println(key);
        }
        //值的迭代器寫法類似
        Iterator<Book> iValue=bookMap.values().iterator();
        while(iValue.hasNext()) {
            Book value=iValue.next();
            System.out.println(value.getPrice());
        }
    }
}

迭代器可以和其他迴圈用法結合,大家可以自己嘗試。

包裝類

先看一下這段程式碼是否能編譯呢?

List<int> nums=new ArrayList<int>();

編譯器會提示只能寫引用型別,java為每個基本資料型別都提供了引用型別。

基本型別 引用型別
int Integer
double Double
float Float
byte Byte
long Long

這些引用型別賦值時可以賦值對應的基本型別

Integer i=1;
Float f=2.2f;

也可以像引用型別那樣初始化為null

Integer i=null;

這些包裝類的方法過多,大家可以查閱文件。

歡迎將查閱到的包裝類的方法發表到留言區