日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

java提高篇之数组(2)

發(fā)布時(shí)間:2025/3/21 编程问答 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java提高篇之数组(2) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前面一節(jié)主要介紹了數(shù)組的基本概念,對(duì)什么是數(shù)組稍微深入了一點(diǎn)點(diǎn),在這篇博文中主要介紹數(shù)組的其他方面。

三、性能?請(qǐng)優(yōu)先考慮數(shù)組

在java中有很多方式來(lái)存儲(chǔ)一系列數(shù)據(jù),而且在操作上面比數(shù)組方便的多?但為什么我們還需要使用數(shù)組,而不是替代它呢?數(shù)組與其他種類(lèi)的容器之間的區(qū)別有三個(gè)方面:效率、類(lèi)型和保存基本類(lèi)型的能力。在java中,數(shù)組是一種效率最高的存儲(chǔ)和隨機(jī)訪問(wèn)對(duì)象引用序列的方式。

在項(xiàng)目設(shè)計(jì)中數(shù)組使用的越來(lái)越少了,而且它確實(shí)是沒(méi)有List、Set這些集合使用方便,但是在某些方面數(shù)組還是存在一些優(yōu)勢(shì)的,例如:速度,而且集合類(lèi)的底層也都是通過(guò)數(shù)組來(lái)實(shí)現(xiàn)的。

1 2 3 4 5 6 --------這是ArrayList的add()------ ????public boolean add(E e) { ????ensureCapacity(size + 1);? // Increments modCount!! ????elementData[size++] = e; ????return true; ????}

下面利用數(shù)組和list來(lái)做一些操作比較。

一、求和

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Long time1 = System.currentTimeMillis(); ????????for(int i = 0 ; i < 100000000 ;i++){ ????????????sum += arrays[i%10]; ????????} ????????Long time2 = System.currentTimeMillis(); ????????System.out.println("數(shù)組求和所花費(fèi)時(shí)間:" + (time2 - time1) + "毫秒"); ????????Long time3 = System.currentTimeMillis(); ????????for (int i = 0; i < 100000000; i++) { ????????????sum? += list.get(i%10); ????????} ????????Long time4 = System.currentTimeMillis(); ????????System.out.println("List求和所花費(fèi)時(shí)間:" + (time4 - time3) + "毫秒"); --------------Output: 數(shù)組求和所花費(fèi)時(shí)間:696毫秒 List求和所花費(fèi)時(shí)間:3498毫秒

從上面的時(shí)間消耗上面來(lái)說(shuō)數(shù)組對(duì)于基本類(lèi)型的求和計(jì)算的速度是集合的5倍左右。其實(shí)在list集合中,求和當(dāng)中有一個(gè)致命的動(dòng)作:list.get(i)。這個(gè)動(dòng)作是進(jìn)行拆箱動(dòng)作,Integer對(duì)象通過(guò)intValue方法自動(dòng)轉(zhuǎn)換成一個(gè)int基本類(lèi)型,在這里就產(chǎn)生了不必要的性能消耗。

? 所以在性能要求較高的場(chǎng)景中請(qǐng)優(yōu)先考慮數(shù)組。

四、變長(zhǎng)數(shù)組?

數(shù)組是定長(zhǎng)的,一旦初始化聲明后是不可改變長(zhǎng)度的。這對(duì)我們?cè)趯?shí)際開(kāi)發(fā)中是非常不方便的,聰明的我們肯定是可以找到方法來(lái)實(shí)現(xiàn)的。就如java不能實(shí)現(xiàn)多重繼承一樣,我們一樣可以利用內(nèi)部類(lèi)和接口來(lái)實(shí)現(xiàn)(請(qǐng)參考:java提高篇(九)—–實(shí)現(xiàn)多重繼承)。

那么如何來(lái)實(shí)現(xiàn)變長(zhǎng)數(shù)組呢?我們可以利用List集合add方法里面的擴(kuò)容思路來(lái)模擬實(shí)現(xiàn)。下面是ArrayList的擴(kuò)容方法:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public void ensureCapacity(int minCapacity) { ????????modCount++;? ????????int oldCapacity = elementData.length; ????????/** ?????????* 若當(dāng)前需要的長(zhǎng)度超過(guò)數(shù)組長(zhǎng)度時(shí)進(jìn)行擴(kuò)容處理 ?????????*/ ????????if (minCapacity > oldCapacity) { ????????????Object oldData[] = elementData;??? ????????????int newCapacity = (oldCapacity * 3) / 2 + 1;??? //擴(kuò)容 ????????????if (newCapacity < minCapacity) ????????????????newCapacity = minCapacity; ????????????//拷貝數(shù)組,生成新的數(shù)組 ????????????elementData = Arrays.copyOf(elementData, newCapacity); ????????} ????}

這段代碼對(duì)我們有用的地方就在于if語(yǔ)句后面。它的思路是將原始數(shù)組拷貝到新數(shù)組中,新數(shù)組是原始數(shù)組長(zhǎng)度的1.5倍。所以模擬的數(shù)組擴(kuò)容代碼如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 public class ArrayUtils { ????/** ?????* @desc 對(duì)數(shù)組進(jìn)行擴(kuò)容 ?????* @author chenssy ?????* @data 2013-12-8 ?????* @param <T> ?????* @param datas 原始數(shù)組 ?????* @param newLen 擴(kuò)容大小 ?????* @return T[] ?????*/ ????public static <T> T[] expandCapacity(T[] datas,int newLen){ ????????newLen = newLen < 0 ? datas.length :datas.length + newLen;?? ????????//生成一個(gè)新的數(shù)組 ????????return Arrays.copyOf(datas, newLen); ????} ????/** ?????* @desc 對(duì)數(shù)組進(jìn)行擴(kuò)容處理,1.5倍 ?????* @author chenssy ?????* @data 2013-12-8 ?????* @param <T> ?????* @param datas? 原始數(shù)組 ?????* @return T[] ?????*/ ????public static <T> T[] expandCapacity(T[] datas){ ????????int newLen = (datas.length * 3) / 2;????? //擴(kuò)容原始數(shù)組的1.5倍 ????????//生成一個(gè)新的數(shù)組 ????????return Arrays.copyOf(datas, newLen); ????} ????/** ?????* @desc 對(duì)數(shù)組進(jìn)行擴(kuò)容處理, ?????* @author chenssy ?????* @data 2013-12-8 ?????* @param <T> ?????* @param datas 原始數(shù)組 ?????* @param mulitiple 擴(kuò)容的倍數(shù) ?????* @return T[] ?????*/ ????public static <T> T[] expandCapacityMul(T[] datas,int mulitiple){ ????????mulitiple = mulitiple < 0 ? 1 : mulitiple; ????????int newLen = datas.length * mulitiple; ????????return Arrays.copyOf(datas,newLen ); ????} }

通過(guò)這種迂回的方式我們可以實(shí)現(xiàn)數(shù)組的擴(kuò)容。因此在項(xiàng)目中如果確實(shí)需要變長(zhǎng)的數(shù)據(jù)集,數(shù)組也是在考慮范圍之內(nèi)的,我們不能因?yàn)樗枪潭ㄩL(zhǎng)度而排斥他!

五、數(shù)組復(fù)制問(wèn)題

以前在做集合拷貝的時(shí)候由于集合沒(méi)有拷貝的方法,所以一個(gè)一個(gè)的復(fù)制是非常麻煩的,所以我就干脆使用List.toArray()方法轉(zhuǎn)換成數(shù)組然后再通過(guò)Arrays.copyOf拷貝,在轉(zhuǎn)換成集合,個(gè)人覺(jué)得非常方便,殊不知我已經(jīng)陷入了其中的陷進(jìn)!我們知道若數(shù)組元素為對(duì)象,則數(shù)組里面數(shù)據(jù)是對(duì)象引用

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 public class Test { ????public static void main(String[] args) { ????????Person person_01 = new Person("chenssy_01"); ????????Person[] persons1 = new Person[]{person_01}; ????????Person[] persons2 = Arrays.copyOf(persons1,persons1.length); ????????System.out.println("數(shù)組persons1:"); ????????display(persons1); ????????System.out.println("---------------------"); ????????System.out.println("數(shù)組persons2:"); ????????display(persons2); ????????//改變其值 ????????persons2[0].setName("chessy_02"); ????????System.out.println("------------改變其值后------------"); ????????System.out.println("數(shù)組persons1:"); ????????display(persons1); ????????System.out.println("---------------------"); ????????System.out.println("數(shù)組persons2:"); ????????display(persons2); ????} ????public static void display(Person[] persons){ ????????for(Person person : persons){ ????????????System.out.println(person.toString()); ????????} ????} } -------------Output: 數(shù)組persons1: 姓名是:chenssy_01 --------------------- 數(shù)組persons2: 姓名是:chenssy_01 ------------改變其值后------------ 數(shù)組persons1: 姓名是:chessy_02 --------------------- 數(shù)組persons2: 姓名是:chessy_02

從結(jié)果中發(fā)現(xiàn),persons1中的值也發(fā)生了改變,這是典型的淺拷貝問(wèn)題。所以通過(guò)Arrays.copyOf()方法產(chǎn)生的數(shù)組是一個(gè)淺拷貝。同時(shí)數(shù)組的clone()方法也是,集合的clone()方法也是,所以我們?cè)谑褂每截惙椒ǖ耐瑫r(shí)一定要注意淺拷貝這問(wèn)題。

有關(guān)于深淺拷貝的博文,參考:

漸析java的淺拷貝和深拷貝:http://www.cnblogs.com/chenssy/p/3308489.html。

使用序列化實(shí)現(xiàn)對(duì)象的拷貝:http://www.cnblogs.com/chenssy/p/3382979.html。

六、數(shù)組轉(zhuǎn)換為L(zhǎng)ist注意地方

我們經(jīng)常需要使用到Arrays這個(gè)工具的asList()方法將其轉(zhuǎn)換成列表。方便是方便,但是有時(shí)候會(huì)出現(xiàn)莫名其妙的問(wèn)題。如下:

1 2 3 4 5 6 7 public static void main(String[] args) { ????????int[] datas = new int[]{1,2,3,4,5}; ????????List list = Arrays.asList(datas); ????????System.out.println(list.size()); ????} ------------Output: 1

結(jié)果是1,是的你沒(méi)有看錯(cuò), 結(jié)果就是1。但是為什么會(huì)是1而不是5呢?先看asList()的源碼

1 2 3 public static <T> List<T> asList(T... a) { ????????return new ArrayList<T>(a); ????}

注意這個(gè)參數(shù):T…a,這個(gè)參數(shù)是一個(gè)泛型的變長(zhǎng)參數(shù),我們知道基本數(shù)據(jù)類(lèi)型是不可能泛型化的,也是就說(shuō)8個(gè)基本數(shù)據(jù)類(lèi)型是不可作為泛型參數(shù)的,但是為什么編譯器沒(méi)有報(bào)錯(cuò)呢?這是因?yàn)樵趈ava中,數(shù)組會(huì)當(dāng)做一個(gè)對(duì)象來(lái)處理,它是可以泛型的,所以我們的程序是把一個(gè)int型的數(shù)組作為了T的類(lèi)型,所以在轉(zhuǎn)換之后List中就只會(huì)存在一個(gè)類(lèi)型為int數(shù)組的元素了。所以我們這樣的程序System.out.println(datas.equals(list.get(0)));輸出結(jié)果肯定是true。當(dāng)然如果將int改為Integer,則長(zhǎng)度就會(huì)變成5了。

我們?cè)诳聪旅娉绦?#xff1a;

1 2 3 4 5 6 enum Week{Sum,Mon,Tue,Web,Thu,Fri,Sat} ????public static void main(String[] args) { ????????Week[] weeks = {Week.Sum,Week.Mon,Week.Tue,Week.Web,Week.Thu,Week.Fri}; ????????List<Week> list = Arrays.asList(weeks); ????????list.add(Week.Sat); ????}

這個(gè)程序非常簡(jiǎn)單,就是講一個(gè)數(shù)組轉(zhuǎn)換成list,然后改變集合中值,但是運(yùn)行呢?

1 2 3 4 Exception in thread "main" java.lang.UnsupportedOperationException ????at java.util.AbstractList.add(AbstractList.java:131) ????at java.util.AbstractList.add(AbstractList.java:91) ????at com.array.Test.main(Test.java:18)

編譯沒(méi)錯(cuò),但是運(yùn)行竟然出現(xiàn)了異常錯(cuò)誤!UnsupportedOperationException ,當(dāng)不支持請(qǐng)求的操作時(shí),就會(huì)拋出該異常。從某種程度上來(lái)說(shuō)就是不支持add方法,我們知道這是不可能的!什么原因引起這個(gè)異常呢?先看asList()的源代碼:

1 2 3 public static <T> List<T> asList(T... a) { ????????return new ArrayList<T>(a); ????}

這里是直接返回一個(gè)ArrayList對(duì)象返回,但是注意這個(gè)ArrayList并不是java.util.ArrayList,而是Arrays工具類(lèi)的一個(gè)內(nèi)之類(lèi):

1 2 3 4 5 6 7 8 9 10 11 private static class ArrayList<E> extends AbstractList<E> ????implements RandomAccess, java.io.Serializable{ ????????private static final long serialVersionUID = -2764017481108945198L; ????????private final E[] a; ????????ArrayList(E[] array) { ????????????if (array==null) ????????????????throw new NullPointerException(); ????????a = array; ????} ???????/** 省略方法 **/ ????}

但是這個(gè)內(nèi)部類(lèi)并沒(méi)有提供add()方法,那么查看父類(lèi):

1 2 3 4 5 6 7 public boolean add(E e) { ????add(size(), e); ????return true; ????} ????public void add(int index, E element) { ????throw new UnsupportedOperationException(); ????}

這里父類(lèi)僅僅只是提供了方法,方法的具體實(shí)現(xiàn)卻沒(méi)有,所以具體的實(shí)現(xiàn)需要子類(lèi)自己來(lái)提供,但是非常遺憾

這個(gè)內(nèi)部類(lèi)ArrayList并沒(méi)有提高add的實(shí)現(xiàn)方法。在ArrayList中,它主要提供了如下幾個(gè)方法:

1、size:元素?cái)?shù)量

2、toArray:轉(zhuǎn)換為數(shù)組,實(shí)現(xiàn)了數(shù)組的淺拷貝。

3、get:獲得指定元素。

4、contains:是否包含某元素。

所以綜上所述,asList返回的是一個(gè)長(zhǎng)度不可變的列表。數(shù)組是多長(zhǎng),轉(zhuǎn)換成的列表是多長(zhǎng),我們是無(wú)法通過(guò)add、remove來(lái)增加或者減少其長(zhǎng)度的。

參考文獻(xiàn):《編寫(xiě)高質(zhì)量代碼–改善Java程序的151個(gè)建議》

本系列:

  • java提高篇之?dāng)?shù)組(1):認(rèn)識(shí)JAVA數(shù)組
  • java提高篇之?dāng)?shù)組(2)
from:?http://www.importnew.com/20683.html

總結(jié)

以上是生活随笔為你收集整理的java提高篇之数组(2)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。