1. 程式人生 > >Java集合框架——List介面

Java集合框架——List介面

第三階段 JAVA常見物件的學習

集合框架——List介面

按照集合框架的繼承體系,我們先從Collection中的List介面開始學習

(一) 概述及功能(ArrayList演示)

(1) 概述

List在Collection中充當著一個什麼樣的身份呢?——有序的 collection(也稱為序列)

實現這個介面的使用者以對列表中每個元素的插入位置進行精確地控制。使用者可以根據元素的整數索引(在列表中的位置)訪問元素,並搜尋列表中的元素。與 set 不同,列表通常允許重複的元素。

####(2)List集合功能

A:基本功能:(繼承而來)
//新增功能
boolean add(E e)向集合中新增一個元素
    
//刪除功能
void clear():移除集合中的所有元素
boolean remove(Object o):從集合中移除指定的元素
boolean removeAll(Collection<?> c):從集合中移除一個指定的集合元素(有一個就返回true)

//獲取功能
Iterator iterator():就是用來獲取集合中每一個元素。

//判斷功能
boolean isEmpty():判斷集合是否為空
boolean contains(Object o):判斷集合中是否包含指定元素
boolean containsAll(Collection<?> c):判斷集合中是否包含指定的一個集合中的元素

//長度功能
int size():獲取集合中元素的個數

//集合轉換為陣列
Object[] toArray()
B:特有功能:

//新增功能:在指定位置新增元素
void add(int index,Object element)
   
//獲取功能:獲取指定位置的元素
Object get(int index)
   
//列表迭代器:List集合特有的迭代器
ListIterator listIterator()
   
//刪除功能:根據索引刪除元素,返回被刪除的元素
Object remove(int index)
   
//修改功能:根據索引修改元素,返回被修飾的元素。
Object set(int index,Object element)
A:add() 使用方法:

我們還是先寫一個List遍歷字串的程式碼

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

public class Demo1 {
    public static void main(String[] args) {
        //建立集合物件
        List list = new ArrayList();


        //儲存元素
        list.add("I");
        list.add("love");
        list.add("you");
        list.add("❤");
        list.add("❤");

        //遍歷集合
        Iterator it = list.iterator();
        while (it.hasNext()) {
            String s = (String) it.next();
            System.out.print(s + " ");
        }
    }
}

//執行結果
I love you ❤ ❤ 

通過這段程式碼我們可以看到,List集合的特點——有序(儲存和去取出的元素一直),可重複

我們再使用List儲存學生物件並遍歷看看

//Student 自行補充

//StudentDemo類
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class StudentDemo {
    public static void main(String[] args) {
        List list = new ArrayList();

        Student s1 = new Student("張三", 20);
        Student s2 = new Student("李四", 30);
        Student s3 = new Student("王五", 40);

        list.add(s1);
        list.add(s2);
        list.add(s3);

        Iterator it = list.iterator();
        while (it.hasNext()) {
            Student s = (Student) it.next();
            System.out.println(s.getName() + "---" + s.getAge());
        }
    }
}

//執行結果
張三---20
李四---30
王五---40

//Student s = (Student)it.next();       
//it.next()返回的是Object型別。
//(Student)it.next();是將Object型別強制轉換成Student型別。
//這樣才能夠呼叫getName()方法和getAge()方法。
B:add() 使用方法:
package cn.bwh_02_List.ArrayList;

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

public class StudentDemo {
    public static void main(String[] args) {
        List list = new ArrayList();

        Student s1 = new Student("張三", 20);
        Student s2 = new Student("李四", 30);
        Student s3 = new Student("王五", 40);

        list.add(s1);
        list.add(s2);
        list.add(s3);
		//迭代器遍歷
        Iterator it = list.iterator();
        while (it.hasNext()) {
            Student s = (Student) it.next();
            System.out.println(s.getName() + "---" + s.getAge());
        }

        //利用List的功能遍歷
        for (int x = 0; x < list.size(); x++){
            Student s = (Student) list.get(x);
            System.out.println(s.getName() + "---" + s.getAge());
        }
    }
}

上面幾個例項中,我們使用了Iterator迭代器遍歷,下面我們介紹一種特別的迭代器

C: 列表迭代器:

ListIterator listIterator():列表迭代器:List集合特有的迭代器

列表迭代器繼承於Iterator迭代器,可以直接使用hasNext() 和next()方法

基本功能

//將指定的元素插入列表(可選操作)
void add(E e) 

//返回 true如果遍歷正向列表,列表迭代器有多個元素
boolean hasNext() 

//返回列表中的下一個元素,並且前進游標位置
E next() 

//從列表中刪除由 next()或 previous()返回的最後一個元素(可選操作) 
void remove() 

//用 指定的元素替換由 next()或 previous()返回的最後一個元素(可選操作)
void set(E e) 

特有功能

//獲取上一個元素
Object previous()

//判斷是否有元素
boolean hasPrevious()

列表迭代器的好處是相比Iterator提供了更多的方法,並且可以實現正向遍歷,才能逆向遍歷,所以一般來說意義不大。

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

public class Demo1 {
    public static void main(String[] args) {
        //建立集合物件
        List list = new ArrayList();

        //儲存元素
        list.add("I");
        list.add("love");
        list.add("you");
        list.add("❤");
        list.add("❤");

        ListIterator lit= list.listIterator();
		//正向遍歷
        while(lit.hasNext()){
            String s = (String)lit.next();
            System.out.print(s + " ");
        }

        System.out.println();
		//逆向遍歷
        while (lit.hasPrevious()) {
            String s = (String) lit.previous();
            System.out.print(s + " ");

        }
    }
}

//執行結果
I love you ❤ ❤ 
❤ ❤ you love I 

(二) 併發修改異常問題

我建立了一個集合,並且遍歷它,使用if語句判斷 是否集合中存在"love"這個字串,若存在,就增加一個"❤"元素,我們先順著這個思路寫一下程式碼:

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

/*
 *  併發修改異常
 */
public class Demo2 {
    public static void main(String[] args) {
        //建立集合物件
        List list = new ArrayList();

        //儲存元素
        list.add("I");
        list.add("love");
        list.add("you");

        Iterator it = list.iterator();
        while (it.hasNext()) {
            String s = (String) it.next();
            if ("love".equals(s)) {
                list.add("❤");
            }
            System.out.println(s);
        }
    }
}

//執行結果(節選)
Exception in thread "main" java.util.ConcurrentModificationException

我們貼出JDK中對這個異常的解釋:

This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible.

當不允許這樣的修改時,可以通過檢測到物件的併發修改的方法來丟擲此異常。

(1) 原因解釋:

當我們對集合進行遍歷的時候,我們會獲取當前集合的迭代物件

//List為例,獲取集合的迭代物件
Iterator it = list.iterator();

這個迭代物件中,封裝了迭代器的方法與集合本身的一些方法,當我們在迭代中使用集合本身的add方法的時候,就產生了ConcurrentModificationException異常,通俗的說就是,在判斷成功後,集合中元素增加了,但是迭代器不清楚,所以就報錯,如果迭代器中含有這一種方法(假設),我們是用迭代器新增元素就不會有問題了。

針對這個問題,我們給出兩個解決方案

(2) 解決方案:

方式1:迭代器迭代元素,迭代器修改元素

我們假想如果Iterator迭代器中有新增功能就好了,但很遺憾並沒有,但是它的子介面ListIterator卻擁有這個功能

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

public class Demo2 {
    public static void main(String[] args) {
        //建立集合物件
        List list = new ArrayList();


        //儲存元素
        list.add("I");
        list.add("love");
        list.add("you");

        ListIterator lit = list.listIterator();
        while (lit.hasNext()) {
            String s = (String) lit.next();
            if ("love".equals(s)) {
                lit.add("❤");
            }
            System.out.print(s + " ");
        }
    }
}

//執行結果
I love you 

#####2:集合遍歷元素,集合修改元素(普通for)

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

public class Demo2 {
    public static void main(String[] args) {
        //建立集合物件
        List list = new ArrayList();

        //儲存元素
        list.add("I");
        list.add("love");
        list.add("you");

        for (int x = 0; x < list.size(); x++){
            String s = (String)list.get(x);
            if ("love".equals(s)){
                list.add("❤");
            }
            System.out.print(s + " ");
        }
    }
}

//執行結果
I love you ❤ 

兩者均可以解決併發修改異常的問題,但是通過執行結果也可以看出,方法一新增後,在本次遍歷中不會輸出新增的結果,而方法二卻可以。

補充:增強for迴圈實現將集合進行遍歷,也產生了併發修改異常,這是因為增強for在底層也是呼叫的集合本身的remove

(3) 總結:

在迭代器遍歷時,如果需要對集合進行增刪操作時,要呼叫迭代器本身的remove方法,或者選擇使用普通for進行遍歷

(三) Vector (過時,不推薦)

特有功能
	a:新增
		public void addElement(E obj)		--	add()
	b:獲取
		public E elementAt(int index)		--	get()
		public Enumeration<E> elements()	--  iterator()

(四) List案例練習

下面的案例題目個別來源於網路,我們來整理,書寫一下。

案例(一):集合巢狀儲存和遍歷元素的案例

需求:

我們班有學生,每一個學生是不是一個物件。所以我們可以使用一個集合表示我們班級的學生。ArrayList<Student>

但是呢,我們旁邊是不是還有班級,每個班級是不是也是一個 ArrayList<Student>

而我現在有多個ArrayList<Student>。也要用集合儲存,怎麼辦呢 ?

按照我們的想法就是這個樣子的:ArrayList<ArrayList<Student>>


案例 (二): 獲取10個1-20之間的隨機數,要求不能重複

package cn.bwh_02_List.ArrayList.RandomDemo;

import java.util.ArrayList;
import java.util.Random;
/*
 *  分析:
 *      A:建立產生隨機數的物件
 *      B:建立一個儲存隨機數的集合
 *      C:定義一個統計變數,從0開始
 *      D:判斷統計遍歷是否小於10
 *          小於10:
 *              若不存在:就新增,同時統計變數++
 *              若不存在:則不作處理
 *          大於10;
 *              不作處理
 *      E:遍歷集合
 */
public class ArrayDemo {
    public static void main(String[] args) {
        Random r = new Random();
        ArrayList<Integer> a = new ArrayList<Integer>();
        int count = 0;
        while (count < 10) {
            int number = r.nextInt(20) + 1;
            if (!a.contains(number)){
                a.add(number);
                count++;
            }
        }

        for (Integer i : a){
            System.out.print(i + " ");
        }

    }
}

案例 (三) 鍵盤錄入多個數據

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

package cn.bwh_02_List.ArrayList.InputMore;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;

/*
 *  分析:
 *      A:建立鍵盤錄入資料物件
 *      B:鍵盤錄入多個數據,不知道數量,所以用集合儲存
 *      C:以0結束——只要鍵盤錄入的資料是0,就不繼續錄入資料了
 *      D:把集合轉成陣列
 *      E:對陣列排序
 *      F:獲取該陣列中的最大索引的值
 */
public class AeeayDemo {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("請輸入資料");
        ArrayList<Integer> a = new ArrayList<Integer>();
        while (true) {
            int number = sc.nextInt();
            if (number != 0) {
                a.add(number);
            } else {
                break;
            }
        }

        Integer[] i = new Integer[a.size()];
        a.toArray(i);
        Arrays.sort(i);
        System.out.println(i[i.length - 1]);

    }
}

案例 (五) 登入註冊案例(使用集合)

package cn.bwh.pojo;

/**
 * 這是使用者基本描述類
 *
 * @author BWH_Steven
 * @version v1.0
 */

public class User {
    private String username;
    private String password;

    public User() {
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

package cn.bwh.dao;

import cn.bwh.pojo.User;

/**
 * 這是針對使用者進行操作的介面
 *
 * @author BWH_Steven
 * @version v1.0
 */
public interface UserDao {
    /**
     * 這是使用者登入功能
     *
     * @param username 使用者名稱
     * @param password 密碼
     * @return 返回登入是否成功
     */
    public abstract boolean isLogin(String username, String password);

    /**
     * 這是使用者註冊功能
     *
     * @param user 要註冊的使用者資訊
     */
    public abstract void regist(User user);
}

因為註冊的時候很可能還要填寫 例如地址,性別,愛好等等資訊(而登入功能的時候往往只需要使用者名稱和密碼),所以這個註冊功能傳進來的引數過多,因此用物件代替過多的引數,也就是說,通過傳遞物件(User user)包含眾多資訊避免了直接傳遞String username,password等等變數過多的問題

package cn.bwh.dao.impl;

import cn.bwh.dao.UserDao;
import cn.bwh.pojo.User;

import java.util.ArrayList;

/**
 * 這是使用者操作的具體實現類(集合類)
 *
 * @author BWH_Steven
 * @version v1.0
 */
public class UserDaoImpl implements UserDao {
    //為了多個集合能夠使用同一個集合,就把集合定義為成員變數
    //為了不讓外人看到,用private
    private static ArrayList<User> array = new ArrayList<User>();

    @Override
    public boolean isLogin(String username, String password) {

        //遍歷集合,獲取每一個使用者,並且判斷使用者的使用者名稱和密碼是否和傳遞過來的匹配
        boolean flag = false;

        for (User u : array) {
            if (u.getUsername().equals(username) && u.getPassword().equals(password)) ;
            flag = true;
            break;
        }

        return flag;
    }

    @Override
    public void regist(User user) {
        //把使用者資訊存入集合內
        array.add(user);
    }
}
package cn.bwh.test;

import cn.bwh.dao.UserDao;
import cn.bwh.dao.impl.UserDaoImpl;
import cn.bwh.pojo.User;

import java.util.Scanner;

/**
 * 使用者測試類
 *
 * @author BWH_Steven
 * @version v1.0
 */
public class UserTest {
    public static void main(String[] args) {
        //為了能夠到主介面
        while (true) {
            System.out.println("------------初次見面,請多指教------------");
            System.out.println("1 登入");
            System.out.println("2 註冊");
            System.out.println("3 退出");
            System.out.println("請輸入你的選擇");

            Scanner sc = new Scanner(System.in);
            //為了後面錄入資訊方便,所有的資料錄入均使用字串接受
            //Switch語句的多個地方要使用,物件就定義到外面
            String choicString = sc.nextLine();

            //呼叫註冊功能,使用多型
            UserDao ud = new UserDaoImpl();

            switch (choicString) {
                case "1":
                    System.out.println("----------------登入系統----------------");
                    System.out.println("請輸入使用者名稱");
                    String username = sc.nextLine();
                    System.out.println("請輸入密碼");
                    String password = sc.nextLine();

                    //呼叫登入功能
                    boolean flag = ud.isLogin(username, password);
                    if (flag) {
                        System.out.println("登陸成功");
                        System.exit(0);
                        //break; 這裡break結束的是switch
                    } else {
                        System.out.println("使用者名稱或者密碼錯誤,登入失敗");
                    }
                    break;
                case "2":
                    System.out.println("--------------新使用者註冊---------------");
                    System.out.println("請輸入使用者名稱");
                    String newUsername = sc.nextLine();
                    System.out.println("請輸入密碼");
                    String newPassword = sc.nextLine();

                    //把使用者名稱和密碼封裝到一個類中
                    User user = new User();
                    user.setUsername(newUsername);
                    user.setPassword(newPassword);

                    ud.regist(user);
                    System.out.println("註冊成功");
                    break;
                case "3":
                default:
                    System.out.println("謝謝使用,感謝你曾經來過過");
                    System.exit(0);
                    break;
            }

        }
    }
}
小結:

dao層主要連線資料庫,封裝增刪改查的資料庫語句

daoimpl是實現dao層方法的介面,所以可以把具體實現的方法寫在daoimpl中,dao層只寫方法名就可以。

Pojo代表簡單的Java物件

(五) List子類的特點(總結)

ArrayList:

​ 底層資料結構是陣列查詢快增刪慢

執行緒不安全效率高

Vector:

​ 底層資料結構是陣列查詢快增刪慢

執行緒安全效率低

LinkedList:

​ 底層資料結構是連結串列查詢慢增刪快

執行緒不安全效率高

使用具體情況

保證安全:Vector

​ (即使要安全,也不用這個,後面有替代的)

不保證安全:ArrayList或者LinkedList

查詢多:ArrayList

增刪多:LinkedList

結尾:

如果內容中有什麼不足,或者錯誤的地方,歡迎大家給我留言提出意見, 蟹蟹大家 !^_^

如果能幫到你的話,那就來關注我吧!(系列文章均會在公眾號第一時間更新)

在這裡的我們素不相識,卻都在為了自己的夢而努力 ❤

一個堅持推送原創Java技術的公眾號:理想二旬不止

相關推薦

Java集合框架——List介面

第三階段 JAVA常見物件的學習 集合框架——List介面 按照集合框架的繼承體系,我們先從Collection中的List介

第三十一講 集合框架——List介面

List介面概述 Collection介面有兩個子介面:List(列表)、Set(集),本文我們先重點學習List(列表)介面。查閱API,檢視List的介紹,我們可以發現以下這些話語: 有序的collection(也稱為序列)。此介面的使用者可以對列表中每個元素的插入位

Java集合框架頂層介面collectiion介面

如何使用迭代器 通常情況下,你會希望遍歷一個集合中的元素。例如,顯示集合中的每個元素。 一般遍歷陣列都是採用for迴圈或者增強for,這兩個方法也可以用在集合框架,但是還有一種方法是採用迭代器遍歷集合框架,它是一個物件,實現了Iterator 介面或ListIterator介面。 迭代器,使你能夠通過迴

Java————集合框架——list

目錄 (1)增加 (5)刪除 (6)替換 四:遍歷。 一:List介面(使用的初步介紹) 1:List集合的特徵 ——:第一個是有序; ——:第二個集合可以重複; (1)Ar

JAVA集合框架——List

List List介紹 List體系結構 ArrayList LinkedList List介紹 list集合可以裝任意型別,裡面的資料有序且可以重複 List體系結構 ArrayList

Java集合框架介面和類層次關係結構圖

集合框架中的核心介面  介面 說明 實體類 Collection 一種基本介面,它定義了一些普通操作,通過這些操作,可以將一個物件集合當作一個獨立單元來對其進行存放和處理 Set Set介面擴充套件了Collection介面,用

Java集合框架List,Map,Set, Queue介紹

Java Collections Framework是Java提供的對集合進行定義,操作,和管理的包含一組介面,類的體系結構。 Collection介面     Collection是最基本的集合介面,一個Collection代表一組Object的集合,這些Objec

java集合框架-Map介面

map是一個鍵值對對映物件,一個map不能包含重複的key,每一個key都能唯一的對映到至多一個value. 這個介面替代了Dictonary類。map介面提供了三種集合檢視,它允許將map的內容視為一個鍵集合、值集合或者鍵值對映集合。map的順序被定義為集合檢視的迭代器返

Java集合框架List+Set+Map基本操作

一、List集合  List的特徵是其元素以線性方式儲存,集合中可以存放重複物件。  List介面主要實現類包括:   ArrayList : 代表長度可以改變得陣列。可以對元素進行隨機的訪問,向

JAVA集合框架Collection介面和Map介面主要知識總結

 Java集合框架下有兩個重要的介面,一個是Collection介面,一個是Map介面。 一、Collection介面 Collection介面中又有三個子介面,分別是List(序列),Queue(佇列),Set(集), 其中常用的有List和Set; List和Qu

java集合框架介面概述

java平臺的集合介面所定義的函式是通用的,例如:Collection<E>,但是實現可以選擇的支援相關操作,當執行沒有被支援的操作時,拋UnsupportedOperationException.異常,有幸的時,java平臺的各種集合都實現了相關操作。附上集合核

Java集合框架——Set介面

List集合的特點是有序的,可重複的,是不是存在這一種無序,且能保證元素唯一的集合呢?(HashSet )這就涉及到我們今天所要講的Set集合 Set可以理解為行為不同的Collection (一) 概述及功能 (1) 概述 Collection List —— 有序(儲存順序和取出順序一致),可重

Java集合框架——Map介面

在實際需求中,我們常常會遇到這樣的問題,在諸多的資料中,通過其編號來尋找某一些資訊,從而進行檢視或者修改,例如通過學號查詢學生資訊。今天我們所介紹的Map集合就可以很好的幫助我們實現這種需求 (一) 概述及功能 (1) 概述 Map是一種儲存元素對的集合(元素對分別稱作 鍵 和 值 也稱鍵值對)它將鍵對

Java 知識點整理-9.Java集合框架 集合概述+Collection介面+Iterator介面+迭代器+List介面+併發修改異常+ListIterator介面+Vector類+List子類

本章會用大量程式碼做具體演示。統一說明:返回型別E在JDK1.5之前是Object,1.5之後等泛型再講。 先介紹一個偶然發現的快捷鍵和一個很實用的快捷鍵: Alt + Shift + N 快速呼叫建立選單。直接按開頭的首字母進行建立即可,某些時候感覺比Ctrl + N更快捷。

Java集合框架官方教程(1):Collection/Set/List介面

概述   一個集合,即collection,有時也被稱為一個容器,是將多個元素聚整合一個單元的物件。Collections常被用來儲存、檢索、操縱聚集資料以及聚集資料間的通訊。一般來說,Collections表示一組自然類群的資料項,比如一手撲克牌、一個信箱(由很多信件

Java學習筆記——淺談數據結構與Java集合框架(第一篇、List

技術分享 emp 鏈表 adc 下標 -c nod nal integer 橫看成嶺側成峰,遠近高低各不同。不識廬山真面目,只緣身在此山中。               ——蘇軾 這一塊兒學的是雲裏霧裏,咱們先從簡單的入手。逐漸的撥開迷霧見太陽。本次先做List集合的三

Java集合框架學習(一)List

collect 有序集合 original package images 遍歷 容量 exp 子類 先附一張Java集合框架圖。 從上面的集合框架圖可以看到,Java集合框架主要包括兩種類型的容器,一種是集合(Collection),存儲一個元素集合,另一種是圖(M

JAVA-初步認識-常用對象API(集合框架-List集合的常用方法)

技術分享 java 修改 class cti 不同 bubuko span 接下來 一. 現在重點學習一下List,List是Collection的子接口,那麽Collection的方法,List都具備,共性方法就不講述了。 講述一下List中特有的方法,這些特有方法的共性

JAVA-初步認識-常用對象API(集合框架-List常用子類的特點)

只需要 大小 虛線 版本 技術 鏈接 bubuko 就是 編號 一. 凡是虛線框都是接口,我們真正在使用的時候,用的是接口中的子類, List接口中,有一堆子類,是我們開發中常用的容器。ArrayList,LinkList,Vecter這三個算是開發中比較常用的。 (l

Java基礎知識(JAVA集合框架List與Set)

開發 如果 表數 特點 必須 加鎖 以及 stringbu 不可 List和Set概述數組必須存放同一種元素。StringBuffer必須轉換成字符串才能使用,如果想拿出單獨的一個元素幾乎不可能。數據有很多使用對象存,對象有很多,使用集合存。 集合容器因為內部