目录

数组


数组

1 数组的概念

1.1 数组的作用

  • 用来保存、管理一组相同数据类型的数据

1.2 把一组具有相同数据类型的变量使用同一个名字来进行管理,并且这些元素按照一定的顺序进行排列。这同一个名字我们称为【数组名】,每一个元素通过编号进行区别,这个编号我们称为【下标】或索引。元素的总个数就是【数组的长度】。

2 数组如何声明和初始化

2.1 数组的声明

  • 数组的类型 数组名;

  • 数组的元素的类型[] 数组名;

    • 推荐的方式
  • 数组的元素的类型 数组名[];

2.2 初始化

  • 动态初始化

    • 格式:

      • 数组名 = new 元素的类型[数组的长度];
  • 静态初始化

    • 格式

      • 数组名 = new 元素的类型[]{元素列表};

        • 元素列表的每一个元素使用,分割
        • 元素列表的个数就是数组的长度
      • 简写形式

        • 数组的元素的类型[] 数组名 = {元素列表};

          • 只有声明和静态初始化在一行,才可以这么简写

3 数组的元素

3.1 表示形式

  • 数组名[下标]

    • 下标的范围

      • [0,数组的长度-1]

        • [0, 数组名.length -1]
      • [0,数组的长度)

3.2 赋值

  • 数组名[下标] = 值;

4 数组的长度

4.1 数组名.length

5 数组的遍历

5.1 for循环

  • for(int i=0; i<数组名.length; i++){ }

5.2 foreach循环

  • for(数组的元素的类型 元素的临时名 : 数组名){ }

6 数组的算法

6.1 (1)在数组中找最大值/最小值

//找最大值

public static int max(int[] arr){

	//第一步:假设第一个元素最大

	int max = arr[0];



	//遍历后面的元素和max比较

	for (int i = 1; i < arr.length; i++) {

		//当有比max的值,就把max修改为它的值

		if(max < arr[i]){

			max = arr[i];

		}

	}



	return max;

}

6.2 (2)在数组中找最大值、最小值的下标

//找最大值的下标

public static int maxIndex(int[] arr){

	//第一步:假设第一个元素最大

	int index = 0;



	//arr[index] 和 后续的元素一一比较

	for (int i = 1; i < arr.length; i++) {

		//当有比max的值,就把max修改为它的值

		if(arr[index] < arr[i]){

			index = i;

		}

	}

	return index;

}

6.3 (3)数组元素的累加和,平均值

//求数组元素的总和

public static long sum(int[] arr){

	long sum = 0;



	for (int i = 0; i < arr.length; i++) {

		sum += arr[i];

	}



	return sum;

}

public static double avg(int[] arr){

	double sum = sum(arr);

	return sum/arr.length;

}

6.4 (4)反转

//反转

public static void reverse(int[] arr){

	//如果有5个元素,应该交换2次或3次      arr.length/2

	//如果有6个元素,应该交换3次                 arr.length/2

	//数组的收尾对应位置交换



	//次数

	for(int i=0; i<arr.length/2; i++){

		//首尾交换

		int temp = arr[i];

		arr[i] = arr[arr.length-1-i];

		arr[arr.length-1-i] = temp;

	}

}





//反转部分

public static void reverse(int[] arr, int start ,int end){

	//次数

	//假设start = 1, end = 5     次数2次    (end + 1 - start)/2  (5+1-1)/2  2

	//假设start = 1, end = 6  次数3次      (end + 2 - start)/2  (6+1-1)/2  3



	for(int i=0; i< (end + 1 - start)/2; i++){

		//首尾交换

		//arr[start],arr[start+1]...

		//arr[end],arr[end-1]...

		int temp = arr[start + i];

		arr[start + i] = arr[end -i];

		arr[end-i] = temp;

	}

}

6.5 (5)复制

//复制一个数组,从原数组的[0]元素开始复制,新数组的长度由使用者决定

public static int[] copy(int[] src, int newLength){

	//1、创建新数组的对象

	int[] newArray = new int[newLength];



	//2、把原数组的元素复制到新数组中

	for(int i=0; i<newArray.length && i<src.length; i++){

		newArray[i] = src[i];

	}



	return newArray;

}



//复制一个数组,从原数组的[start]元素开始复制,新数组的长度由使用者决定

public static int[] copy(int[] src, int start, int newLength){

	//1、创建新数组

	int[] newArray = new int[newLength];



	//2、把原数组的元素从[start]复制到新数组的[0]...

	for(int i=0; i<newArray.length && start+i<src.length; i++){

		newArray[i] = src[start+i];

	}



	return newArray;

}

6.6 (6)排序

  • 冒泡排序

    //假设数组5个元素

    public static void pubSort3(int[] arr){

      //方式二:把大的往右沉
    
      //每一轮从左边开始比较
    
      //比较的轮数依然是n-1轮
    
      for(int i=1; i<arr.length; i++){
    
      	//每一轮从左边开始比较
    
      	/*
    
      	 * 第一轮:i=1, 比较4次,j=0,1,2,3   ,j<arr.length-i  j<5-1 j<4
    
      	 * 第二轮:i=2,比较3次,j=0,1,2      ,j<arr.length-i  j<5-2 j<3
    
      	 * ...
    
      	 */
    
      	for(int j=0; j<arr.length-i; j++){
    
      		//如果左边的元比右边的元素大,交换
    
      		if(arr[j] > arr[j+1]){
    
      			int temp = arr[j];
    
      			arr[j] = arr[j+1];
    
      			arr[j+1] = temp;
    
      		}
    
      	}
    
      }
    

    }

    //假设数组5个元素

    public static void pubSort2(int[] arr){

      //排序规则:每一轮通过相邻元素的比较,把小的往左边冒(或把大的往右边沉),每一轮都是把本轮的最小值冒出来(最大值沉下去)
    
      //经过n-1轮完成最终的排序
    
      //(1)方式一:把小的往左边冒,注意,每一轮都是从最右边往左边比较
    
      //i=0,i=1,i=2,i=3  i<5-1 -->  i<4 -->  i<=3
    
      for(int i=0; i<arr.length-1; i++){//一共n-1轮
    
      	//每一轮都要从最右边往左边比较
    
      	/*
    
      	 * 第一轮:比较n-1次,比较4次, i=0, j=4,3,2,1 ,j>i
    
      	 * 第二轮:比较3次,i=1, j=4,3,2 ,j>i
    
      	 * ....
    
      	 */
    
      	for(int j=arr.length-1; j>i; j--){
    
      		//相邻的元素比较,而且如果右边的比左边的小,需要交换
    
      		if(arr[j] < arr[j-1]){
    
      			int temp = arr[j];
    
      			arr[j] = arr[j-1];
    
      			arr[j-1] = temp;
    
      		}
    
      	}
    
      }
    

    }

    //冒泡排序:从小到大

    //如果数组是5个元素

    public static void pubSort(int[] arr){

      //排序规则:每一轮通过相邻元素的比较,把小的往左边冒(或把大的往右边沉),每一轮都是把本轮的最小值冒出来(最大值沉下去)
    
      //经过n-1轮完成最终的排序
    
      //(1)方式一:把小的往左边冒,注意,每一轮都是从最右边往左边比较
    
      for(int i=1; i<arr.length; i++){//一共n-1轮
    
      	//每一轮都要从最右边往左边比较
    
      	/*
    
      	 * 第一轮:比较n-1次,比较4次, i=1, j=4,3,2,1 ,j>=i
    
      	 * 第二轮:比较3次,i=2, j=4,3,2 ,j>=i
    
      	 * ....
    
      	 */
    
      	for(int j=arr.length-1; j>=i; j--){
    
      		//相邻的元素比较,而且如果右边的比左边的小,需要交换
    
      		if(arr[j] < arr[j-1]){
    
      			int temp = arr[j];
    
      			arr[j] = arr[j-1];
    
      			arr[j-1] = temp;
    
      		}
    
      	}
    
      }
    

    }

  • 直接选择排序

    //直接选择排序

    //基本原理:将待排序的元素分为已排序(初始为空)和未排序两组,依次将未排序的元素中值最小的元素放入已排序的组中。

    //[3,2,1,5,4] 从小到大排序

    /*

    * 第一次:所有元素都属于未排序 把未排序的元素中的最小值找出来 arr[2] = 1 ,放入已排序组中 和第一个元素交换

    * [1,2,3,5,4]

    * 第二次:已排序的是[1],未排序的是[2,3,5,4],把未排序元素中的最小值找出 arr[1]=2,放入已排序组中

    * 【1,2】,【3,5,4】

    * …

    *

    */

    //假设5个元素

    public static void selectSort(int[] arr){

      //次数
    
      for(int i=0; i<arr.length-1; i++){
    
      	//第一次,找最小值
    
      	//假设每一轮的未排序元素的第一个最小
    
      	int index = i;
    
    
    
      	//找出本轮最小值
    
      	/*
    
      	 * int i=0 ,从哪些元素中找最小值  [0]~[4]   j=1,2,3,4
    
      	 * int i=1,从哪些元素中找最小值[1]~[4]    j=2,3,4
    
      	 * ...
    
      	 */
    
      	for(int j=i+1; j<arr.length; j++){
    
      		if(arr[index] > arr[j]){
    
      			index = j;
    
      		}
    
      	}
    
    
    
      	//找出arr[index]值最小,下标是index
    
      	//arr[i] 和 arr[index]交换
    
      	if(i!=index){
    
      		int temp = arr[i];
    
      		arr[i] = arr[index];
    
      		arr[index] = temp;
    
      	}
    
    
    
      }
    

    }

6.7 (7)数组的扩容

private void kuorong(){

	//先扩容

	int[] newArray = new int[arr.length*2];

	//通过循环把原数组中的内容复制到新数组中

	for(int i=0; i<arr.length; i++){

		newArray[i] = arr[i];

	}

	//把新家的地址记录下来,下次存、取元素都从新家操作,旧家不要了

	arr = newArray;

}

6.8 (8)数组的元素插入

package com.atguigu.array;

public class MyArrayList {

private int[] arr = new int[5];//装数据

private int total;//记录实际存储的元素的个数





//在index插入数据data

public void insert(int index, int data){

	//如果当前数组已满,需要先扩容

	if(total >= arr.length){

		//(1)先创建一个新的更大的数组

		int[] newArray = new int[arr.length*2];

		//(2)把原来数组中的数据复制到新数组中

		for(int i=0; i<arr.length; i++){

			newArray[i] = arr[i];

		}

		//(3)使得arr指向新数组

		arr = newArray;

	}



	//1、先把index右边的元素右移

	/*

	 * 假设total=3,index=1

	 * 现在有值arr[0],arr[1],arr[2],需要移动的是arr[2],arr[1]

	 * 假设total=5,index=1

	 * 现在有值arr[0],arr[1],arr[2],arr[3],arr[4],需要移动的是,arr[4],arr[3],arr[2],arr[1]

	 */

	for(int i = total-1; i>=index; i--){

		//右边的元素=左边的元素

		arr[i+1] = arr[i];

	}



	//在index位置插入data

	arr[index]= data;



	//元素个数加1

	total++;

}

}

6.9 (9)数组的元素删除

  • 删除指定位置的元素

    package com.atguigu.array;

    public class MyArrayList {

    private int[] arr = new int[5];//装数据

    private int total;//记录实际存储的元素的个数

    //删除指定位置的元素

    public void delete(int index){

      //(1)把index右边的元素左移
    
      /*
    
       * 假设现在total=3,index =1
    
       * 有值的是arr[0],arr[1],arr[2],需要移动的是arr[2]
    
       * 假设现在total=5,index =1
    
       * 现在有值arr[0],arr[1],arr[2],arr[3],arr[4],需要移动的似乎arr[2],arr[3],arr[4]
    
       */
    
      for(int i = index+1; i<total; i++){
    
      	//左边的元素=右边的元素
    
      	arr[i-1] = arr[i];
    
      }
    
    
    
      //(2)把最后一个元素的位置置为“空”(还原到默认值)
    
      arr[total-1] = 0;
    
    
    
      //(3)元素个数减一
    
      total--;
    

    }

    }

  • 删除指定的元素值

    package com.atguigu.array;

    public class MyArrayList {

    private int[] arr = new int[5];//装数据

    private int total;//记录实际存储的元素的个数

    //删除指定位置的元素

    public void delete(int index){

      //(1)把index右边的元素左移
    
      /*
    
       * 假设现在total=3,index =1
    
       * 有值的是arr[0],arr[1],arr[2],需要移动的是arr[2]
    
       * 假设现在total=5,index =1
    
       * 现在有值arr[0],arr[1],arr[2],arr[3],arr[4],需要移动的似乎arr[2],arr[3],arr[4]
    
       */
    
      for(int i = index+1; i<total; i++){
    
      	//左边的元素=右边的元素
    
      	arr[i-1] = arr[i];
    
      }
    
    
    
      //(2)把最后一个元素的位置置为“空”(还原到默认值)
    
      arr[total-1] = 0;
    
    
    
      //(3)元素个数减一
    
      total--;
    

    }

    public int findValue(int value){

      //挨个遍历,一共有total,遍历total个
    
      for (int i = 0; i < total; i++) {
    
      	if(arr[i] == value){
    
      		return i;
    
      	}
    
      }
    
      return -1;
    

    }

    public void deleteValue(int value){

      //1、先找到value在数组中的index,这里以第一次找到为准
    
      int index = findValue(value);
    
    
    
      //2、删除index位置的元素
    
      if(index!=-1){
    
      	delete(index);
    
      }
    

    }

    }

6.10 (10)在数组中查找某个值的下标

package com.atguigu.array;

public class MyArrayList {

private int[] arr = new int[5];//装数据

private int total;//记录实际存储的元素的个数



//删除指定位置的元素

public void delete(int index){

	//(1)把index右边的元素左移

	/*

	 * 假设现在total=3,index =1

	 * 有值的是arr[0],arr[1],arr[2],需要移动的是arr[2]

	 * 假设现在total=5,index =1

	 * 现在有值arr[0],arr[1],arr[2],arr[3],arr[4],需要移动的似乎arr[2],arr[3],arr[4]

	 */

	for(int i = index+1; i<total; i++){

		//左边的元素=右边的元素

		arr[i-1] = arr[i];

	}



	//(2)把最后一个元素的位置置为“空”(还原到默认值)

	arr[total-1] = 0;



	//(3)元素个数减一

	total--;

}



public int findValue(int value){

	//挨个遍历,一共有total,遍历total个

	for (int i = 0; i < total; i++) {

		if(arr[i] == value){

			return i;

		}

	}

	return -1;

}



public void deleteValue(int value){

	//1、先找到value在数组中的index,这里以第一次找到为准

	int index = findValue(value);



	//2、删除index位置的元素

	if(index!=-1){

		delete(index);

	}

}

}

7 二维数组

7.1 如何声明

  • 数组类型 数组名;

    • 数组类型是xx[][]
  • 元素的类型[][] 数组名;

7.2 如何创建二维数组对象及初始化

  • 动态初始化

    • 数组名 = new 元素的数据类型[行长度][每一行的列长度];

      • 每一行的列数相同
    • 数组名 = new 元素的数据类型[行长度][];

      • 每一行的列数不确定

      • 每一行的行对象暂时是null

      • 创建每一行的行对象,即为行分配空间

        • 数组名[行下标] = new 元素的类型[该行的列数];
  • 静态初始化

    • 数组名 = new 元素的数据类型[][]{{x,x,x,x,….},{x,x,x},{x,x,x,x,x,x,x},…..};

      • {}中嵌套{},里面的一个{}代表一行

7.3 二维数组的长度,即行数

  • 二维数组名.length

7.4 二维数组的行对象

  • 二维数组名[行下标]

    • 行下标的范围[0,二维数组名.length-1]

7.5 二维数组的每一行的列数

  • 二维数组名[行下标].length

7.6 二维数组的每一个元素

  • 二维数组名[行下标][列下标]

    • 注意列下标

      • 每一行的列下标的范围可能是不一样
      • [0, 二维数组名[行下标].length)
  • 二维数组名[行下标][列下标] = 值

7.7 二维数组的遍历

  • for

    • for(int i=0; i<数组名.length; i++){ for(int j=0; j<数组名[i].length; j++){ 数组名[i][j]表示一个元素 } }
  • 增强for

    • for(行类型 hang : 二维数组名){ for(元素类型 lie : hang){ lie就是代表每一个元素 } }

8 数组的内存图

8.1 一维数组

  • 元素是基本数据类型

  • 元素是引用数据类型,又称为对象数组

8.2 二维数组

  • 元素是基本数据类型

    • 规则

    • 不规则

  • 元素是引用数据类型

    • 规则

    • 不规则

9 数组的工具类

9.1 java.util.Arrays

9.2 静态方法

  • (1)int Arrays.binarySearch(int[] a ,int key)

    • 在a数组中查找key的下标
    • (1)数组a必须是有序的,否则结果不一定正确
    • (2)如果key在a中存在,就返回它的下标,如果不存在,返回(-(插入点)-1)
  • (2)Arrays.fill(int[] a, int value)

    • 给数组a的每一个元素都赋值为value
  • (3)Arrays.sort(int[])

    • 排序,从小到大
  • (4)String Arrays.toString(int[] a)

    • 把数组的元素列表用字符串返回,形式[元素1,元素2,元素3.。。]

10 命令行参数

10.1 主方法的参数

10.2 java命令

  • java 包.类名 参数1 参数2 参数3 ….

    • 参数之间使用空格

10.3 eclipse

11 可变参数

11.1 可变参数属于形参

11.2 要求

  • 一个方法只能有一个可变参数,而且只能是最后一个
  • 在声明它的方法中,当做数组处理
  • 对于调用这个方法者,可变参数的位置可以传,[0~n]个实参,也可以传对应类型数组对象

11.3 可变参数的重载问题

  • 对于编译器来说不属于重载

    • 不属于重载

      • public static void main(String[] args) { System.out.println(getSum(1)); }

    public static int getSum(int… args){ return 0; } public static int getSum(int a,int… args){ return 0; }

      	- 如果传一个整数时,不知道用谁好
    
      - 	public static int getSum(int... args){
      return 0;
    

    }

    public static int getSum(int[] args){

    }

      	- 但是它俩不完全等价
    
      		- 因为int... args既可以传数组对象,又可以传 n个元素值
      		- int[]只能传数组对象
    
    • 属于重载

      • public static void main(String[] args) { System.out.println(getSum(1)); }

    public static int getSum(int… args){ return 0; } public static int getSum(int a){ System.out.println(“一个参数”); return 0; }

      	- 优先于确定参数个数