最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java基礎(chǔ)-數(shù)組擴(kuò)容詳解

 更新時(shí)間:2021年08月20日 16:40:03   作者:haijiao12138  
這篇文章主要介紹了Java數(shù)組擴(kuò)容實(shí)現(xiàn)方法解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

數(shù)組與鏈表的比較:

  • 數(shù)組通過下標(biāo)訪問的話是O(1)
  • 數(shù)組一旦聲明 長度就是固定的
  • 數(shù)組的數(shù)據(jù)是物理邏輯均連續(xù)的
  • 鏈表增刪要快一些, 數(shù)組遍歷快一些
  • 長度一定的話, 數(shù)組的存儲(chǔ)空間比鏈表要小

ArrayList:

ArrayList是List接口的實(shí)現(xiàn)類,它是支持根據(jù)需要而動(dòng)態(tài)增長的數(shù)組;java中標(biāo)準(zhǔn)數(shù)組是定長的,在數(shù)組被創(chuàng)建之后,它們不能被加長或縮短。這就意味著在創(chuàng)建數(shù)組時(shí)需要知道數(shù)組的所需長度,但有時(shí)我們需要?jiǎng)討B(tài)程序中獲取數(shù)組長度。ArrayList就是為此而生的。

擴(kuò)容機(jī)制發(fā)生在add()方法調(diào)用的時(shí)候;

  public boolean add(E e) {
       //擴(kuò)容
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

該行代碼ensureCapacityInternal()是用來擴(kuò)用的,形參是最小擴(kuò)容量,進(jìn)入該方法后:

    private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

通過方法calculateCapacity(elementData, minCapacity)獲取:

   private static int calculateCapacity(Object[] elementData, int minCapacity) {
        //如果傳入的是個(gè)空數(shù)組則最小容量取默認(rèn)容量與minCapacity之間的最大值
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

使用 ensureExplicitCapacity方法可以判斷是否需要擴(kuò)容:

 private void ensureExplicitCapacity(int minCapacity) {
          modCount++;
          // 如果最小需要空間比elementData的內(nèi)存空間要大,則需要擴(kuò)容
          if (minCapacity - elementData.length > 0)
              //擴(kuò)容
              grow(minCapacity);
      }

需要擴(kuò)容,進(jìn)入ArrayList擴(kuò)容的關(guān)鍵方法grow():擴(kuò)大為原來的1.5倍;

 private void grow(int minCapacity) {
          // 獲取到ArrayList中elementData數(shù)組的內(nèi)存空間長度
          int oldCapacity = elementData.length;
         // 擴(kuò)容至原來的1.5倍
         int newCapacity = oldCapacity + (oldCapacity >> 1);
         // 再判斷一下新數(shù)組的容量夠不夠,夠了就直接使用這個(gè)長度創(chuàng)建新數(shù)組,
          // 不夠就將數(shù)組長度設(shè)置為需要的長度
         if (newCapacity - minCapacity < 0)
             newCapacity = minCapacity;
         //若預(yù)設(shè)值大于默認(rèn)的最大值檢查是否溢出
         if (newCapacity - MAX_ARRAY_SIZE > 0)
             newCapacity = hugeCapacity(minCapacity);
         // 調(diào)用Arrays.copyOf方法將elementData數(shù)組指向新的內(nèi)存空間時(shí)newCapacity的連續(xù)空間
         // 并將elementData的數(shù)據(jù)復(fù)制到新的內(nèi)存空間
         elementData = Arrays.copyOf(elementData, newCapacity);
     }
復(fù)制代碼

至此得出ArrayList擴(kuò)容的本質(zhì)是計(jì)算出新的擴(kuò)容數(shù)組的size后實(shí)例化,并將原有數(shù)組內(nèi)容復(fù)制到新數(shù)組中去。

LinkedList:

鏈表實(shí)現(xiàn)擴(kuò)容,直接在尾指針后面加入新的元素即可。

實(shí)現(xiàn)LinkedList:LinkedList的底層實(shí)現(xiàn)是鏈表。更深理解是一個(gè)雙向鏈表。

節(jié)點(diǎn)代碼:

//節(jié)點(diǎn)
public class Node {
	Node previous;//前繼,指向前一個(gè)Node
	Object data;//節(jié)點(diǎn)數(shù)據(jù)
	Node next;//后繼,指向后一個(gè)Node
	public Node() {
	}
	public Node(Node previous, Object data, Node next) {
		super();
		this.previous = previous;
		this.data = data;
		this.next = next;
	} 
}

初始化MyLinkedList:

public class MyLinkedList {
	private Node first;//首節(jié)點(diǎn)
	private Node last;//尾節(jié)點(diǎn)
	private int size;//鏈表大小
	public MyLinkedList() {
		first = null;
		last = null;
		size = 0;
	}
}

尾部添加,實(shí)現(xiàn)add(Object obj)方法:

public void add(Object obj){
		Node node = new Node(null,null,null);
		if(first==null){//first=null,說明LinkedList中沒有一個(gè)節(jié)點(diǎn)
			node.data = obj;
			first = node;
			last = node;//第一個(gè)節(jié)點(diǎn)和最后一個(gè)節(jié)點(diǎn)都是node
			size++;
		}else{
			node.data = obj;
			last.next = node;//和最后一個(gè)連接起來
			node.previous = last;
			last = node;//當(dāng)前節(jié)點(diǎn)變?yōu)槟┪补?jié)點(diǎn)
			size++;
		}

現(xiàn)get(int index)方法,獲取index處的節(jié)點(diǎn)并返回Node:

使用循環(huán),遍歷鏈表:

public Node get(int index) {
		RangeCheck(index);
		Node temp = null;
		if(index < (size>>1)){//改進(jìn)的遍歷方法,右移運(yùn)算符的巧用
			temp = first;
			for(int i=0;i<index;i++){
				temp = temp.next;
			}
		}else {
			temp = last;
			for(int i=size-1;i>index;i--){
				temp = temp.previous;
			}
		}
		return temp;
	}

任意位置插入,實(shí)現(xiàn)add(int index,Object obj)方法:插入的步驟注意順序,不要產(chǎn)生斷鏈。

public void add(int index,Object obj) {
		RangeCheck(index);//對(duì)傳入的索引必須進(jìn)行檢查,判斷是否越界
		Node node = new Node(null,null,null);
		node.data = obj;
		Node node2=first;
		for(int i=0;i<index-1;i++){
			node2 = node2.next;
		}
		node.next = node2.next;
		node2.next.previous=node;
		node2.next = node;
		node.previous=node2;
		size++;
	}

RangeCheck():

private void RangeCheck(int index) {
		if(index<0||index >= size){
			throw new IndexOutOfBoundsException("IndexOutOfBounds"+index);//不合法則拋出異常
		}
	}

實(shí)現(xiàn)remove(Object obj)方法:

public boolean remove(Object obj) {
		Node node = first;
		if(obj==null){
			while(node!=null){
				if(node.data==null){
					removefast(node);
					return true;
				}
				node = node.next;
			}
		}else {
			while(node!=null){
				if(obj.equals(node.data)){
					removefast(node);
					return true;
				}
				node = node.next;
			}
		}
		return false;
	}
	private void removefast(Node node){
		node.previous.next=node.next;
		size--;
		node.data=null;
		node.previous = node.next = null;
	}

實(shí)現(xiàn)set(int index,Object obj)方法:

public Object set(int index,Object obj) {
		Node node = get(index);
		Object oldObject=node.data;
		node.data = obj;
		return oldObject;
	}

總結(jié)

本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • MyBatis實(shí)現(xiàn)注冊(cè)及獲取Mapper

    MyBatis實(shí)現(xiàn)注冊(cè)及獲取Mapper

    本文主要介紹了MyBatis實(shí)現(xiàn)注冊(cè)及獲取Mapper,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-03-03
  • 關(guān)于Java8新特性O(shè)ptional類的詳細(xì)解讀

    關(guān)于Java8新特性O(shè)ptional類的詳細(xì)解讀

    Optional類是一個(gè)容器類,它可以保存類型T的值,代表這個(gè)值存在?;蛘邇H僅保存null,表示這個(gè)值不存在,原來用 null 表示一個(gè)值不存在,現(xiàn)在Optional 可以更好的表達(dá)這個(gè)概念。并且可以避免空指針異常,需要的朋友可以參考下
    2023-05-05
  • 一文搞懂Java的ThreadPoolExecutor原理

    一文搞懂Java的ThreadPoolExecutor原理

    都說經(jīng)典的就是好的,這句話放在Java的ThreadPoolExecutor上那是一點(diǎn)都沒錯(cuò),像現(xiàn)在數(shù)據(jù)庫連接的池化實(shí)現(xiàn),或者像Tomcat這種WEB服務(wù)器的線程管理,處處都有著ThreadPoolExecutor的影子,本篇文章將結(jié)合源碼實(shí)現(xiàn),對(duì)ThreadPoolExecutor的原理進(jìn)行一個(gè)深入學(xué)習(xí)
    2023-06-06
  • 詳解Java中String,StringBuffer和StringBuilder的使用

    詳解Java中String,StringBuffer和StringBuilder的使用

    這篇文章主要為大家詳細(xì)介紹了Java中String,StringBuffer和StringBuilder三者的區(qū)別以及使用,文中的少了講解詳細(xì),感興趣的可以了解一下
    2022-07-07
  • Java漏桶算法的簡單代碼實(shí)例

    Java漏桶算法的簡單代碼實(shí)例

    這篇文章主要介紹了Java漏桶算法的簡單代碼實(shí)例,漏桶算法的意義在于能夠平滑請(qǐng)求,不給下游服務(wù)造成過大壓力,特別適用于突發(fā)流量或者定時(shí)任務(wù)拉取大量數(shù)據(jù)時(shí),需要處理大量數(shù)據(jù)或者請(qǐng)求的場景,需要的朋友可以參考下
    2024-01-01
  • Java獲取一個(gè)類的隱藏屬性的幾種方法

    Java獲取一個(gè)類的隱藏屬性的幾種方法

    這篇文章主要討論了在Java中如何訪問或修改類的私有字段,包括使用公共的getter和setter方法、反射、繼承和序列化機(jī)制,文章強(qiáng)調(diào)了尊重類的封裝性,感興趣的小伙伴跟著小編一起來看看吧
    2025-02-02
  • Java實(shí)現(xiàn)簡單連連看游戲

    Java實(shí)現(xiàn)簡單連連看游戲

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)簡單連連看游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • MyBatis圖文并茂講解注解開發(fā)多對(duì)多查詢

    MyBatis圖文并茂講解注解開發(fā)多對(duì)多查詢

    這篇文章主要介紹了SpringBoot中Mybatis注解多對(duì)多查詢的實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • Java利用Socket和IO流實(shí)現(xiàn)文件的上傳與下載

    Java利用Socket和IO流實(shí)現(xiàn)文件的上傳與下載

    本文主要介紹了Java利用Socket和IO流實(shí)現(xiàn)文件的上傳與下載,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • IDEA性能優(yōu)化方法解決卡頓問題

    IDEA性能優(yōu)化方法解決卡頓問題

    本文主要介紹了如何在不升級(jí)電腦配置的情況下通過修改IntelliJIDEA的設(shè)置來優(yōu)化其性能,從而提升開發(fā)效率
    2024-12-12

最新評(píng)論

通山县| 冕宁县| 恩平市| 巍山| 张北县| 大渡口区| 米林县| 广南县| 奎屯市| 德钦县| 丹江口市| 深水埗区| 北辰区| 武邑县| 富民县| 遂平县| 乌拉特后旗| 利辛县| 沙河市| 唐山市| 察雅县| 肥西县| 松原市| 平舆县| 东城区| 虞城县| 威宁| 龙山县| 晋城| 冕宁县| 黑山县| 隆昌县| 佛教| 望城县| 蛟河市| 来凤县| 泽普县| 普陀区| 琼海市| 桦川县| 宁乡县|