この記事の編集者は、JAVA 配列の使用法について紹介しますので、必要な方は参考にしてください
JAVA 配列とコンテナ クラスには 3 つの主な違いがあります: 効率、型、基本型を保存する機能です。 。 JAVA では、配列はオブジェクト参照のシーケンスを格納し、ランダムにアクセスする最も効率的な方法です。配列は単純な線形シーケンスであるため、要素へのアクセスが非常に高速になります。ただし、その代償として、配列のサイズは固定されており、その存続期間中は変更できません。
ジェネリックと自動パッケージ化メカニズムの出現により、コンテナーは配列とほぼ同じくらい簡単に基本型で使用できるようになりました。配列とコンテナーはどちらも、範囲外になると、RuntimeException が発生するため、それらの悪用をある程度防ぐことができます。配列の唯一の利点は効率性です。ただし、より一般的な問題を解決したい場合、配列では制約が多すぎる可能性があるため、この場合でもほとんどの人はコンテナーを選択します。
したがって、最新の JAVA バージョンを使用している場合は、配列よりもコンテナーを優先する必要があります。プログラムを配列にリファクタリングするのは、パフォーマンスに問題があることが判明し、配列に切り替えることでパフォーマンスが向上する場合にのみ行う必要があります。
【初期化】
JAVA には配列の初期化に関して非常に厳しい規制があり、配列の悪用を効果的に防止できます。初期化エラーが発生した場合は、RuntimeException ではなく CompileException が直接発生します。配列が適切に初期化されるまで、この配列参照に対して何も行うことはできません。
配列定義には、int[] array と int array[] が含まれます。通常、最初のスタイルは型と変数名を分離するために使用されます。
配列を初期化するには、静的初期化と動的初期化の 2 つの方法があります。長さは初期化時に指定する必要があり、多次元配列の最初の次元の長さを指定する必要があり、高次元から低次元まで定義する必要があります。初期化アクションはコード内のどこにでも指定できますが、{} メソッドは配列が作成される場所にのみ指定できます。特定の初期化方法については、プログラムを参照してください:
public class javaArrayInit{ public static void main(String args[]){ int[] arrayA; //未初始化 int[] arrayB = new int[5]; //静态初始化 //System.out.println(arrayA.length); //CompileException System.out.println("arrayB length: " + arrayB.length); //无法得到实际保存的元素个数 arrayA = new int[10]; //动态初始化 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}; //错误的初始化,不能同时定义维和初始化值 int[][] arrayE = new int[1][]; System.out.println("arrayE length: " + arrayE.length); //int[][] arrayF = new int[][2]; //应先指定高维的长度 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()}; //自定义数组类型 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
読み取り専用メンバーの長さは配列オブジェクトの一部です (ただし、この変数は実際には宣言されていません) API では、実行時に動的に生成されます)。これがアクセスできる唯一のフィールドまたはメソッドです。 [] 構文は配列オブジェクトにアクセスする唯一の方法であり、コンテナーには get() メソッドを通じてアクセスします。 Array.length を使用して配列のサイズを取得できます。String 型の String.length() とは異なることに注意してください。 Array はメンバー変数を使用し、String はメンバー メソッドを使用します。同時に、Array.length は配列のサイズのみを取得できますが、配列が実際に持つ要素の数は取得できません。多次元配列の長さは、最初の次元の長さのみを計算します。
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},};//注意后面的逗号 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 を使用すると配列全体または配列の特定の領域を埋めることができますが、Arrays.fill は単一の値でしか呼び出すことができないため、あまり役に立ちません。
【代入と参照】
JAVA配列が初期化されるとき、それは配列への参照のみを持ち、配列には記憶領域は割り当てられません。したがって、配列間のコピーは同じオブジェクトを操作するため、単純に「=」代入を使用することはできません。次のプログラム:
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]); } }
私はarrayAです、私は何も変更されていません: arrayBは変更されました
可以看出,我们改变arrayB[0]的值,改变的是引用的数组,因此我们输出arrayA[0],其实和arrayB[0]一样。
【数组复制】
JAVA中复制数组的方法:
1.使用FOR循环复制全部或指定元素,效率较低
2.使用clone方法,得到数组的值,而不是引用。然而clone不能复制指定元素,灵活性较低
3.使用System.arraycopy(src, srcPos, dest, destPos, length)方法,java标准类库提供有static方法 System.arraycopy(),用它复制数组要比for循环快很多,System.arraycopy()针对所有类型做了重载,基本类型数组和对象数组都可以用System.arraycopy()复制,但是对象数组只是复制引用,不会出现两份对象的拷贝。这被称作浅复制(shallowcopy)。
src:源数组;
srcPos:源数组要复制的起始位置;
dest:目的数组;
destPos:目的数组放置的起始位置;
length:复制的长度.
注意:System.arraycopy()不会进行自动包装和自动拆包,因此两个数组必须是同类型或者可以转换为同类型的数组。同时,这个方法也可以用于复制数组本身。
int[] test ={0,1,2,3,4,5,6};
System.arraycopy(test,0,test,3,3);
则结果为:{0,1,2,0,1,2,6};
测试程序如下:
代码如下:
public class javaArrayCopy{ public static void main(String args[]){ int[] array = {1,2,3,4,5,6,7,8,9}; //for循环方法 int[] arrayA = new int[9]; for(int i = 0; i < arrayA.length; i++){ arrayA[i] = array[i]; System.out.print(arrayA[i] + ","); } //测试 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(); //测试 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); //测试 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] + ","); } } }
【数组比较】
Arrays提供了重载后的equals()方法,针对所有类型和Object类型都做了重载,用来比较整个数组。数组相等的条件是元素个数必须相等,并且对应位置的元素也相等。而多维数组的比较用deepEquals()方法。Array.equals()方法比较的两个数组必须是同类型的数组。
代码如下:
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)); } }
【数组排序与查找】
数组提供了内置的排序方法sort(),可以对任意基本类型数组或者对象数组进行排序(该对象必须实现Comparable接口或者具有相关联的Comparator)。JAVA对不同的类型提供了不同的排序方法----针对基本类型设计的快速排序,以及针对对象设计的“稳定归并排序”,所以无需担心数组排序的效率问题。
binarySearch()用于在以排好序的数组中快速查找元素,如果对未排序的数组使用binarySearch(),那么将产生难以预料的结果。
【返回数组】
C和C++不能返回一个数组,只能返回指向数组的指针,因为返回数组使得控制数组的生命周期变得困难,并且容易造成内存泄漏。java允许直接返回一个数组,并且可以由垃圾回收机制回收。
【数组与容器转换】【无法转换基本类型数组】
数组转为List:
代码如下:
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输出会不同呢?
List转为数组
代码如下:
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
【去除重复数据】
利用数组和容器转换可以方便地去除数组重复数据,不过如果数组过大,效率是一个问题。
代码如下:
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; } }
关于效率问题,我做了一个对比,在我电脑上运行十万数据的数组大概是577ms,而运行一百万数据的数据大约要5663ms。这还跟计算机的运行能力有关,但是明显是随着数组大小递增的。
代码如下:
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; } }
输出:
startarray unique run time: 577msarrayB unique run time: 5663ms
以上がJAVA 配列の使用の概要の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。