java基礎學習之類集框架(十)

茉莉915發表於2020-10-26

類集框架的簡介

類集的主要用處是在於其實現了動態物件陣列的操作,並且定義了大量的操作。

單物件儲存父介面:Collection

java.util.Collection是進行單物件儲存的最大父介面,即每次利用Collection介面都只能儲存
一個物件資訊。

// A code block
public interface Collection<E> extends Iterable<E>

Collection介面的核心方法

NO.方法名稱型別描述
1public boolean add(E e)普通向集合裡面儲存資料
2public boolean addAll(Collection<? extends E> c)普通追加一個集合
3public void clear()普通清空集合,根元素為null
4public boolean contains(Object o)普通判斷是否包含指定內容,需要equals()支援
5public boolean isEmpty()普通判斷是否是空集合(不是null)
6public boolean remove(Object o)普通刪除物件,需要equals()支援
7public int size()普通取得集合中儲存的元素個數
8public Object[] toArray()普通將集合變為物件陣列儲存
9public Iterator< E > iterator()普通為Iterator介面例項化(Interator介面定義)

對於表中的方法,一定要記住add()與iterator()兩個方法。

Collection及其子介面繼承關係
在這裡插入圖片描述

List子介面

List子介面最大的功能是裡面所儲存的資料可以存在有重複內容,並且在Collection子介面中List子介面是最為常用的一個子介面,在List介面中對Collection介面的功能進行了擴充

NO.方法名稱型別描述
1public E get(int index)普通取得索引編號內容
2public E set(int index, E element)普通修改指定索引編號的內容
3public ListIterator< E> listIterator()普通為ListIterator介面例項化

新的子類:ArrayList

ArrayList子類是List子介面中最常用的一個子類。

// An highlighted block
public class Demo{
	public static void main(String[] args){
		List<String> all = new ArrayList<>();
		System.out.println("長度:"+all.size()+",是否為空:"+all.isEmpty());
		all.add("hello");
		all.add("hello");
		all.add("world");
		for(int x = 0; x < all.size(); x++){
			String str = all.get(x);
			system.out.println(str);
		}
	}
}
執行結果:長度:0,是否為空:true
		hello
		hello
		world

在集合裡面刪除物件

// An highlighted block
public class Book{
	private String title;
	private double price;
	public Book(String title,double price){
		this.title = title;
		this.price = price;
	}
	@Override
	public boolean equals(Object ob){
		if(this == ob){
			return true;
		}
		if(ob == null){
			return false;
		}
		if(!(ob instanceof Book)){
			return false;
		}
		Book book = (Book)ob;
		if(this.title.equals(book.title)&&this.price == book.price){
			return true;
		}
	}
	@Override
	public String toString(){
		return "書名:"+this.title+",價格:"+this.price;
	}
}
public class Demo{
	public static void main(String[] args){
		List<String> all = new ArrayList<>();
		all.add(new Book("Java開發實戰經典"79.8));
		all.add(new Book("Java Web開發實戰經典"69.8));
		all.add(new Book("Mysql開發實戰經典"89.8));
		all.remove(new Book("Mysql開發實戰經典"89.8));
		system.out.println(all);
	}
}
執行結果:Java開發實戰經典,79.8,Java Web開發實戰經典,69.8

請解釋ArrayList和LinkedList的區別
實際上在List子介面中還存在一個LinkedList子類,而使用時大部分情況下都是利用子類為父介面例項化。

  1. ArrayList中採用順序式的結果進行資料儲存,並且可以自動生成相應的索引資訊;
  2. LinkedList集合儲存的是前後元素,也就是說,它每一個節點儲存的是兩個元素物件,一個它對應的下一個節點,以及另外一個它對應的上一個節點,所以LinkedList要佔用比ArrayList更多的記憶體空間。同時LinkedList比ArrayList多實現了一個Queue佇列資料介面。

舊的子類:Vector

// An highlighted block
public class TestDemo {
    public static void main(String args[]) {
        List<String> all = new Vector<String>();
        System.out.println("長度:"+all.size()+",是否為空:"+all.isEmpty());
        all.add("hello");
        all.add("hello");
        all.add("world");
        System.out.println("長度:"+all.size()+",是否為空:"+all.isEmpty());
        for(int x = 0; x < all.size();x++){
            String str = all.get(x);
            System.out.println(str);
        }
    }
}
執行結果:長度:0,是否為空:true
		長度:3,是否為空:false
		hello
		hello
		world

ArrayList和Vector子類的區別:

No區別點ArrayList(90%)Vector(10%)
1推出時間JDK1.2推出,屬於新的類JDK1.0推出,屬於舊的類
2效能採用非同步處理採用同步處理
3資料安全非執行緒安全執行緒安全
4輸出Iterator、ListIterator、foreachIterator、ListIterator、foreach、Enumeration

Set子介面

在Collection介面下又有另外一個比較常用的子介面為Set子介面,但是Set子介面並不像List子介面那樣對Collection介面進行了大量的擴充,而是簡單地繼承了Collection介面。也就是說無法使用get()方法根據索引取得儲存資料的操作。在Set介面下有兩個常用的子類:HashSet、TreeSet。

HashSet是雜湊存放資料,而TreeSet是有序存放的子類。在實際開發中,如果要使用TreeSet子類則必須同時使用比較器的概念,而HashSet子類相對於TreeSet子類更加容易一些,所以如果沒有排序要求應優先考慮HashSet子類。

使用HashSet子類的特點

// An highlighted block
public class TestDemo {
    public static void main(String args[]) {
        Set<String> all = new HashSet<String>();
        all.add("jixianit");
        all.add("mldn");
        all.add("yootk");
        all.add("yootk");
        System.out.println(all);
    }
}
執行結果:[mldn, jixianit, yootk]

可以看出在Set集合中不允許儲存重複資料。
關於"Hash"的說明
這種演算法就是利用二進位制的計算結果來設定儲存的空間,根據數值的不同,最終儲存空間的位置也不同,所以利用Hash演算法儲存的集合都是無序的,但是查詢速度較快。

使用TreeSet子類

// An highlighted block
public class TestDemo {
    public static void main(String args[]) {
        Set<String> all = new TreeSet<String>();
        all.add("jixianit");
        all.add("mldn");
        all.add("yootk");
        all.add("yootk");
        System.out.println(all);
    }
}
執行結果:[jixianit, mldn,yootk]

TreeSet子類屬於排序的類集結構,所以當使用TreeSet子類例項化Set介面後,所儲存的資料將變為有序,預設情況按字母的升序排列。

關於資料排序的說明

TreeSet子類儲存的內容可以進行排序,但是其排序是依靠比較器介面(Comparable)實現的,即如果要利用TreeSet子類儲存任意類的物件,那麼該物件所在的類必須要實現java.lang.Comparable介面。

// An highlighted block
class Book implements Comparable<Book>{
    private String title;
    private double price;
    public Book(String title,double price){
        this.title = title;
        this.price = price;
    }
    @Override
    public String toString(){
        return "書名:"+this.title+",價格:"+this.price;
    }

    @Override
    public int compareTo(Book o) {
        if(this.price > o.price){
            return 1;
        }else if(this.price < o.price){
            return -1;
        }else {
            return this.title.compareTo(o.title);
        }
    }
}
public class TestDemo {
    public static void main(String args[]) {
        Set<Book> all = new TreeSet<Book>();
        all.add(new Book("Java開發實戰經典",79.8));
        all.add(new Book("Java開發實戰經典",79.8));
        all.add(new Book("JSP開發實戰經典",79.8));
        all.add(new Book("Android開發實戰經典",89.8));
        System.out.println(all);
    }
}
執行結果:[書名:JSP開發實戰經典,價格:79.8, 書名:Java開發實戰經典,價格:79.8, 書名:Android開發實戰經典,價格:89.8]

本程式首先利用TreeSet子類儲存了若干個Book類物件,由於Book類實現了Comparable介面,所以會自動將儲存的Book類物件強制轉換為Comparable介面物件,然後呼叫compareTo()方法進行排序,如果發現比較結果為0則認為是重複元素,將不再進行儲存。因此TreeSet資料的排序以及重複元素的消除依靠的都是Comparable介面。

關於重複元素說明

TreeSet利用Comparable介面實現重複元素的判斷,但是這樣的操作只適合支援排序類集操作環境下;而其他子類(例如:HashSet)如果要消除重複元素,則必須依靠Object類中提供的兩個方法。

  1. 取得雜湊碼:public int hashCode();
    先判斷物件的雜湊碼是否相同,依靠雜湊碼取得一個物件的內容;
  2. 物件比較:public boolean equals(Object obj)。
    再將物件的屬性進行依次的比較。

利用HashSet子類儲存自定義物件。

// An highlighted block
class Book {
    private String title;
    private double price;
    public Book(String title,double price){
        this.title = title;
        this.price = price;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Book book = (Book) o;
        return Double.compare(book.price, price) == 0 &&
                Objects.equals(title, book.title);
    }

    @Override
    public int hashCode() {
        return Objects.hash(title, price);
    }

    @Override
    public String toString(){
        return "書名:"+this.title+",價格:"+this.price;
    }

}
public class TestDemo {
    public static void main(String args[]) {
        Set<Book> all = new HashSet<>();
        all.add(new Book("Java開發實戰經典",79.8));
        all.add(new Book("Java開發實戰經典",79.8));
        all.add(new Book("JSP開發實戰經典",79.8));
        all.add(new Book("Android開發實戰經典",89.8));
        System.out.println(all);
    }
}
執行結果:[書名:JSP開發實戰經典,價格:79.8, 書名:Android開發實戰經典,價格:89.8, 書名:Java開發實戰經典,價格:79.8]

直接通過idea工具生成操作步驟:【Source】→【Generate hashCode() and equals()】

集合輸出

迭代輸出:Iterator

Iterator(迭代器)是集合輸出操作中最為常見的介面,而在Collection介面中也提供了直接為Iterator介面例項化的方法(iterator()),所以任何集合型別都可以轉換為Iterator介面輸出。

Iterator介面中一共定義了兩個抽象方法,

NO.方法型別描述
1public boolean hasNext()普通判斷是否還有內容
2public E next()普通取出當前內容

在這裡插入圖片描述

// An highlighted block
public class TestDemo {
    public static void main(String args[]) {
        List<String> all = new ArrayList<>();
        all.add("hello");
        all.add("hello");
        all.add("world");
        Iterator<String> iter = all.iterator();
        while (iter.hasNext()){
            String str = iter.next();
            System.out.println(str);
        }
    }
}
執行結果:hello
		 hello
		 world

關於Iterator介面中的remove()方法。
如果利用集合類(Collection、List、Set)提供的remove()方法會導致程式中斷執行的問題,而如果非要進行集合元素的刪除,只能利用Iterator介面提供的remove()方法才可以正常完成。

雙向迭代:ListIterator

雖然利用Iterator可以實現集合的迭代輸出操作,但是Iterator本身卻存在一個問題:只能進行由前向後的輸出。所以為了讓輸出變得更加靈活,在類集框架中就提供了一個ListIterator介面,利用此介面可以實現雙向迭代。ListIterator屬於Iterator的子介面,此介面常用方法如表:

NO.方法型別描述
1public boolean hasPrevious()普通判斷是否有前一個元素
2public E previous()普通取出前一個元素
3public E add()普通向集合追加元素
4public E set()普通修改集合元素

實際上迭代器本質上就是一個指標的移動操作,而ListIterator與Iterator的迭代處理原理類似。所以如果要進行由後向前迭代,則必須先進行由前向後迭代。

// An highlighted block
public class TestDemo {
    public static void main(String args[]) {
        List<String> all = new ArrayList<>();
        all.add("hello");
        all.add("hello");
        all.add("mldn");
        all.add("world");
        ListIterator<String> iter = all.listIterator();
        while (iter.hasNext()){
            String str = iter.next();
            System.out.println(str);
        }
        System.out.println();
        while(iter.hasPrevious()){
            String str = iter.previous();
            System.out.println(str);
        }
    }
}
執行結果:hello
		hello
		mldn
		world
		
		world
		mldn
		hello
		hello

foreach輸出

// An highlighted block
public class TestDemo {
    public static void main(String args[]) {
        List<String> all = new ArrayList<>();
        all.add("hello");
        all.add("hello");
        all.add("mldn");
        all.add("world");
        for(String str : all){
            System.out.println(str);
        }
    }
}
執行結果:hello
		 hello
		 world

Enumeration輸出

Enumeration(列舉輸出)是與Vector類一起在JDK1.0時推出的輸出介面

// An highlighted block
public class TestDemo {
    public static void main(String args[]) {
        Vector<String> all = new Vector<>();
        all.add("hello");
        all.add("hello");
        all.add("mldn");
        all.add("world");
        Enumeration<String> enu = all.elements();
        while (enu.hasMoreElements()){
            String str = enu.nextElement();
            System.out.println(str);
        }
    }
}
執行結果:hello
		 hello
		 mldn

本程式與Iterator介面輸出實現的最終效果是完全一致的,唯一的區別就是,如果要使用Enumeration介面例項化,就必須依靠Vector子類完成。

偶物件儲存:Map介面

Collection每次只能夠儲存一個物件,所以屬於單值儲存父介面。而在類集中又提供有儲存偶物件的集合:Map集合,利用Map結合可以儲存一對關聯資料(按照“key = value”的形式),如圖13-4所示。,這樣就可以實現根據key取得value的操作。

在這裡插入圖片描述在這裡插入圖片描述
Map介面的常用方法

NO.方法型別描述
1public V put(K key, V value)普通向集合中儲存元素
2public V get(Object key)普通根據key查詢對應的value資料
3public Set<Map.Entry<K,V>> entrySet()普通將Map集合轉化為Set集合
4public Set keySet()普通取出全部的key

HashMap的使用

// An highlighted block
public class TestDemo {
    public static void main(String args[]) {
        HashMap<String,Integer> map = new HashMap<>();
        map.put("壹",1);
        map.put("貳",2);
        map.put("叄",3);
        map.put("叄",33);
        map.put("肆",4);
        map.put("空",null);
        map.put(null,0);
        System.out.println(map.get("叄"));
        System.out.println(map.get(null));
        System.out.println(map.get("空"));
    }
}
執行結果:33
		 0
		 null

從上可以發現如下特點:

  • 使用HashMap定義的Map集合是無序存放的;
  • 如果發現了重複的key會進行覆蓋,使用新的內容替換舊的內容;
  • 使用HashMap子類儲存資料時key或value可以儲存為null。

Hashtable的使用

// An highlighted block
public class TestDemo {
    public static void main(String args[]) {
        Map<String,Integer> map = new Hashtable<>();
        map.put("壹",1);
        map.put("貳",2);
        map.put("叄",3);
        map.put("叄",33);
        map.put("肆",4);
        System.out.println(map.get("叄"));
    }
}
執行結果:33

使用Hashtable子類例項化的Map集合中,儲存的key和value都不允許出現null,否則會出現"NullPointerException"異常

HashMap和Hashtable子類的區別:

No區別點HashMapHashtable
1推出時間JDK1.2推出,屬於新的類JDK1.0推出,屬於舊的類
2效能採用非同步處理採用同步處理
3資料安全非執行緒安全執行緒安全
4設定null允許key或value內容為null不允許設定null

利用Iterator輸出Map集合

進行Map集合儲存時,所儲存的key與value會自動包裝為Map.Entry介面物件,也就是說如果利用Iterator進行迭代,那麼每當使用next()方法讀取資料時返回的都會是一個Map.Entry介面物件,此介面定義如下:
public static interface Map.Entry<K,V> {}
Map.Entry介面定義的常用方法

No方法型別描述
1public K getKey()普通取得資料中的key
2public V getValue()普通取得資料中的value
3public V setValue(V value)普通修改資料中的value

在這裡插入圖片描述
Iterator輸出Map集合的操作步驟:
1.利用entrySet()方法將Map介面資料中的資料轉換為Set介面例項進行儲存,此時Set介面中所使用的泛型型別為Map.Entry,而Map.Entry中的K與V的泛型型別則與Map集合定義的K與V型別相同;
2.利用Set介面中的iterator()方法將Set集合轉化為Iterator介面例項;
3.利用Iterator介面進行迭代輸出,每一次迭代取得的都是Map.Entry介面例項,而後利用此介面例項進行key與value的分離。

// An highlighted block
public class TestDemo {
    public static void main(String args[]) {
        Map<String,Integer> map = new HashMap<>();
        map.put("壹",1);
        map.put("貳",2);
        map.put("叄",3);
        map.put("叄",33);
        map.put("肆",4);
        map.put("空",null);
        map.put(null,0);
        Set<Map.Entry<String,Integer>> set= map.entrySet();
        Iterator<Map.Entry<String, Integer>> iterator = set.iterator();
        while (iterator.hasNext()){
            Map.Entry<String, Integer> next = iterator.next();
            System.out.println(next.getKey()+"="+next.getValue());
        }
    }
}
執行結果:貳=2
		null=0=33=4=1=null

自定義Map集合的key型別

在使用Map介面的時候可以發現,幾乎可以使用任意的型別來作為key或value的存在,那麼也就表示也可以使用自定義的型別作為key。那麼這個作為key的自定義的類必須要覆寫Object類之中的hashCode()與equals()兩個方法,因為只有靠這兩個方法才能夠確定元素是否重複,而在Map中指的是是否能夠找到。

// An highlighted block
class Book{
    private String title;
    public Book(String title){
        this.title = title;
    }

    @Override
    public String toString() {
        return "Book{" +
                "title='" + title + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Book book = (Book) o;
        return Objects.equals(title, book.title);
    }

    @Override
    public int hashCode() {
        return Objects.hash(title);
    }
}
public class TestDemo {
    public static void main(String args[]) {
        Map<Book, String> map = new HashMap<>();
        map.put(new Book("Java開發"),new String("Java"));
        System.out.println(map.get(new Book("Java開發")));
    }
}
執行結果:Java

Stack子類

棧也是一種動態物件陣列,採用的是一種先進後出的資料結構形式,即:在棧中最早儲存的資料最後才會取出,而最後儲存的資料可以最先取出

在這裡插入圖片描述在這裡插入圖片描述
java.util包中可以利用Stack類實現棧的功能,此類定義如下:
public class Stack extends Vector
Stack類的常用方法

No方法型別描述
1public E push(E item)普通資料入棧
2public E pop()普通資料出棧,如果棧中沒有資料,則呼叫此方法會丟擲空棧異常(EmptyStackException)

觀察棧的操作

// An highlighted block
public class TestDemo {
    public static void main(String args[]) {
        Stack<String> all = new Stack<String>();
        all.push("www.abc.com");
        all.push("www.hhh.com");
        all.push("www.trtr.com");
        System.out.println(all.pop());
        System.out.println(all.pop());
        System.out.println(all.pop());
        System.out.println(all.pop());
    }
}
執行結果:Exception in thread "main" java.util.EmptyStackException
				at java.util.Stack.peek(Stack.java:102)
				at java.util.Stack.pop(Stack.java:84)
				at chapter4.TestDemo.main(TestDemo.java:12)
			www.trtr.com
			www.hhh.com
			www.abc.com

Properties子類

相關文章