数组——Arrays
数组是(相同类型数据)的(有序)(集合),数组中可以存储基本数据类型,可以存储引用数据类型;但是对于一个数组而言,数组的类型是固定的,数组的长度是固定的,一经定义,不能再发生变化。
0 java.util.Arrays——数组工具类
Arrays类包含用于操作数组的各种方法(如排序和搜索)等。
常用的Arrays方法:
-
Arrays.toString(arr)
:数组转字符串 -
Arrays.copyOf(arr,arr.length)
:数组拷贝,arr为某一类型的数组 -
Arrays.equals(arr1,arr2)
: 判断两个数组是否相等 -
Arrays.sort(arr)
:数组排序(升序) -
Arrays.sort(arr,from,to)
:数组排序(升序),指定范围排序。 -
sort(T[] a, Comparator<? super T> c) :根据指定的比较器引发的顺序对指定的对象数组的指定范围进行排序。
①对一维数组进行降序排列,注意数组也必须是Integer类型。
Integer[] array={1,3,5,7,9,2,0};
Arrays.sort(array, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
});
System.out.println(Arrays.toString(array));
结果:[9, 7, 5, 3, 2, 1, 0]
lambda表达式的写法:
Arrays.sort(array,(o1,o2)-> o2-o1);
②对二维数组进行排序,以第三列为基础,进行升序排列
1,3,0
4,3,5
9,5,4
Integer[][] array={{1,3,0},{4,3,5},{9,5,4}};
Arrays.sort(array, new Comparator<Integer[]>() {
@Override
public int compare(Integer[] o1, Integer[] o2) {
return o1[2]-o2[2];
}
});
for(int i=0;i<array.length;i++){
for(int j=0;j<array[0].length;j++){
if(j==array[0].length-1){
System.out.println(array[i][j]);
continue;
}
System.out.print(array[i][j]+" ");
}
}
结果:
1,3,0 1 3 0
4,3,5 -> 9 5 4
9,5,4 4 3 5
lambda表达式的写法:
Arrays.sort(array, (Integer[] o1,Integer[] o2)->o1[2]-o2[2]);
Arrays.hashCode(arr):
返回数组的哈希码
int[] array={1,3,5};
System.out.println(Arrays.hashCode(array));
结果:30850
Arrays.asList(T... a)
:接受一个数组或是一个用逗号分割的元素列表,将其转化为List对象。
List<Integer> list1= Arrays.asList(1,2,3,4,5);
Integer[] array = {1,3,4,5};
List<Integer> list2 = Arrays.asList(array);
list2.add(1);运行时报错
//当需求类型和Arrays.asList中的类型不一致时,需要指明类型
//List<Integer> list2 = Arrays.<Integer>asList(array);
- 通过Arrays.asList(数组)的方式,因为底层表示的是数组,所以当调用add时,会报错,因为数组是不能调整尺寸的。
- 为了让编译器知道Arrays.asList中的类型,有时需要添加一个显示类型参数说明如:
Arrays.<String>asList(array)
注意:
- 数组是一种引用类型,数组是存放一组相同数据类型的集合,数组是一块连续的内存。
- 数组中数据类型必须统一
- 数组的长度在运行期间不可改变
- Java中的参数传递只有值传递包括(基本类型、引用类型),
引用类型是一个地址,要改变形参指向的地址时,原参地址不会改变。
1 数组初始化
两种初始化:
1). 动态初始化(指定长度)
2). 静态初始化(指定内容)
1). 动态初始化(不确定数组内容时)
数组存储的数据类型[] 数组名 = new 数组存储的数据类型[长度]
int[] arr = new int[3]; //new 创建数组的动作
可以拆分为两个步骤:
int[] arr;
arr = new int[3];
2).静态初始化 (确定了数组内容时使用)
数据类型[] 数组名 = new 数据类型[]{元素1,元素2,…};
int[] arr = new int[] {1,2,3,4,5}; //没有指定长度,会自动推算得到长度
静态初始化的标准形式,可以拆分为两个步骤:
int[] arr;
arr = new int[] {1,2,3,4,5};
3).省略的静态初始化(不可以拆分为两个步骤)
数据类型[] 数组名 = {元素1,元素2,…};
int[] arr = {1,2,3,4,5};
2 数组的访问
int[] array = {1,3,4}; //静态初始化也有一个设置默认值的过程
System.out.println(array); //输出数组对应的内存地址哈希值
数组名[索引] :
索引从0开始到数组长度-1,即 [0,length-1]。
获取数组的长度
int[] array = {12,34,5,6,7,8,9};
int len = array.length;
System.out.println(“数组的数据长度:”+ len);
对于动态创建的数组:
int [] array = new int[3];
System.out.println(array[0]); >>> 0
使用动态数组初始化时,其中的元素会自动拥有一个默认值:
整数类型:0
浮点类型:0.0
字符类型:\u0000
布尔类型:false
引用类型:null
array[1] = 123; //赋值
3 数组索引越界异常
空指针异常:
int[] array = null;
//所有的引用类型都可以赋值为一个null值
System.out.println(array[0]);
数组必须进行初始化才能使用其中的元素
如果只赋值了一个null,将会发生空指针异常NullPointerException
4 可变长参数方法
public static void main(String[] args){
sum(2,3,4,5);
}
public static void sum(int b, int... a){
System.out.println(b);
System.out.println("********");
for(int x:a){
System.out.println(x);
}
}
- 形参类型后增加3个点 … ,则表明该形参可以接受多个参数值,多个参数值会被当做数组传入。
- 调用时,如果同时能匹配固定参数和可变长参数的方法,会优先匹配固定参数方法。
- 一个方法只能有一个可变参数,且可变参数应为最后一个参数。
5 数组示例
(1)遍历数组
int[] array = {1,2,3,4};
for (int i = 0; i<array.length; ++i){
System.out.println(array[i]);
}
//for-ench循环遍历数组
for (int x:array){
System.out.println(x);
}
(2)求取数组的最大值:
public static void main(String[] args){
int[] array = {3,65,77,32,23,665};
int max = array[0];
for (int i=1; i<array.length;i++){
if (array[i]>max){
max = array[i];
}
}
System.out.println(“最大值:” + max);
}
(3)数组元素反转
public class Demo_Test{
public static void main(String[] args){
int[] array = {21,3,4,5,64,1};
for (int min=0,max=array.length-1;min<max;min++,max--){
int temp = array[min];
array[min] = array[max];
array[max] = temp;
}
for (int i=0; i<array.length-1;i++){
System.out.println(array[i]);
}
}
}
(4)数组作为方法的参数
public static void printArray(int[] array){
for (int i=0; i<array.length-1;i++){
System.out.println(array[i]);
}
}
数组可以作为方法的参数。
当调用方法的时候,传递的是数组的地址值
(5)数组作为方法的返回值
public class Demo_Test{
public static void main(String[] args){
int[] result = calculate(12,32,43);
System.out.println(“总和”+result[0]);
System.out.println(“平均数”+result[1]);
}
public static int[] calculate(int a, int b, int c){
int sum = a+ b +c;
int avg = sum/3;
int[] array = {sum,avg};
return array;
}
}
任何数据类型都可以作为方法的参数类型或返回值类型
数组作为方法的返回值,返回的其实是数组的地址值
(6)数组转字符串
import java.util.Arrays
int[] arr = {1,2,3,4,5};
String newArr = Arrays.toString(arr);
System.out.println(newArr);
// >>> [1,2,3,4,5]
重写toString方法
public static void main(String[] args){
int[] arr= {1,2,3,4};
System.out.pirintln(toString(arr));
}
public static String toString(int[] arr){
String ret = "[";
for (int i=0;i<arr.length;i++){
ret += arr[i];
if(i!=arr.length-1){
ret+=",";
}
}
ret+="]";
retrun ret;
}
(7)数组拷贝
import java.util.Arrays
int[] arr = {1,2,3,4};
int[] newArr = Arrays.copyOf(arr,arr.length);
System.out.println("newArr:"+Arrays.toString(newArr));
数组拷贝的方式(浅拷贝):
- for
- clone()
- System.arraycopy()
- Arrays.copy()
(8) 二分查找
在数据已经有序的情况下
public static void mian(String[] args){
int[] arr = {1,2,3,4,5,6};
System.out.println(binarySearch(arr,6));
}
public static int binarySearch(int[] arr,int toFind){
int left = 0;
int right = arr.length - 1;
while (left <= right){
int mid =(left+right)/2;
if(toFind<arr[mid]){
//去左侧区间找
right = mid-1;
}else if (toFind>arr[mid]){
//去右侧区间找
left = mid +1;
}else {
//toFind ==arr[mid]相等,找到
return mid;
}
}
//循环结束,找到目标
return -1;
}
(9) 判断数组是否是升序的
public static void main(String[] args){
int[] arr = {1,2,3,4,5,3};
System.out.println(isSorted(arr));
}
public static boolean isSorted(int[] arr){
for(int i=0;i<arr.length-1;i++){
if(arr[i]>arr[i+1]){
return false;
}
}
return true;
}
(10)冒泡排序(升序)
import java.util.Arrays;
class Main{
public static void main(String[] args){
int[] arr = {1,3,5,9,5,6,2};
bubbleSort(arr);
System.out.println(Arrays.toString(arr));
}
public static void bubbleSort(int[] arr){
for(int i=0;i<arr.length-1;i++){
for(int j= 0;j<arr.length-1-i;j++){
if(arr[j]>arr[j+1]){
int tmp = arr[j];
arr[j]=arr[j+1];
arr[j+1]=tmp;
}
}
}
}
}
结果: [1, 2, 3, 5, 5, 6, 9]
(10)sort排序
public static void main(String[] args){
int[] arr = {9,5,2,7};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}
(11)数组数字排序
(偶数放在前半部分,奇数放在右半部分)
public static void main(String[] args){
int[] arr = {1,2,3,4,5,6};
transform(arr);
System.out.println(Arrays.toString(arr));
}
public static void transform(int[] arr){
int left = 0;
int right = arr.length-1;
while(left<right){
while (left<right && arr[left] %2 == 0){
left++;
}
while(left<right && arr[right]%2 != 0){
ritht--;
}
int tmp = arr[left];
arr[left] = arr[right];
arr[right] = tmp;
}
}
6 二维数组
二维数组本质上是一个一维数组,不过每个元素又是一个一维数组。
数据类型[ ][ ] 数组名称 = new 数据类型[行][列]{初始化数据}
int[][] array = new int[][]{{1,4,5},{2,3,5}};
二维数组也可以是不规则的,如arr1 = {{1,2,3},{4,6}};
int[][] arr = {{1,2,3},{4,5,6}};
int[][] arr1 = {{1,2,3},{4,6}};
for (int row=0; row<arr.length;row++){
for(int col=0;col<arr[row].length;col++){
System.out.print(arr[row][col]+" ");
}
System.out.println("");
}
结果:
1 2 3
4 5 6