数组的三种创建方式
创建数组的三种方式:其实分为2类,一种是静态的创建,如方式一。一种是动态的创建,只不过根据写法的不同分为方式二和方式三:
public static void main(String[] args) {
// 1.方式一 声明 分配空间并赋值
int[] arr1 = {1,2,3};
// 2.方式二 显示初始化
int[] arr2;
arr2 = new int[]{1,2,3};
// 3.方式三 显示初始化()
int[] arr3;
arr3 = new int[3];
}
他们的区别,方式一:在声明的时候直接就已经分配空间,并赋值,方式一是不能写成如下这种形式的。
int[] arr1;
arr1 = {1,2,3};//错误写法 编译不同过
方式二和方式三,声明和内存分配是分开的,如上面的例子,
int[] arr2; 和 int[] arr3;
这一步是在栈空间分配一个引用,存放的是一个引用,null
arr2 = new int[]{1,2,3};
arr3 = new int[3];
到这一步的时候jvm才开始在内存堆区域分配空间,并赋值,方式二直接赋值 1,2,3 方式三 默认初始化,基本类型是 0 布尔类型是 false 引用类型为null,
注:内存一旦分配不能改变,所有说数组长度固定
多维数组的遍历
对于一维数组
最简单的遍历方法
for( int i =0; i<arrayName.length; i++)
{
Syetem.out.printf("arrayName[i]");
}
foreach循环
java5之后,java提供了一种更为简单的循环,无需根据索引来访问数组元素,foreach循环自动遍历数组和集合的每个元素。
public class ForEachTest
{
public static void main (String [] args)
{
string[] books = {"1","2","3"};
for( String book : books)
{
System.out.println(book);
}
}
}
对于多维数组
Java中的二维数组其实是一个一维数组的数组,这意味着二维数组是一个数组的引用,其每一个元素都是另一个int数组的引用(多维数组依次),所以不同的遍历方式对性能的影响非常大
package arrayTraverse;
/**
* 二维数组的问题
*
* 我们在初始化一个任意大小的2维数组。(为简化分析我们使用二维方阵)我们将用两种不同方式迭代同一个数组,分析结果
* 两种迭代方式的性能差距很大
* @author mohit
*
*/
public class TheProblemOf2DArray {
//数组大小:数组越大,性能差距越明显
private static final int ARR_SIZE=9999;
public static void main(String[] args) {
//新数组
int arr[][]=new int[ARR_SIZE][ARR_SIZE];
long currTime=System.currentTimeMillis();
colMajor(arr);
System.out.println("Total time in colMajor : "+(System.currentTimeMillis()-currTime)+" ms");
//新数组,与arr完全相同
int arr1[][]=new int[ARR_SIZE][ARR_SIZE];
currTime=System.currentTimeMillis();
rowMajor(arr1); // this is the only difference in above
System.out.println("Total time in col : "+(System.currentTimeMillis()-currTime) +" ms");
}
/**
* 下面的代码按列为主遍历数组
* 即在扫描下一行之前先扫描完本行
*
*/
private static void colMajor(int arr[][]) {
for(int i=0;i<ARR_SIZE;i++){
for (int j=0;j<ARR_SIZE;j++){
//See this, we are traversing j first and then i
arr[i][j]=i+j;
}
}
}
/**
* 如果我们转换内外循环
* 程序就以行为主顺序遍历数组
* 即在扫描下一列之前先扫描完本列
* 这意味着我们访问数组时每次都在访问不同的行(因此也在访问不同的页)
* 代码微小的改变将导致这个程序花费更多的时间完成遍历
*/
private static void rowMajor(int arr[][]) {
for(int i=0;i<ARR_SIZE;i++){
for (int j=0;j<ARR_SIZE;j++){
/*看这个,我们先遍历j,然后遍历i,但是对于访问元素来说
* 它们在更远的位置,所以需要花费的更多
*/
arr[j][i]=i+j;
}
}
}
}
Arrays类的常用方法
asList()
- Arrays.asList(T… data)
注意:该方法返回的是Arrays内部静态类ArrayList,而不是我们平常使用的ArrayList,,该静态类ArrayList没有覆盖父类的add, remove等方法,所以如果直接调用,会报UnsupportedOperationException异常
- 将数组转换为集合,接收一个可变参
List<Integer> list = Arrays.asList(1, 2, 3);
list.forEach(System.out::println); // 1 2 3
Integer[] data = {1, 2, 3};
List<Integer> list = Arrays.asList(data);
list.forEach(System.out::println); // 1 2 3
- 如果将基本数据类型的数组作为参数传入
该方法会把整个数组当作返回的List中的第一个元素
int[] data = {1, 2, 3};
List<int[]> list = Arrays.asList(data);
System.out.println(list.size()); // 1
System.out.println(Arrays.toString(list.get(0))); // [1, 2, 3]
copyOf()
- Arrays.copyOf(T[] original, int newLength)
- 拷贝数组,其内部调用了 System.arraycopy() 方法,从下标0开始,如果超过原数组长度,会用null进行填充
Integer[] data1 = {1, 2, 3, 4};
Integer[] data2 = Arrays.copyOf(data1, 2);
System.out.println(Arrays.toString(data2)); // [1, 2]
Integer[] data2 = Arrays.copyOf(data1, 5);
System.out.println(Arrays.toString(data2)); // [1, 2, 3, 4, null]
copyOfRange
- Arrays.copyOfRange(T[] original, int from, int to)
- 拷贝数组,指定起始位置和结束位置,如果超过原数组长度,会用null进行填充
Integer[] data1 = {1, 2, 3, 4};
Integer[] data2 = Arrays.copyOfRange(data1, 0, 2);
System.out.println(Arrays.toString(data2)); // [1, 2]
Integer[] data2 = Arrays.copyOfRange(data1, 0, 5);
System.out.println(Arrays.toString(data2)); // [1, 2, 3, 4, null]
sort()
- Arrays.sort(Object[] array)
- 对数组元素进行排序(串行排序)
String[] data = {"1", "4", "3", "2"};
System.out.println(Arrays.toString(data)); // [1, 4, 3, 2]
Arrays.sort(data);
System.out.println(Arrays.toString(data)); // [1, 2, 3, 4]
- Arrays.sort(T[] array, Comparator<? super T> comparator)
- 使用自定义比较器,对数组元素进行排序(串行排序)
String[] data = {"1", "4", "3", "2"};
System.out.println(Arrays.toString(data)); // [1, 4, 3, 2]
// 实现降序排序,返回-1放左边,1放右边,0保持不变
Arrays.sort(data, (str1, str2) -> {
if (str1.compareTo(str2) > 0) {
return -1;
} else {
return 1;
}
});
System.out.println(Arrays.toString(data)); // [4, 3, 2, 1]
lambda注:表达式可能在某些低版本编译器编译不通过
- Arrays.sort(Object[] array, int fromIndex, int toIndex)
- 对数组元素的指定范围进行排序(串行排序)
String[] data = {"1", "4", "3", "2"};
System.out.println(Arrays.toString(data)); // [1, 4, 3, 2]
// 对下标[0, 3)的元素进行排序,即对1,4,3进行排序,2保持不变
Arrays.sort(data, 0, 3);
System.out.println(Arrays.toString(data)); // [1, 3, 4, 2]
- Arrays.sort(T[] array, int fromIndex, int toIndex, Comparator<? super T> c)
- 使用自定义比较器,对数组元素的指定范围进行排序(串行排序)
toString()
- Arrays.toString(Object[] array)
- 返回数组元素的字符串形式
Integer[] data = {1, 2, 3};
System.out.println(Arrays.toString(data)); // [1, 2, 3]
fill()
- Arrays.fill(Object[] array, Object obj)
- 用指定元素填充整个数组(会替换掉数组中原来的元素)
Integer[] data = {1, 2, 3, 4};
Arrays.fill(data, 9);
System.out.println(Arrays.toString(data)); // [9, 9, 9, 9]
- Arrays.fill(Object[] array, int fromIndex, int toIndex, Object obj)
- 用指定元素填充数组,从起始位置到结束位置,取头不取尾(会替换掉数组中原来的元素)
Integer[] data = {1, 2, 3, 4};
Arrays.fill(data, 0, 2, 9);
System.out.println(Arrays.toString(data)); // [9, 9, 3, 4]