一、语言基础---5.数组高级
(一)方法参数的值传递机制
097、main方法的数组参数
public class Hello
{
/*
main方法是static修饰的,说明直接使用类名Hello类调用即可
在底层是JVM通过Hello.main(new String[]{});
main方法的String数组参数,其实是暴露给程序运行者的,用于给程序传递一个数据信息。
*/
public static void main(String[] args) //参数:参数类型String[] 参数名称args
{
System.out.println(args.length);
for (int index = 0; index < args.length ; index ++ )
{
System.out.println(args[index]);
}
}
}
用法: java [-options(执行类)] class [args...]
098、参数的值传递机制-基本数据类型
在栈里面(不需要垃圾回收器),方法调用完毕后就栈帧销毁了,所以调用完change()方法后,change方法的栈帧就移出栈了,main方法的栈帧就到了栈的顶部,继续执行
//参数的值传递机制-基本数据类型
class ParameterDemo
{
public static void main(String[] args)
{
int x = 10;
System.out.println("main方法前,x:" + x); //10
change(x); //改变x变量
System.out.println("main方法后,x:" + x); //10
}
static void change(int x) //修改变量方法
{
System.out.println("change方法前,x:" + x); //10
x = 50;
System.out.println("change方法后,x:" + x); //50
}
}
099、参数的值传递机制-引用数据类型
//参数的值传递机制-引用数据类型
class ParameterDemo1
{
public static void main(String[] args)
{
int[] arr = new int[]{10,99};
printArray(arr); //[10,99]
swap(arr); //交换第一个和最后一个元素的值
printArray(arr);
}
static void swap(int[] arr)
{
int temp = arr[0]; //把第一个元素赋值给temp
arr[0] = arr[arr.length - 1]; // 把最后一个元素赋值给第一个元素位置
arr[arr.length - 1] = temp;
}
//打印数组的方法
static void printArray(int[] arr) //String[] arr = null;
{
if (arr == null)
{
System.out.println("null");
return; //结束方法
}
String ret = "[";
for (int index = 0; index < arr.length ; index ++ )
{
ret = ret + arr[index];
if (index != arr.length - 1) //如果当前index不是最后一个索引,则拼接“,”
{
ret = ret + ",";
}
}
ret = ret +"]";
System.out.println(ret);
}
}
(二)多维数组
100、数组中的数组-多维数组
数组的语法:数组元素类型[] 数组名
一维数组:数组中的每一个元素都是一个值(基本类型和引用类型的值)
二维数组:数组中的每一个元素又是一个一维数组
三维数组:数组中的每一个元素又是一个二维数组
严格上说,在java中不存在多维数组的概念,和C语言做区分,一般称之为数组中的数组
int[] arr1 = {1,2,3};
int[] arr2 = {4,5};
int[] arr3 = {6};
//把上述的每一个数组都作为一个元素,那么此时元素的类型为int[]
int[][] arr = new int[][] {arr1,arr2,arr3}; //二维数组 int[][] arr = new int[][] {{1,2,3},{4,5},{6}};
101、多维数组的操作
二维数组的初始化操作:
静态初始化: int[][] arr = new int[][] {{1,2,3},{4,5},{6}};
动态初始化:int[][] arr = new int[3][5]; 创建一个长度为3的二维数组,每一个元素(一维数组)的长度为5
class ArrayInArrayDemo
{
public static void main(String[] args)
{
int[][] arr = new int[][] {
{1,2,3},
{4,5},
{6}
};
System.out.println(arr.length); //3
for (int i = 0; i < arr.length ; i ++ )
{
System.out.println(arr[i]); //打印出的是数组中
for (int j = 0; j < arr[i].length ; j++ )
{
System.out.println(arr[i][j]);
}
}
}
}
(三)Java5对数组的支持
102、Java5对数组的支持-for循环增强
需求:定义一个数组,使用循环迭代出数组中的每一个元素
使用for循环的操作如下:
//增强for循环--foreach
class ForeachDemo
{
public static void main(String[] args)
{
int[] nums = new int[] {10,20,30,40,50};
//使用循环迭代出数组中的每一个元素
for (int index = 0; index < nums.length ; index ++ )
{
System.out.println(nums[index]);
}
}
}
在使用循环迭代数组的时候,是不关心迭代变量(数组的索引)。迭代数组元素的时候,就只操作数组元素,不去操作数组的索引
从java5(jdk1.5),提供了一种新语法:增强for循环(foreach)
语法:
for(数组元素类型 变量 : 数组名)
{
循环体
}
//增强for循环--foreach
class ForeachDemo
{
public static void main(String[] args)
{
int[] nums = new int[] {10,20,30,40,50};
for(int ele :nums) //(数组元素类型:数组名)
{
System.out.println(ele);
}
}
}
103、Java5对数组的支持-方法的可变参数
需求:编写一个方法,统计使用数组传递过来的总和
class VarArgsDemo
{
public static void main(String[] args)
{
double[] ps = new double[]{10.0,20.0,30.0,40.0,50.0};
double sum = getSum(ps); //调用getSum方法
System.out.println(sum);
}
//计算总和
static double getSum(double[] arr)
{
double sum = 0.0;
for (double price : arr ) //循环取出每一个元素
{
sum = sum +price;
}
return sum;
}
}
class VarArgsDemo
{
public static void main(String[] args)
{
//double[] ps = new double[]{10.0,20.0,30.0,40.0,50.0};
double sum = getSum(0.7,10.0,20.0,30.0,40.0,50.0); //调用getSum方法
System.out.println(sum);
}
//计算总和
static double getSum(double cutoff, double ... arr) // ... 方法的可变参数(个数可变);可变参数必须作为方法的最后一个参数,避免参数歧义性
{
double sum = 0.0;
for (double price : arr ) //循环取出每一个元素
{
sum = sum +price;
}
return sum * cutoff;
}
}
方法的可变参数其底层就是一个数组类型
推论:方法最多只能有一个可变参数
(四)数组算法
104、实现int类型数组元素拷贝
//数组元素拷贝
class ArrayCopeDemo
{
public static void main(String[] args)
{
int[] src = new int[]{1,2,3,4,5,6,7,8,9,10}; // 源数组
int[] dest = new int[10]; //目标数组
//需求:从 src数组中拷贝3,4,5,6元素到dest数组中
printArray(dest); //[0,0,0,0,0,0,0,0,0,0]
copy(src,2,dest,5,4); //拷贝操作
printArray(dest); //[0,0,0,0,0,3,4,5,6,0]
}
/* 参数:
src:源数组
srcPos:从源数组中哪一个索引位置开始拷贝
dest:目标数组
destPos:在目标数组中哪一个索引位置开始粘贴
length:拷贝元素个数
*/
static void copy(int[] src, int srcPos, int[] dest, int destPos, int length)
{
/*原始方法
//拷贝3
dest[destPos] = src[srcPos];
srcPos++; destPos++;
//拷贝4
dest[destPos] = src[srcPos];
srcPos++; destPos++;
//拷贝5
dest[destPos] = src[srcPos];
srcPos++; destPos++;
//拷贝6
dest[destPos] = src[srcPos];
srcPos++; destPos++;
*/
for (int index = srcPos; index <srcPos + length ; index ++) //index表示每次需要拷贝元素的索引
{
dest[destPos] = src[index];
destPos++;
}
}
//打印数组方法
static void printArray(int[] arr) //String[] arr = null;
{
if (arr == null)
{
System.out.println("null");
return; //结束方法
}
String ret = "[";
for (int index = 0; index < arr.length ; index ++ )
{
ret = ret + arr[index];
if (index != arr.length - 1) //如果当前index不是最后一个索引,则拼接“,”
{
ret = ret + ",";
}
}
ret = ret +"]";
System.out.println(ret);
}
}
代码存在的问题:1.只能拷贝int类型数组;2.代码不够健壮
105、System类中的arraycopy方法
需求:支持任意类型数组元素拷贝操作(反射)
数组拷贝操作,是经常使用到的,Sun公司直接把拷贝操作存放在JDK中的System类中
Object:Java语言中的根类,Object可以表示任意类型数据
该方法没有方法体,该方法使用了native修饰符(本地方法),该方法底层使用了C/C++语言实现了,Java直接调用其他语言编写好的功能
System.arraycopy(src,2,dest,5,4); //调用数组拷贝方法
查阅API文档(Java的帮助文档),什么类中有什么功能的方法即可,文档在手,天下我有
106、排序算法-冒泡排序
//数组排序操作
class ArraySortDemo
{
public static void main(String[] args)
{
int[] arr = {2,9,6,7,4,1};
printArray(arr); //[2,9,6,7,4,1]
bubbleSort(arr); //排序
printArray(arr);
System.out.println("Hello World!");
}
//冒泡排序
static void bubbleSort(int[] arr)
{
for (int times = 1; times <= arr.length - 1 ;times ++ ) //times=1,2,3,4,5
{
for (int i = 1; i <= arr.length -times ; i++ )
{
if (arr[i - 1] > arr[i])
{
swap(arr,i-1,i);
}
}
}
/*
//第一轮比较:比较5次,完毕之后出现最大值
for (int i = 1; i <= arr.length -1 ; i++ )
{
if (arr[i - 1] > arr[i])
{
swap(arr,i-1,i);
}
}
//第二轮比较:比较4次,完毕之后出现第二大值
for (int i = 1; i <= arr.length -2 ; i++ )
{
if (arr[i - 1] > arr[i])
{
swap(arr,i-1,i);
}
}
//第三轮
for (int i = 1; i <= arr.length -3 ; i++ )
{
if (arr[i - 1] > arr[i])
{
swap(arr,i-1,i);
}
}
//第四轮
for (int i = 1; i <= arr.length -4 ; i++ )
{
if (arr[i - 1] > arr[i])
{
swap(arr,i-1,i);
}
}
第五轮
for (int i = 1; i <= arr.length -5 ; i++ )
{
if (arr[i - 1] > arr[i])
{
swap(arr,i-1,i);
}
}
*/
}
//交换两个元素位置
static void swap(int[] arr, int index1, int index2)
{
int temp = arr[index1];
arr[index1] = arr[index2];
arr[index2] = temp;
}
//打印数组元素
static void printArray(int[] arr) //String[] arr = null;
{
if (arr == null)
{
System.out.println("null");
return; //结束方法
}
String ret = "[";
for (int index = 0; index < arr.length ; index ++ )
{
ret = ret + arr[index];
if (index != arr.length - 1) //如果当前index不是最后一个索引,则拼接“,”
{
ret = ret + ",";
}
}
ret = ret +"]";
System.out.println(ret);
}
}
107、选择排序
//数组排序操作
class ArraySortDemo1
{
public static void main(String[] args)
{
int[] arr = {2,9,6,7,4,1};
printArray(arr); //[2,9,6,7,4,1]
selectionSort(arr); //排序
printArray(arr);
System.out.println("Hello World!");
}
//选择排序
static void selectionSort(int[] arr)
{
for (int times = 1; times <= arr.length - 1 ; times ++ )
{
for (int i = times; i <= arr.length -1 ; i++ )
{
if (arr[times - 1] > arr[i])
{
swap(arr,times - 1,i);
}
}
}
/*
//第一轮比较:选定一个位置后,比较5次,完毕之后出现最小值
for (int i = 1; i <= arr.length -1 ; i++ )
{
if (arr[0] > arr[i])
{
swap(arr,0,i);
}
}
//第二轮比较:比较4次,完毕之后出现第二小值
for (int i = 2; i <= arr.length -1 ; i++ )
{
if (arr[1] > arr[i])
{
swap(arr,1,i);
}
}
//第三轮
for (int i = 3; i <= arr.length -1 ; i++ )
{
if (arr[2] > arr[i])
{
swap(arr,2,i);
}
}
//第四轮
for (int i = 4; i <= arr.length -1 ; i++ )
{
if (arr[3] > arr[i])
{
swap(arr,3,i);
}
}
//第五轮
for (int i = 5; i <= arr.length -1 ; i++ )
{
if (arr[4] > arr[i])
{
swap(arr,4,i);
}
}
*/
}
//交换两个元素
static void swap(int[] arr, int index1, int index2)
{
int temp = arr[index1];
arr[index1] = arr[index2];
arr[index2] = temp;
}
//打印数组元素
static void printArray(int[] arr) //String[] arr = null;
{
if (arr == null)
{
System.out.println("null");
return; //结束方法
}
String ret = "[";
for (int index = 0; index < arr.length ; index ++ )
{
ret = ret + arr[index];
if (index != arr.length - 1) //如果当前index不是最后一个索引,则拼接“,”
{
ret = ret + ",";
}
}
ret = ret +"]";
System.out.println(ret);
}
}
//选择排序,每一次循环只交换一次
static void selectionSort(int[] arr)
{
for (int times = 0; times < arr.length - 1 ; times ++ )
{
int minIndex = times;
for (int i = times + 1; i < arr.length ; i++ )
{
if (arr[i] < arr[minIndex])
{
minIndex = i;
}
}
swap(arr,times,minIndex);
}
108、搜索算法-二分法搜索
数组的搜索算法,从指定数组中去搜索某一个元素的索引是多少
方式一:线性搜索(从头搜到尾/从尾搜到头):indexOf / lastIndexOf ,对于元素过多的数组,性能极低。有N个元素,循环次数 =(N+1)/2
方式二:二分搜索/二分查找/折半查找 前提:数组元素必须有序
//二分查找法
class BinarySearcherDemo
{
public static void main(String[] args)
{
int[] arr = {1,2,3,4,5,6,7,8,9,10};
int index = binarySearch(arr,8); //返回8对应的索引
System.out.println(index);
}
//从arr数组中搜索key的元素,找到返回其索引,否则返回-1
static int binarySearch(int[] arr, int key)
{
int low = 0; //最小的索引
int high = arr.length - 1; //最大的索引
while (low <= high)
{
System.out.println(low +"---" + high);
int mid = (low + high)/2; //中间索引 (low + high) >> 1
int midVal = arr[mid];
if (midVal > key) //猜大了
{
high = mid -1;
}
else if (midVal < key) //猜小了
{
low = mid +1;
}
else
{
return mid;
}
}
return -1;
}
//打印数组元素
static void printArray(int[] arr) //String[] arr = null;
{
if (arr == null)
{
System.out.println("null");
return; //结束方法
}
String ret = "[";
for (int index = 0; index < arr.length ; index ++ )
{
ret = ret + arr[index];
if (index != arr.length - 1) //如果当前index不是最后一个索引,则拼接“,”
{
ret = ret + ",";
}
}
ret = ret +"]";
System.out.println(ret);
}
}
109、自行封装数组操作的工具类ArrayUtil
打印数组元素:print
颠倒数组元素:reverse
获取元素索引:indexOf / lastIndexOf
获取元素最值:getMax / getMin
拷贝数组元素:arraycopy
数组元素排序:sort
二分查找方法:binarySearch
针对于数组来说,上述方法会经常使用到,在A类中使用,得把上述方法拷贝到A类中去使用。在B类中使用,得把上述方法拷贝到B类中去使用。重复的功能被定义了N次!
定义一个专门的类(数组的工具类),类中涵盖数组相关的算法的方法,我们只需要ArrayUtil.sort(数组...),就完成排序操作
Crtl+F11查找方法
//数组工具类,涵盖了很多操作数组的方法
class ArrayUtil
{
//打印数组
static void printArray(int[] arr) //int[] arr = 0;
{
if (arr == null)
{
System.out.println("null");
return; //结束方法
}
String ret = "[";
for (int index = 0; index < arr.length ; index ++ )
{
ret = ret + arr[index];
if (index != arr.length - 1) //如果当前index不是最后一个索引,则拼接“,”
{
ret = ret + ",";
}
}
ret = ret +"]";
System.out.println(ret);
}
//索引
static int binarySearch(int[] arr, int key)
{
int low = 0; //最小的索引
int high = arr.length - 1; //最大的索引
while (low <= high)
{
System.out.println(low +"---" + high);
int mid = (low + high)/2; //中间索引 (low + high) >> 1
int midVal = arr[mid];
if (midVal > key) //猜大了
{
high = mid -1;
}
else if (midVal < key) //猜小了
{
low = mid +1;
}
else
{
return mid;
}
}
return -1;
}
//交换两个元素
static void swap(int[] arr, int index1, int index2)
{
int temp = arr[index1];
arr[index1] = arr[index2];
arr[index2] = temp;
}
//冒泡排序
static void bubbleSort(int[] arr)
{
for (int times = 1; times <= arr.length - 1 ;times ++ ) //times=1,2,3,4,5
{
for (int i = 1; i <= arr.length -times ; i++ )
{
if (arr[i - 1] > arr[i])
{
swap(arr,i-1,i);
}
}
}
}
}
class ArrayUtilDemo
{
public static void main(String[] args)
{
int[] arr = {1,3,1,2,0,9,6,-3};
//搜索6的索引
ArrayUtil.printArray(arr);//打印数组
ArrayUtil.bubbleSort(arr);//排序
ArrayUtil.printArray(arr);//排序后打印数组
int index = ArrayUtil.binarySearch(arr , 6); //返回6对应的索引
System.out.println(index);
}
}
110、Java内置数组工具类Arrays
java-->util-->Arrays.java
//演示数组的工具类:Arrays类
class ArraysDemo
{
public static void main(String[] args)
{
int[] arr = {1,3,1,2,0,9,6,-3}; //定义一个数组
String ret = java.util.Arrays.toString(arr); //打印
System.out.println(ret); //[1, 3, 1, 2, 0, 9, 6, -3]
java.util.Arrays.sort(arr); //排序
System.out.println(java.util.Arrays.toString(arr)); //[-3, 0, 1, 1, 2, 3, 6, 9]
int index = java.util.Arrays.binarySearch(arr,1); //索引
System.out.println(index); //3
}
}
111、小结