關(guān)于JAVA 數(shù)組的使用介紹
JAVA數(shù)組與容器類(lèi)主要有三方面的區(qū)別:效率、類(lèi)型和保存基本類(lèi)型的能力。在JAVA中,數(shù)組是一種效率最高的存儲(chǔ)和隨機(jī)訪問(wèn)對(duì)象引用序列的方式。數(shù)組就是一個(gè)簡(jiǎn)單的線性數(shù)列,這使得元素訪問(wèn)非??焖?。但是為此付出的代價(jià)卻是數(shù)組的大小被固定,并且在其生命周期中不可改變。
由于范型和自動(dòng)包裝機(jī)制的出現(xiàn),容器已經(jīng)可以與數(shù)組幾乎一樣方便地用于基本類(lèi)型中了。數(shù)組和容器都可以一定程度上防止你濫用他們,如果越界,就會(huì)得到RuntimeException異常。數(shù)組碩果僅存的優(yōu)勢(shì)便是效率,然而,如果要解決更一般化的問(wèn)題,那數(shù)組可能會(huì)受到過(guò)多的限制,因此這種情況下大部分還是會(huì)選擇容器。
因此,如果使用最近的JAVA版本,應(yīng)該優(yōu)先選擇容器而不是數(shù)組。只有在已證明性能已成為問(wèn)題,并且切換到數(shù)組可以提高性能時(shí),才應(yīng)該重構(gòu)程序?yàn)閿?shù)組。
【初始化】
JAVA對(duì)數(shù)組初始化有很?chē)?yán)格的規(guī)定,這樣可以有效地防止濫用數(shù)組。如果初始化錯(cuò)誤,會(huì)直接得到CompileException而不是RuntimeException。在未對(duì)數(shù)組正確初始化之前,無(wú)法用此數(shù)組引用做任何事情。
數(shù)組定義有int[] array 和int array[],一般采用第一種風(fēng)格,可以將類(lèi)型與變量名分開(kāi)。
數(shù)組的初始化有兩種方式,靜態(tài)初始化和動(dòng)態(tài)初始化。初始化的時(shí)候必須指定長(zhǎng)度,多維數(shù)組第一維的長(zhǎng)度必須指出,同時(shí)必須由高維向低維定義。初始化動(dòng)作可以在代碼的任何地方,而用{}方式只能在創(chuàng)建數(shù)組的地方出現(xiàn)。具體初始化方式見(jiàn)程序:
public class javaArrayInit{
public static void main(String args[]){
int[] arrayA; //未初始化
int[] arrayB = new int[5]; //靜態(tài)初始化
//System.out.println(arrayA.length); //CompileException
System.out.println("arrayB length: " + arrayB.length); //無(wú)法得到實(shí)際保存的元素個(gè)數(shù)
arrayA = new int[10]; //動(dòng)態(tài)初始化
System.out.println("arrayA length: " + arrayA.length);
int[] arrayC = new int[]{1,2,3,4};
System.out.println("arrayC length: " + arrayC.length);
//int[] arrayD = new int[1]{1}; //錯(cuò)誤的初始化,不能同時(shí)定義維和初始化值
int[][] arrayE = new int[1][];
System.out.println("arrayE length: " + arrayE.length);
//int[][] arrayF = new int[][2]; //應(yīng)先指定高維的長(zhǎng)度
int[][] arrayG = new int[][]{{1,2,3,4},{5,6,7},{7,24,23,24}};
System.out.println("arrayG length: " + arrayG.length);
int[][][] arrayH = new int[][][]{{{1,2,3},{4,5,6},{7,8,9},{10,11,12}}};
System.out.println("arrayH length: " + arrayH.length);
dummyArray[] arrayI = {new dummyArray(),new dummyArray()}; //自定義數(shù)組類(lèi)型
System.out.println("arrayI length: " + arrayI.length);
System.out.println("arrayI[1]: " + arrayI[1].getValue());
dummyArray[] arrayK = new dummyArray[5];
System.out.println("arrayK[0]: " + arrayK[0]); //null
for(int i = 0; i < arrayK.length; i++){
arrayK[i] = new dummyArray();
}
System.out.println("arrayK[0]: " + arrayK[0].getValue()); //2
}
}
class dummyArray{
private static int temp;
private final int arrayValue = temp++;
public int getValue(){
return arrayValue;
}
}
輸出:
arrayB length: 5
arrayA length: 10
arrayC length: 4
arrayE length: 1
arrayG length: 3
arrayH length: 1
arrayI length: 2
arrayI[1]: 1
arrayK[0]: null
arrayK[0]: 2
【length】
只讀成員length是數(shù)組對(duì)象的一部分(雖然實(shí)際上API里面并沒(méi)有聲明這個(gè)變量,是運(yùn)行時(shí)動(dòng)態(tài)生成),這是唯一一個(gè)可以訪問(wèn)的字段或方法。而[]語(yǔ)法是訪問(wèn)數(shù)組對(duì)象的唯一方式,容器是通過(guò)get()方法訪問(wèn)??梢允褂肁rray.length來(lái)得到數(shù)組的大小,注意與String類(lèi)型的String.length()區(qū)分。Array使用的是成員變量的方式,而String使用的是成員方法的方式。同時(shí),Array.length只能得到數(shù)組的大小,而無(wú)法得到數(shù)組實(shí)際有多少元素。多維數(shù)組的length只計(jì)算第一維的長(zhǎng)度。
public class javaArrayLength{
public static void main(String args[]){
int[] arrayA = new int[15];
arrayA[1] = 1;
arrayA[2] = 2;
arrayA[3] = 3;
System.out.println("arrayA length: " + arrayA.length);
int[][] arrayB = new int[10][];
System.out.println("arrayB length: " + arrayB.length);
int[][] arrayC = new int[][]{{1,1,1,2,},{1,1,2,3,4,5},{4,5,6,7,7},};//注意后面的逗號(hào)
System.out.println("arrayC length: " + arrayC.length);
int[][] arrayD = new int[][]{{1,1,1,2,},{1,1,2,3,4,5},{4,5,6,7,7},{}};
System.out.println("arrayD length: " + arrayD.length);
}
}
輸出:
arrayA length: 15
arrayB length: 10
arrayC length: 3
arrayD length: 4
【Arrays.fill】
Arrays.fill是一個(gè)作用十分有限的方法,因?yàn)樗荒苡猛粋€(gè)值填充各個(gè)位置(如果是對(duì)象,則復(fù)制同一個(gè)引用進(jìn)行填充)。使用Arrays.fill可以填充整個(gè)數(shù)組或者數(shù)組的某一個(gè)區(qū)域,但是由于只能用單一的數(shù)值來(lái)調(diào)用Arrays.fill,因此作用并不是很大。
【賦值與引用】
JAVA數(shù)組初始化的時(shí)候擁有的只是對(duì)數(shù)組的引用,并沒(méi)有給數(shù)組分配存儲(chǔ)空間。因此,數(shù)組之間的復(fù)制不能簡(jiǎn)單地用“=”賦值,因?yàn)椴僮鞯氖峭粚?duì)象。如下程序:
public class javaArrayQuote{
public static void main(String args[]){
String testA = "testA";
String testB = "testB";
String[] arrayA = new String[]{"arrayA"};
String[] arrayB = new String[]{"arrayB"};
testB = testA;
testB = "testB change";
System.out.println("I'm testA,I have no changed: " + testA);
arrayB = arrayA;
arrayB[0] = "arrayB have changed";
System.out.println("I'm arrayA, I have no changed: " + arrayA[0]);
}
}
輸出:
I'm testA,I have no changed:testA
I'm arrayA, I have no changed:arrayB have changed
可以看出,我們改變arrayB[0]的值,改變的是引用的數(shù)組,因此我們輸出arrayA[0],其實(shí)和arrayB[0]一樣。
【數(shù)組復(fù)制】
JAVA中復(fù)制數(shù)組的方法:
1.使用FOR循環(huán)復(fù)制全部或指定元素,效率較低
2.使用clone方法,得到數(shù)組的值,而不是引用。然而clone不能復(fù)制指定元素,靈活性較低
3.使用System.arraycopy(src, srcPos, dest, destPos, length)方法,java標(biāo)準(zhǔn)類(lèi)庫(kù)提供有static方法 System.arraycopy(),用它復(fù)制數(shù)組要比f(wàn)or循環(huán)快很多,System.arraycopy()針對(duì)所有類(lèi)型做了重載,基本類(lèi)型數(shù)組和對(duì)象數(shù)組都可以用System.arraycopy()復(fù)制,但是對(duì)象數(shù)組只是復(fù)制引用,不會(huì)出現(xiàn)兩份對(duì)象的拷貝。這被稱(chēng)作淺復(fù)制(shallowcopy)。
src:源數(shù)組;
srcPos:源數(shù)組要復(fù)制的起始位置;
dest:目的數(shù)組;
destPos:目的數(shù)組放置的起始位置;
length:復(fù)制的長(zhǎng)度.
注意:System.arraycopy()不會(huì)進(jìn)行自動(dòng)包裝和自動(dòng)拆包,因此兩個(gè)數(shù)組必須是同類(lèi)型或者可以轉(zhuǎn)換為同類(lèi)型的數(shù)組。同時(shí),這個(gè)方法也可以用于復(fù)制數(shù)組本身。
int[] test ={0,1,2,3,4,5,6};
System.arraycopy(test,0,test,3,3);
則結(jié)果為:{0,1,2,0,1,2,6};
測(cè)試程序如下:
public class javaArrayCopy{
public static void main(String args[]){
int[] array = {1,2,3,4,5,6,7,8,9};
//for循環(huán)方法
int[] arrayA = new int[9];
for(int i = 0; i < arrayA.length; i++){
arrayA[i] = array[i];
System.out.print(arrayA[i] + ",");
}
//測(cè)試
System.out.println("");
arrayA[1] = 19;
for(int i = 0; i < arrayA.length; i++){
System.out.print(arrayA[i] + ",");
}
System.out.println("");
for(int i = 0; i < array.length; i++){
System.out.print(array[i] + ",");
}
System.out.println("");
//clone方法
int[] arrayB = new int[9];
arrayB = array.clone();
//測(cè)試
arrayB[1] = 19;
for(int i = 0; i < arrayB.length; i++){
System.out.print(arrayB[i] + ",");
}
System.out.println("");
for(int i = 0; i < array.length; i++){
System.out.print(array[i] + ",");
}
System.out.println("");
//System.arrayCopy 方法
int[] arrayC = new int[9];
System.arraycopy(array, 0, arrayC, 0, arrayC.length);
//測(cè)試
arrayC[1] = 19;
for(int i = 0; i < arrayC.length; i++){
System.out.print(arrayC[i] + ",");
}
System.out.println("");
for(int i = 0; i < array.length; i++){
System.out.print(array[i] + ",");
}
}
}
【數(shù)組比較】
Arrays提供了重載后的equals()方法,針對(duì)所有類(lèi)型和Object類(lèi)型都做了重載,用來(lái)比較整個(gè)數(shù)組。數(shù)組相等的條件是元素個(gè)數(shù)必須相等,并且對(duì)應(yīng)位置的元素也相等。而多維數(shù)組的比較用deepEquals()方法。Array.equals()方法比較的兩個(gè)數(shù)組必須是同類(lèi)型的數(shù)組。
import java.util.Arrays;
public class javaArrayEquals{
public static void main(String args[]){
int[] arrayA = {1,2,3};
int[] arrayB = {1,2,3,};
int[] arrayC = new int[4]; //if int[] arrayC = new int[3],return true
arrayC[0] = 1;
arrayC[1] = 2;
arrayC[2] = 3;
System.out.println(Arrays.equals(arrayA, arrayB));
System.out.println(Arrays.equals(arrayA, arrayC));
String[][] arrayD = {{"a","b"},{"c","d"}};
String[][] arrayE = {{"a","b"},{"c","d"}};
System.out.println(Arrays.deepEquals(arrayD, arrayE));
}
}
【數(shù)組排序與查找】
數(shù)組提供了內(nèi)置的排序方法sort(),可以對(duì)任意基本類(lèi)型數(shù)組或者對(duì)象數(shù)組進(jìn)行排序(該對(duì)象必須實(shí)現(xiàn)Comparable接口或者具有相關(guān)聯(lián)的Comparator)。JAVA對(duì)不同的類(lèi)型提供了不同的排序方法----針對(duì)基本類(lèi)型設(shè)計(jì)的快速排序,以及針對(duì)對(duì)象設(shè)計(jì)的“穩(wěn)定歸并排序”,所以無(wú)需擔(dān)心數(shù)組排序的效率問(wèn)題。
binarySearch()用于在以排好序的數(shù)組中快速查找元素,如果對(duì)未排序的數(shù)組使用binarySearch(),那么將產(chǎn)生難以預(yù)料的結(jié)果。
【返回?cái)?shù)組】
C和C++不能返回一個(gè)數(shù)組,只能返回指向數(shù)組的指針,因?yàn)榉祷財(cái)?shù)組使得控制數(shù)組的生命周期變得困難,并且容易造成內(nèi)存泄漏。java允許直接返回一個(gè)數(shù)組,并且可以由垃圾回收機(jī)制回收。
【數(shù)組與容器轉(zhuǎn)換】【無(wú)法轉(zhuǎn)換基本類(lèi)型數(shù)組】
數(shù)組轉(zhuǎn)為L(zhǎng)ist:
import java.util.*;
public class arrayToList{
public static void main(String args[]){
String[] arrayA = {"a","b","c"};
List listA = java.util.Arrays.asList(arrayA);
System.out.println("listA: " + listA);
int[] arrayB = {1,2,3};
List listB = java.util.Arrays.asList(arrayB);
System.out.println("listB: " + listB);
Integer[] arrayC = {1,2,3};
List listC = java.util.Arrays.asList(arrayC);
System.out.println("listC: " + listC);
}
}
輸出:
listA: [a, b, c]
listB: [[I@de6ced]
listC: [1, 2, 3]
為什么int和Integer輸出會(huì)不同呢?
List轉(zhuǎn)為數(shù)組
import java.util.*;
public class listToArray{
public static void main(String args[]){
List<String> list = new ArrayList<String>();
String[] array;
list.add("testA");
list.add("testB");
list.add("testC");
System.out.println("list: " + list);
String[] strings = new String[list.size()];
array = list.toArray(strings);
for(int i = 0, j = array.length; i < j; i++){
System.out.print(array[i] + ",");
}
}
}
輸出為:
list: [testA, testB, testC]
testA,testB,testC
【去除重復(fù)數(shù)據(jù)】
利用數(shù)組和容器轉(zhuǎn)換可以方便地去除數(shù)組重復(fù)數(shù)據(jù),不過(guò)如果數(shù)組過(guò)大,效率是一個(gè)問(wèn)題。
import java.util.*;
public class javaArrayUnique{
public static void main(String args[]){
String[] array = {"a","b","a","a","c","b"};
arrayUnique(array);
//test
for(int i = 0, j = arrayUnique(array).length; i < j; i++){
System.out.print(arrayUnique(array)[i] + ",");
}
}
public static String[] arrayUnique(String[] array){
List<String> list = new ArrayList<String>();
for(int i = 0, j = array.length; i < j; i++){
if(!list.contains(array[i])){
list.add(array[i]);
}
}
String[] strings = new String[list.size()];
String[] arrayUnique = list.toArray(strings);
return arrayUnique;
}
}
關(guān)于效率問(wèn)題,我做了一個(gè)對(duì)比,在我電腦上運(yùn)行十萬(wàn)數(shù)據(jù)的數(shù)組大概是577ms,而運(yùn)行一百萬(wàn)數(shù)據(jù)的數(shù)據(jù)大約要5663ms。這還跟計(jì)算機(jī)的運(yùn)行能力有關(guān),但是明顯是隨著數(shù)組大小遞增的。
import java.util.*;
public class javaArrayUnique{
public static void main(String args[]){
Double[] array = new Double[100000];
for(int i = 0, j = array.length; i < j; i++){
array[i] = Math.ceil(Math.random()*1000);
}
Double[] arrayB = new Double[1000000];
for(int i = 0, j = arrayB.length; i < j; i++){
arrayB[i] = Math.ceil(Math.random()*1000);
}
System.out.println("start");
long startTime = System.currentTimeMillis();
arrayUnique(array);
long endTime = System.currentTimeMillis();
System.out.println("array unique run time: " +(endTime - startTime) +"ms");
long startTimeB = System.currentTimeMillis();
arrayUnique(arrayB);
long endTimeB = System.currentTimeMillis();
System.out.println("arrayB unique run time: " +(endTimeB - startTimeB) +"ms");
}
public static Double[] arrayUnique(Double[] array){
List<Double> list = new ArrayList<Double>();
for(int i = 0, j = array.length; i < j; i++){
if(!list.contains(array[i])){
list.add(array[i]);
}
}
Double[] doubles = new Double[list.size()];
Double[] arrayUnique = list.toArray(doubles);
return arrayUnique;
}
}
輸出:
start
array unique run time: 577ms
arrayB unique run time: 5663ms
相關(guān)文章
Java線程監(jiān)聽(tīng),意外退出線程后自動(dòng)重啟的實(shí)現(xiàn)方法
下面小編就為大家?guī)?lái)一篇Java線程監(jiān)聽(tīng),意外退出線程后自動(dòng)重啟的實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-03-03Java和SQL實(shí)現(xiàn)取兩個(gè)字符間的值
這篇文章主要介紹了Java和SQL實(shí)現(xiàn)取兩個(gè)字符間的值操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06解決springboot 連接 mysql 時(shí)報(bào)錯(cuò) using password: NO的方案
在本篇文章里小編給大家整理了關(guān)于解決springboot 連接 mysql 時(shí)報(bào)錯(cuò) using password: NO的方案,有需要的朋友們可以學(xué)習(xí)下。2020-01-01Java動(dòng)態(tài)代理和反射機(jī)制詳解
這篇文章主要介紹了Java動(dòng)態(tài)代理和反射機(jī)制,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03VSCode中開(kāi)發(fā)JavaWeb項(xiàng)目的詳細(xì)過(guò)程(Maven+Tomcat+熱部署)
這篇文章主要介紹了VSCode中開(kāi)發(fā)JavaWeb項(xiàng)目(Maven+Tomcat+熱部署),本文分步驟通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09代理模式之Java動(dòng)態(tài)代理實(shí)現(xiàn)方法
今天一個(gè)偶然的機(jī)會(huì)我突然想看看JDK的動(dòng)態(tài)代理,因?yàn)橐郧耙仓酪稽c(diǎn),而且只是簡(jiǎn)單的想測(cè)試一下使用,使用很快里就寫(xiě)好了這么幾個(gè)接口和類(lèi),需要的朋友可以參考下2012-11-11基于list stream: reduce的使用實(shí)例
這篇文章主要介紹了list stream: reduce的使用實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09