1. 程式人生 > >集合、Iterator迭代器、增強for迴圈、泛型、List介面、Set介面

集合、Iterator迭代器、增強for迴圈、泛型、List介面、Set介面

1、集合:

集合是java中提供的一種容器,可以用來儲存多個數據。

集合和陣列的區別:陣列的長度是固定的。集合的長度是可變的。集合中儲存的元素必須是引用型別資料

(1)ArrayList 集合儲存元素並遍歷

練習一:ArrayList集合儲存5int型別元素

import java.util.ArrayList;
public class Demo01 {
    public static void main(String[] args) {
        ArrayList<Integer> list=new ArrayList<Integer>();
        list.add(
1); list.add(2); list.add(3); list.add(4); list.add(5); for(int i=0;i<list.size();i++){ System.out.println(list.get(i)); } } }

練習二:ArrayList集合儲存5Person型別元素

package demo03;

public class Person {
    String name;

    public Person(String name) {//================================構造方法傳參
        
super(); this.name = name; } @Override public String toString() {//==================================重寫toString方法 return name ; } }
package demo03;

import java.util.ArrayList;
public class Demo01  {
    public static void main(String[] args) {
        ArrayList
<Person> list=new ArrayList<Person>(); list.add(new Person("張三")); list.add(new Person("李四")); list.add(new Person("王五")); list.add(new Person("趙六")); list.add(new Person("孫七")); for(int i=0;i<list.size();i++){ System.out.print(list.get(i)+" "); } } }

 

(2)ArrayList集合的繼承實現關係

ArrayList類繼承了抽象類AbstractList同時實現介面List,而List介面又繼承了Collection介面。Collection介面為最頂層集合介面了

public interface List extends Collection {//==========List介面繼承了Collection介面
}
public class ArrayList extends AbstractList implements List{
}

我們在使用ArrayList類時,該類已經把所有抽象方法進行了重寫。那麼,實現Collection介面的所有子類都會進行方法重寫。

Collection介面常用的子介面有:List介面、Set介面

List介面常用的子類有:ArrayList類、LinkedList

Set介面常用的子類有:HashSet類、LinkedHashSet

圖shi:

Collection介面是集合中的頂層介面,因此他中的所有的子類功能都可以使用。

一些 collection 允許有重複的元素,而另一些則不允許。一些 collection 是有序的,而另一些則是無序的。

ArrayList是允許重複和有序的,set是不許重複和無序的

Collection 表示一組物件,這些物件也稱為 collection 的元素。

Collection介面的基本方法:

add():bollean型別,確保此Collection包含指定的元素,基本無法使用,

clear():移除此Collection中的所有的元素

contains():boolean型別,如果此Collection包含指定的元素,包含則返回true,反之返回false

 size():int型別,返回此Collection中的元素數

 toArray():將集合轉成陣列

這些基本方法都得通過方法重寫後才能使用,要不沒有意義,都是通過new ArrayList重寫

格式1:

Collection<String> col=new ArrayList<String>();String代表了元素型別,col是變數名:這樣建立的集合,只能儲存<>中指定的元素型別,該方式為常用方式

 格式2:

Collection col=new ArrayList();col是變數名,這樣建立的集合,集合的元素型別預設為Object型別,即任何型別的元素都可以儲存。

 Collection介面中的方法的演示:

package demo06Collectionmethod;

import java.util.ArrayList;
import java.util.Collection;

public class Demo01 {

    public static void main(String[] args) {
        Collection col=new ArrayList();
        col.add("abc");//add()方法是重寫後的add方法
        col.add("b");
        col.add("def");
        System.out.println(col);
        System.out.println(col.toString());
        //2,從集合中刪除元素。remove(Object o)方法
        col.remove("b");
        //刪除後,集合元素為[abc, def]
        //3,判斷集合中是否包含指定元素。contains(Object o)方法
        System.out.println(col.contains("abc"));
        //4,獲取集合元素個數。size()方法
        System.out.println(col.size());
        //5,返回包含集合中所有元素的陣列。toArray()方法
        Object[] array = col.toArray();
        for(Object bb:array){
            System.out.println(bb);
        }
        
        //陣列中的元素為{"abc", "def"}
        //6,清除集合元素。remove()方法
        //col.clear();
        //清空後,集合元素為[],代表沒有元素

    }

}

 2、Iterator迭代器

 (1)Iterator迭代器介紹:

迭代:

Collection集合元素的通用獲取方式:在取元素之前先要判斷集合中有沒有元素,如果有,就把這個元素取出來,繼續在判斷,如果還有就再取出出來。一直把集合中的所有元素全部取出。這種取出方式專業術語稱為迭代。

集合中把這種取元素的方式描述在Iterator介面中

Iterator介面的常用方法:

hasNext():boolean型別,判斷集合是否有下一個元素可以迭代,如果集合中有元素,可以迭代,則返回true,反之返回false

Next():返回下一個迭代元素

Collection介面描述了一個抽象方法iterator方法,所有Collection子類都實現了這個方法,並且有自己的迭代形式。

Collection介面有一個Iteratoral超級介面,裡面有一個方法,來獲取 Iterator物件

 iterator():返回在此Collection的元素上進行迭代的迭代器

格式:

Collection<String> coll = new ArrayList<String>();

//2.獲取容器的迭代器物件。通過iterator方法。

Iterator it = coll.iterator();

用法例項:

package demo05;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class Demo01 {

    public static void main(String[] args) {
        Collection<String> col=new ArrayList<String>();
        col.add("a");col.add("b");
        col.add("c");col.add("d");
        col.add("e");col.add("f");
        Iterator it=col.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }

    }

}

集合元素的向下轉型

集合中可以儲存任何物件,存放進去的資料都成了Object

 注意:

集合中儲存其實都是物件的地址。

集合中可以儲存基本數值因為出現了基本型別包裝類,它提供了自動裝箱操作(基本型別à物件),這樣,集合中的元素就是基本數值的包裝類物件。

儲存時提升了Object。取出時要使用元素的特有內容,必須向下轉型。

String str = (String) it.next();

    System.out.println(str.length());

注意:

Iterator介面也可以使用<>來控制迭代元素的型別的。

Collection<String> coll = new ArrayList<String>();

coll.add("abc");

coll.add("aabbcc");

coll.add("cat");

Iterator<String> it = coll.iterator();

while (it.hasNext()) {

    String str = it.next();

//當使用Iterator<String>控制元素型別後,就不需要強轉了。獲取到的元素直接就是String型別

    System.out.println(str.length());

}

迭代器使用示例:

package demo01;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class Demo01 {

    public static void main(String[] args) {    
        Demo01 p=new Demo01();
        p.method();
        p.method02();
        p.method03();
    }
    public void method(){
        Collection<String> col=new ArrayList<String>();
        col.add("zbc");
        col.add("bhjbh");
        col.add("vsnaj");
        col.add("abvij");
        //獲取迭代器物件
        Iterator<String> it=col.iterator();
        //迭代器進行迭代
        while(it.hasNext()){
            System.out.println(it.next());
        }
    }
    public static void method02(){
        Collection<Person> col=new ArrayList<Person>();
        col.add(new Person("zhangsan",12));
        col.add(new Person("lisi",14));
        Iterator<Person> it=col.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
    }
    public static void method03(){
        Collection col=new ArrayList();
        col.add("111");
        col.add(123);
        //獲取迭代器物件
        Iterator it=col.iterator();
        while(it.hasNext()){
            Object obj=it.next();//it.next()是匿名函式,只能用一次,先定住it,next型別object,定以後可以重複用
            if(obj instanceof String){
                String s=(String)it.next();//向下轉型
                System.out.println(s);
            }
            
        }
    }

}

3、增強for迴圈

(1)

增強for迴圈是

專門用來遍歷陣列和集合的

部原理其實是個Iterator迭代器,所以在遍歷的過程中,不能對集合中的元素進行增刪操作。

格式:

for(資料型別     變數名:容器){   }

它用於遍歷Collection介面和陣列。通常只進行遍歷元素,不要在遍歷的過程中對集合元素進行增刪操作。

package demo02;

import java.util.ArrayList;

public class Demo03 {

    public static void main(String[] args) {
        //遍歷陣列
        String[] arr={"a","d","f"};
        for(String str:arr){
            System.out.println(str);
            System.out.println(str.length());    
        }
        //遍歷集合
        ArrayList<Integer> list=new ArrayList<Integer>();
        list.add(123);
        list.add(1234);
        list.add(34);
        for(Integer s:list){
            System.out.println(s);
        }
    }

}

注意:

增強for迴圈和老式的for迴圈有什麼區別?

增強for迴圈必須有被遍歷的目標。目標只能是Collection或者是陣列。

建議:遍歷陣列時,如果僅為遍歷,可以使用增強for如果要對陣列的元素進行 操作,使用老式for迴圈可以通過下標操作。

增強for底層就是Iterator迭代器

4、泛型

(1)泛型的引入

注意:

集合就要新增泛型。泛型不進class檔案,class檔案裡沒有泛型一說,泛型和註釋都不進class檔案

集合中是可以存放任意物件的,只要把物件儲存集合後,那麼這時他們都會被提升成Object型別。當我們在取出每一個物件,並且進行相應的操作,這時必須採用型別轉換。

集合中什麼型別的元素都可以儲存。導致取出時,如果出現強轉就會引發執行時 ClassCastException。怎麼來解決這個問題呢?使用集合時,必須明確集合中元素的型別。這種方式稱為:泛型。

(2)泛型的定義與使用

含有泛型的類

定義格式:

修飾符 class 類名<代表泛型的變數> { }

class ArrayList<E>{
public boolean add(E e){ }
    public E get(int index){ }
}

建立物件時確定泛型的型別

格式:

例如:ArrayList<String> list = new ArrayList<String>();

ArrayList<Integer> list = new ArrayList<Integer>();此時,變數E的值就是Integer型別

(3)使用泛型的好處

將執行時期的ClassCastException(型別轉換異常),轉移到了編譯時期變成了編譯失敗。

5、List介面

 (1)List介面的概述:

在Collection中有兩個介面:List和Set介面,

List介面可以對列表中每個元素的插入位置進行精確地控制。使用者可以根據元素的整數索引(在列表中的位置)訪問元素,並搜尋列表中的元素

List介面:

它是一個元素存取有序的集合。例如,存元素的順序是11、22、33。那麼集合中,元素的儲存就是按照11、22、33的順序完成的)。

l 它是一個帶有索引的集合,通過索引就可以精確的操作集合中的元素(與陣列的索引是一個道理)。

集合中可以有重複的元素,通過元素的equals方法,來比較是否為重複的元素。

List介面的常用子類有:

l ArrayList集合

l LinkedList集合

 (2)List介面中的常用方法:

l 增加元素方法

 add(Object e):向集合末尾處,新增指定的元素

 add(int index, Object e):向集合指定索引處,新增指定的元素,原有元素依次後移

l 刪除元素刪除

 remove(Object e):將指定元素物件,從集合中刪除,返回值為被刪除的元素

 remove(int index):將指定索引處的元素,從集合中刪除,返回值為被刪除的元素

l 替換元素方法

 set(int index, Object e):將指定索引處的元素,替換成指定的元素,返回值為替換前的元素

l 查詢元素方法

 get(int index):獲取指定索引處的元素,並返回該元素

package demo03;

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

public class Demo01 {

    public static void main(String[] args) {
        List<String> list=new ArrayList<String>();
        list.add("哆啦a夢");//向集合尾部新增元素
        list.add("大熊");//向集合尾部新增元素
        //指定位置新增指定元素
        list.add(1,"靜香");
        /*for(int i=0;i<list.size();i++){
            System.out.println(list.get(i));
        }*/
        String str = list.remove(2);
        //修改指定下標的元素值
        list.set(1, "胖虎");
        System.out.println(str);
        //獲取指定下標的值
        for(int i=0;i<list.size();i++){
            System.out.println(list.get(i));
        }
    }

}

 (3)Iterator的併發修改異常

list集合迭代元素中,對元素進行判斷,一旦條件滿足就新增一個新元素

public class IteratorDemo {
//在list集合迭代元素中,對元素進行判斷,一旦條件滿足就新增一個新元素
    public static void main(String[] args) {
        //建立List集合
        List<String> list = new ArrayList<String>();
        //給集合中新增元素
        list.add("abc1");
        list.add("abc2");
        list.add("abc3");
        list.add("abc4");
        //迭代集合,當有元素為"abc2"時,集合加入新元素"a"
        Iterator<String> it = list.iterator();
        while(it.hasNext()){
            String str = it.next();
            //判斷取出的元素是否是"abc2",是就新增一個新元素
            if("abc2".equals(str)){
                list.add("a");// 該操作會導致程式出錯
            }
        }
        //列印容器中的元素
        System.out.println(list);
    }
}

 執行後出現

java.util.ConcurrentModificationException========================併發修改異常

 如何解決這個問題:

在迭代時,不要使用集合的方法操作元素。

 (4)List集合儲存元素的結構:

資料儲存的常用結構有:堆疊、佇列、陣列、連結串列。

 特點:

堆疊:先進後出

佇列:先進先出

陣列:查詢快,增刪慢,ArrayList集合資料儲存的結構是陣列結構

連結串列:查詢滿增刪快,   LinkedList集合資料儲存的結構是連結串列結構

 連結串列結構:LinkedList查詢慢,增刪快,因此其提供了很多增、刪的方法

 addFirst()將指定元素插入表頭

addLast()    將指定元素 插入 最後

getFirst()返回第一個元素

getLast()返回最後一個元素

removeFirst()移除並返回第一個元素

removeLast()移除並返回最後一個元素

isEmpty():boolean型別,列表不含資料返回true

6、Set介面

 (1)概述

List中是可以存放重複元素的,Set介面,它裡面的集合,所儲存的元素就是不重複的。

 Set集合通過元素的equals方法,來判斷是否為重複元素, 

 (2)HashSet集合

HashSet集合不能保證的迭代順序與元素儲存順序相同。

 HashSet集合實現Set介面,由雜湊表支援

什麼是雜湊表呢? 

雜湊表底層,使用的也是陣列機制,陣列中也存放物件,而這些物件往陣列中存放時的位置比較特殊,

當需要把這些物件給陣列中存放時,那麼會根據這些物件的特有資料結合相應的演算法,計算出這個對

象在陣列中的位置,然後把這個物件存放在陣列中。而這樣的陣列就稱為雜湊陣列,即就是雜湊表。

當向雜湊表中存放元素時,需要根據元素的特有資料結合相應的演算法,這個演算法其實就是Object類中的hashCode方法

由於任何物件都是Object類的子類,所以任何物件有擁有這個方法。即就是在給雜湊表中存放物件時,會呼叫物件的hashCode方法,算出物件在表中的存放位置,這裡需要注意,如果兩個物件hashCode方法算出結果一樣,這樣現象稱為雜湊衝突,這時會呼叫物件的equals方法,比較這兩個物件是不是同一個物件,如果equals方法返回的是true,那麼就不會把第二個物件存放在雜湊表中,如果返回的是false,就會把這個值存放在雜湊表中。 

HashSet集合元素的唯一,其實就是根據物件的hashCode和equals方法來決定的。如果我們往集合中存放自定義的物件,那麼保證其唯一,就必須複寫hashCode和equals方法建立屬於當前物件的比較方式。

HashSet中儲存JavaAPI中提供的型別元素時,不需要重寫元素的hashCode和equals方法,因為這兩個方法,在JavaAPI的每個類中已經重寫完畢,如String類、Integer類等。

如:

package demo05;

import java.util.HashSet;

public class Demo {

    public static void main(String[] args) {
        Object obj=new Object();
        System.out.println(obj.hashCode());
        HashSet<String> set=new HashSet<String>();
        set.add("abc");
        set.add("bcd");
        set.add("ace");
        set.add("abc");
        for(String s:set){
            System.out.println(s);
            System.out.println(s.hashCode());
            
        }
        
    }

}

總結:

雜湊不能儲存重複元素的原因:

set集合存元素的時候,先呼叫該元素型別的hashcode方法計算雜湊值,先去陣列中看下有沒有重複的雜湊值,如果沒有,則新增上,如果有,則繼續呼叫該元素型別的equals方法判斷內容,如果內容相同,則丟掉(其實是覆蓋掉),如果內容不同,則新增上

(3) HashSet儲存自定義型別元素

HashSet中存放自定義型別元素時,需要重寫物件中的hashCode和equals方法建立自己的比較方式,才能保證HashSet集合中的物件唯一

package demo05;

public class Person {
    String name;
    int age;
    
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Person other = (Person) obj;
        if (age != other.age)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
}
package demo05;

import java.util.HashSet;

public class Demo03 {

    public static void main(String[] args) {
        HashSet<Person> set=new HashSet<Person>();
        set.add(new Person("a",18));
        set.add(new Person("b",17));
        set.add(new Person("c",19));
        set.add(new Person("a",18));
        for(Person p:set){
            System.out.println(p);
        }

    }

}

(4) LinkedHashSet介紹

HashSet保證元素唯一,可是元素存放進去是沒有順序的,那麼我們要保證有序

HashSet下面有一個子類LinkedHashSet,它是連結串列和雜湊表組合的一個數據儲存結構。

public class LinkedHashSetDemo {
    public static void main(String[] args) {
        Set<String> set = new LinkedHashSet<String>();
        set.add("bbb");
        set.add("aaa");
        set.add("abc");
        set.add("bbc");
Iterator it = set.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
    }
}

輸出結果如下,LinkedHashSet集合保證元素的存入和取出的順序:

bbb

aaa

abc

bbc