2020-05-15

項目優(yōu)化和List集合

1、項目優(yōu)化

1.1 分析當前情況

問題

????數(shù)據(jù)存儲是數(shù)組形式,數(shù)據(jù)類型明確。復(fù)用度較低枕荞。

需求

????Student操作使用的代碼,StudentManager想要操作考慮一個復(fù)用度問題搞动。不管更換什么數(shù)據(jù)類型躏精, 都是可以直接使用。

解決問題

????1. 泛型

????2. 數(shù)組不能使用泛型鹦肿,但是這個數(shù)組又需要保存各式各樣的數(shù)據(jù)

????????Object

1.2 使用泛型和Object優(yōu)化項目

package com.qfedu.student.system.util;

import com.qfedu.student.system.myexception.IllegalCapacityException;

import com.qfedu.student.system.myexception.OverflowMaxArraySizeException;

/**

* 自定義數(shù)據(jù)存儲工具矗烛,MyList用于存儲代碼中操作的數(shù)據(jù)

*

* @author Anonymous

*

* @param <E> 使用泛型滿足更多的情況

*/

public class MyList<E> {

????/**

????* 保存數(shù)據(jù)的底層Object數(shù)組,可以保存任意數(shù)據(jù)類型箩溃,但是在操作方法是會

????* 對操作的數(shù)據(jù)類型瞭吃,通過泛型進行約束操作

????*/

????private Object[] elementData = null;

????/**

????* DEFAULT_CAPACITY 默認容量碌嘀,這里是一個帶有名字的常量

????*/

????private static final int DEFAULT_CAPACITY = 10;

????/**

????* 數(shù)組最大容量,是int類型最大值 - 8?

????*/

????private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

????/**

????* 當前底層Object數(shù)組中有效元素個數(shù)

????*/

????private int size = 0;

????/**

????* 無參數(shù)構(gòu)造方法歪架,使用DEFAULT_CAPACITY約束初始化容量

????*/

????public MyList() {

????????elementData = new Object[DEFAULT_CAPACITY];

????}

????/**

????* 提供給用戶可以指定初始化容量的操作方法

????*

????* @param initCapacity 用戶指定的初始化容量股冗,但是必須在合理范圍以內(nèi)

????* @throws IllegalCapacityException 用戶指定的初始化容量超出范圍

????*/

????public MyList(int initCapacity) throws IllegalCapacityException {

????????if (initCapacity < 0 || initCapacity > MAX_ARRAY_SIZE) {

????????????throw new IllegalCapacityException("Input Parameter is Invalid!");

????????}

????????elementData = new Object[initCapacity];

????}

????/**

????* 添加方法,添加在創(chuàng)建MyList對象是約束的具體數(shù)據(jù)類型

????*

????* @param e 通過泛型約束的具體數(shù)據(jù)類型

????* @return 添加成功返回true, 否則返回false

????* @throws OverflowMaxArraySizeException

????*/

????public boolean add(E e) throws OverflowMaxArraySizeException {

????????if (size == elementData.length) {

????????????// 添加操作是一個元素和蚪,最小容量要求就是在原本的數(shù)組容量之上 + 1

????????????grow(size + 1);

????????}

????????elementData[size] = e;

????????size += 1;

????????return true;

????}

????/**

????* 刪除保存在MyList中的指定元素

????*

????* @param obj 用戶指定的元素

????* @return 刪除成功返回true止状,否則返回false

????*/

????public boolean remove(Object obj) {

????????int index = indexOf(obj);

????????return remove(index);

????}

????/**

????* 刪除指定下標的的元素

????*

????* @param index 用戶指定的下標位置

????* @return 刪除成功返回true,否則返回false

????*/

????public boolean remove(int index) {

????????if (index < 0 || index >= size) {

????????????return false;

????????}

????????for (int i = index; i < size - 1; i++) {

????????????elementData[i] = elementData[i + 1];

????????}

????????// 原本最后一個有效元素位置賦值為null

????????elementData[size - 1] = null;

????????// 有效元素個數(shù) - 1

????????size -= 1;

????????return true;

????}

????/**

????* 根據(jù)指定元素攒霹,找出對應(yīng)的下標位置怯疤,沒有找到返回-1

????*

????* @param obj 用戶傳入的元素

????* @return 找到元素返回值大于等于0,沒有找到返回-1

????*/

????public int indexOf(Object obj) {

????????int index = -1;

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

????????????if (obj.equals(elementData[i])) {

????????????????index = i;

????????????????break;

????????????}

????????}

????????return index;

????}

/**

* 替換修改方法剔蹋,使用指定元素替換指定下標的元素

*

* @param index 指定的下標位置,約束在合理范圍以內(nèi)

* @param e 泛型約束的指定數(shù)據(jù)類型辅髓,保證數(shù)據(jù)類型一致化

* @return 被替換掉的元素泣崩。如果沒有被替換的元素,返回null

*/

????public E set(int index, E e) {

????????if (index < 0 || index >= size) {

????????????return null;

????????}

????????// 取出原本的元素

????????E temp = (E) elementData[index];

????????elementData[index] = e;

???????return temp;

????}

????/**

????* 返回當前MyList底層數(shù)組中保存有效元素個數(shù)是多少個

????*

????* @return 返回當前MyList底層數(shù)組中有效元素個數(shù)

????*/

????public int size() {

????????return size;

????}

????/**

????* 判斷當前MyList中是否為空

????*

????* @return 如果是空返回true洛口,否則返回false

????*/

????public boolean isEmpty() {

????????return 0 == size;

????}

????/**

????* 判斷指定元素是否在MyList底層數(shù)組中存在

????*

????* @param obj 用戶指定的元素

????* @return 存在返回true矫付,不存在返回false

????*/

????public boolean contains(Object obj) {

????????return indexOf(obj) > -1;

????}

????/**

????* 根據(jù)指定下標位置,獲取對應(yīng)的元素

????*

????* @param index 指定下標位置

????* @return 對應(yīng)的元素第焰,如果不存在买优,返回null

????*/

????public E get(int index) {

????????return index > -1 && index < size ? (E) elementData[index] : null;

????}

????/**

????* 類內(nèi)私有化方法,用于在添加元素過程中挺举,出現(xiàn)當前底層數(shù)組容量不足的情況下 對底層數(shù)組進行擴容操作杀赢,滿足使用要求

????*

????* @param minCapacity 添加操作要求的最小容量

????* @throws OverflowMaxArraySizeException 數(shù)組容量超出最大范圍

????*/

????private void grow(int minCapacity) throws OverflowMaxArraySizeException {

????????// 1. 獲取原數(shù)組容量

????????int oldCapacity = elementData.length;

????????// 2. 計算得到新數(shù)組容量,新數(shù)組容量大約是原數(shù)組容量的1.5倍

????????// >> 1 右移一位 該操作是二進制操作 等價于 / 2 效率略高

????????int newCapacity = oldCapacity + (oldCapacity >> 1);

???????// 3. 判斷新數(shù)組容量是否滿足最小容量要求

???????if (minCapacity > newCapacity) {

???????????newCapacity = minCapacity;

????????}

????????// 4. 判斷當前容量是否超出了MAX_ARRAY_SIZE

???????if (newCapacity > MAX_ARRAY_SIZE) {

????????????throw new OverflowMaxArraySizeException("Overflow MAX_ARRAY_SIZE");

????????}

????????// 5. 創(chuàng)建新數(shù)組

????????Object[] temp = new Object[newCapacity];

????????// 6. 數(shù)據(jù)拷貝

????????for (int i = 0; i < oldCapacity; i++) {

????????????temp[i] = elementData[i];

????????}

????????// 7. 使用allStus保存新數(shù)組首地址

????????elementData = temp;

????}

}

2湘纵、List接口

2.1 List接口概述

List接口特征:

????1. 數(shù)據(jù)存儲可重復(fù)脂崔。

????2. 有序,添加順序和保存順序一致梧喷。

--| ArrayList<E>

????可變長數(shù)組

--| LinkedList<E>

????雙向鏈表

--| Vector<E>

????線程安全的可變長數(shù)組

2.2 List常用方法

????boolean add(E e);

????????List接口繼承Collection接口 add方法砌左,使用操作和Collection一致,并且這里采用的添加方式是【尾插法】

????boolean add(int index, E e);

????????List接口【特有方法】铺敌,在指定位置汇歹,添加指定元素。

????boolean addAll(Collection<? extends E> c);

????????List接口繼承Collection接口 addAll方法偿凭,使用操作和Collection一致产弹,并且這里采用的添加方式是【尾插法】

????boolean addAll(int index, Collection<? extends E> c);

????????List接口【特有方法】,在指定下標位置弯囊,添加另一個集合中所有內(nèi)容

????E remove(int index);

????????List接口【特有方法】取视,獲取指定下標位置的元素硝皂。

????boolean remove(Object obj);

????????List接口繼承Collection接口方法。刪除集合中的指定元素

????boolean removeAll(Collection<?> c);

????????List接口繼承Collection接口方法作谭。刪除當前集合中和參數(shù)集合重復(fù)元素

????boolean retainAll(Collection<?> c);

????????List接口繼承Collection接口方法稽物。保留當前集合中和參數(shù)集合重復(fù)元素

????clear();

????????List接口繼承Collection接口方法。清空整個集合中的所有元素

????E set(int index, E e);

????????List接口【特有方法】折欠,使用指定元素替代指定下標的元素贝或,返回值是被替換的元素

????int size();

????????List接口繼承Collection接口方法。獲取集合中有效元素個數(shù)

????boolean isEmpty();

????????List接口繼承Collection接口方法锐秦。判斷當前集合是否為空

????boolean contains(Object obj);

????????List接口繼承Collection接口方法咪奖。判斷指定元素是否包含在當前集合中

????boolean containsAll(Collection<?> c);

????????List接口繼承Collection接口方法。判斷參數(shù)集合是不是當前集合在子集合

????Object[] toArray();

????????List接口繼承Collection接口方法酱床。獲取當前集合中所有元素Object數(shù)組

????E get(int index);

????????List接口【特有方法】羊赵。獲取指定下標對應(yīng)的元素

????List<E> subList(int fromIndex, int toIndex);

????????List接口【特有方法】。獲取當前集合指定子集合扇谣,從fromIndex開始昧捷,到toIndex結(jié)束。fromIndex <= 范圍 < toIndex

????int indexOf(Object obj);

????????List接口【特有方法】罐寨。獲取指定元素在集合中第一次出現(xiàn)位置

????int lastIndexOf(Object obj);

????????List接口【特有方法】靡挥。獲取指定元素在集合中最后一次出現(xiàn)的位置

2.3 List接口常用方法演示

package com.qfedu.a_list;

import java.util.ArrayList;

import java.util.List;

public class Demo1 {

????public static void main(String[] args) {

????????/*

????????* List<E>是一個接口,沒有自己的類對象鸯绿,這里使用List接口的

????????* 實現(xiàn)類ArrayList來演示代碼跋破。

????????*/

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

????????/*

????????* 添加方法演示

????????*/

????????list.add("濃郁咖啡摩卡");

????????list.add("濃郁咖啡拿鐵");

????????list.add("焦糖瑪奇朵");

????????list.add("摩卡可可碎星冰樂");

????????list.add("可可卡布奇諾");

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

????????list.add(3, "美式咖啡");

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

????????List<String> list2 = new ArrayList<String>();

????????list2.add("肥宅快樂水");

????????list2.add("芬達");

????????list2.add("雪碧");

????????list2.add("冰峰");

????????list.addAll(4, list2);

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

????????/*

????????* 刪除方法

????????*/

????????String remove = list.remove(1);

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

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

????????// 條件過濾,這里使用了JDK1.8 新特征 Lambda表達式和函數(shù)式接口 【后期知識點】

????????list.removeIf((str) -> str.length() > 4);

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

????}

}

package com.qfedu.a_list;

import java.util.ArrayList;

import java.util.List;

public class Demo1 {

????public static void main(String[] args) {

????????/*

????????* List<E>是一個接口瓶蝴,沒有自己的類對象毒返,這里使用List接口的

????????* 實現(xiàn)類ArrayList來演示代碼。

????????*/

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

????????/*

????????* 添加方法演示

????????*/

????????list.add("濃郁咖啡摩卡");

????????list.add("濃郁咖啡拿鐵");

????????list.add("焦糖瑪奇朵");

????????list.add("摩卡可可碎星冰樂");

????????list.add("可可卡布奇諾");

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

????????list.add(3, "美式咖啡");

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

????????List<String> list2 = new ArrayList<String>();

????????list2.add("肥宅快樂水");

????????list2.add("芬達");

????????list2.add("雪碧");

????????list2.add("冰峰");

????????list.addAll(4, list2);

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

????????/*

????????* 刪除方法

????????*/

????????String remove = list.remove(1);

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

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

????????// 條件過濾舷手,這里使用了JDK1.8 新特征 Lambda表達式和函數(shù)式接口 【后期知識點】

????????list.removeIf((str) -> str.length() > 4);

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

????}

}

3. ArrayList【重點】

3.1 ArrayList概述

ArrayList是在Java中集合非常重要的一個組裝饿悬,基于數(shù)組完成的數(shù)據(jù)結(jié)構(gòu)【鬯可變長數(shù)組操作=铺瘛!蝎宇!

底層保存數(shù)據(jù)的是一個Object類型數(shù)組弟劲。

ArrayList使用的方法都是List接口中的方法,有兩個需要了解的成員方法:

????ensureCapacity();

????????判斷方法姥芥,用于確定當前底層數(shù)組的容量是否滿足當前操作的需求兔乞。

????trimToSize();

????????節(jié)省空間,將底層數(shù)組的容量縮容至有效元素個數(shù)

需要掌握的是關(guān)于ArrayList效率相關(guān)的問題。和細節(jié)問題

3.2 細節(jié)問題

1. DEFAULT_CAPACITY

????默認容量 private static final int DEFAULT_CAPACITY = 10;

????在調(diào)用ArrayList無參數(shù)構(gòu)造方法是庸追,才會使用DEFAULT_CAPACITY霍骄,作為底層Object數(shù)組的初始化容量。如果用戶指定調(diào)用的是帶有初始化底層Object數(shù)組容量的構(gòu)造方法淡溯,會根據(jù)用戶指定的容量創(chuàng)建對一個ArrayList集合读整。】

2. MAX_ARRAY_SIZE ==> Integer.MAX_VALUE - 8;

????int[] arr = new int[10];

????arr.length 是什么??? 數(shù)組容量

????這里是一個方法還是屬性??? 屬性

????屬性是不是成員變量??? 是

????成員變量是否需要占用內(nèi)存??? 需要

????new數(shù)組占用的空間什么地方??? 堆區(qū)

????arr.length 屬性是不是也在堆區(qū)??? 是

????為什么 - 8???

????因為在數(shù)組中存在很多屬性咱娶,length只是眾多屬性中的一個米间,在創(chuàng)建數(shù)組使用的過程中,需要留有內(nèi)存空間用于保存數(shù)組中屬性膘侮。

3.3 效率問題

ArrayList特征:

????增刪慢

????????增加慢

????????????1. 數(shù)組當前容量無法滿足添加操作屈糊,需要進行g(shù)row擴容方法執(zhí)行,在擴容方法中琼了,存在數(shù)組創(chuàng)建逻锐,數(shù)組數(shù)據(jù)拷貝。非常浪費時間雕薪,而且浪費內(nèi)存昧诱。

????????????2. 數(shù)組在添加數(shù)據(jù)的過程中,存在在指定位置添加元素蹦哼,從指定位置開始鳄哭,之后的元素整體向后移動要糊。

????????刪除慢

????????????1. 刪除數(shù)據(jù)之后纲熏,從刪除位置開始,之后的元素整體向前移動锄俄,移動過程非常浪費時間

????????????2. 刪除操作會導(dǎo)致數(shù)據(jù)空間的浪費局劲,內(nèi)存的浪費

????查詢快

????????ArrayList底層是一個數(shù)組結(jié)構(gòu),在查詢操作的過程中奶赠,是按照數(shù)組+下標的方式來操作對應(yīng)的元素鱼填,數(shù)組+下標方式可以直接獲取對應(yīng)的空間首地址,CPU訪問效率極高毅戈。

3.4 【補充知識點苹丸,內(nèi)存地址】

內(nèi)存地址概念:

????[計算機原理]

????計算機中為了更好的使用內(nèi)存,操作程序苇经,完成代碼赘理。將內(nèi)存按照最小單位,進行編號處理扇单。

????最小單位: 字節(jié) byte

????從編號為0內(nèi)存開始商模,到內(nèi)存的最大值。地址的展示方式是十六進制。

3.5 【補充知識點 內(nèi)存地址對于CPU有什么關(guān)系】

代碼實際運行:

????CPU就是根據(jù)內(nèi)存地址施流,可以直達內(nèi)存所在區(qū)域响疚,執(zhí)行對應(yīng)代碼。精準而優(yōu)雅瞪醋,速度非撤拊危快!L苏隆杏糙!

3.6 【補充知識點 數(shù)組空間地址關(guān)系】


3.7【補充知識點 null到底是什么】

null 是計算機中非常特殊的一塊內(nèi)存。該內(nèi)存編號 0x0000 0000

該內(nèi)存受到系統(tǒng)保護

????不只是電腦蚓土,包括手機宏侍,iPad,智能設(shè)備蜀漆,只要存在計算機基本結(jié)構(gòu)的設(shè)備上都存在null 編號為0x0內(nèi)存谅河。大小一個字節(jié)該內(nèi)存不能讀取任何數(shù)據(jù),也不能寫入任何數(shù)據(jù)确丢。一旦操作绷耍,程序直接被系統(tǒng)殺死

????Kill -9

????一般用于引用數(shù)據(jù)類型的初始化,利用開發(fā)中關(guān)于null的異常鲜侥,輔助找出代碼中的錯誤褂始。

????NullPointerException.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市描函,隨后出現(xiàn)的幾起案子崎苗,更是在濱河造成了極大的恐慌,老刑警劉巖舀寓,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件胆数,死亡現(xiàn)場離奇詭異,居然都是意外死亡互墓,警方通過查閱死者的電腦和手機必尼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來篡撵,“玉大人判莉,你說我怎么就攤上這事∮” “怎么了券盅?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長斑司。 經(jīng)常有香客問我渗饮,道長但汞,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任互站,我火速辦了婚禮私蕾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘胡桃。我一直安慰自己踩叭,他們只是感情好,可當我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布翠胰。 她就那樣靜靜地躺著容贝,像睡著了一般。 火紅的嫁衣襯著肌膚如雪之景。 梳的紋絲不亂的頭發(fā)上斤富,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天,我揣著相機與錄音锻狗,去河邊找鬼满力。 笑死,一個胖子當著我的面吹牛轻纪,可吹牛的內(nèi)容都是我干的油额。 我是一名探鬼主播,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼刻帚,長吁一口氣:“原來是場噩夢啊……” “哼潦嘶!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起崇众,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤掂僵,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后校摩,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體看峻,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡阶淘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年衙吩,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片溪窒。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡坤塞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出澈蚌,到底是詐尸還是另有隱情摹芙,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布宛瞄,位于F島的核電站浮禾,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜盈电,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一蝴簇、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧匆帚,春花似錦熬词、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至嚎幸,卻和暖如春颜矿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嫉晶。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工或衡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人车遂。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓封断,卻偏偏與公主長得像,于是被迫代替她去往敵國和親舶担。 傳聞我的和親對象是個殘疾皇子坡疼,可洞房花燭夜當晚...
    茶點故事閱讀 45,092評論 2 355