一、String[] args
主要用在当我们执行Java程序(java 字节码文件)的时候 可以指定一些参数的。
class Test01{
public static void main(String[] args){//args只是变量名,可以换其他名字
System.out.println(args.length);
for(int i=0;i<args.length;i++){
System.out.println(args[i]);
}
}
}
javac Test01.java 编译后,再 java Test01 a b c 运行后
会输出:
3
a
b
c
二、可变长参数
当我们在给一个函数传参的时候,如果我们不确定具体传参数的个数的话,可以使用可变长参数(这些参数必须是相同的类型)
可变长参数本质上就是一个数组
class Test02{
public static void main(String[] args){
multiArguments(1,2,3,4,5,6,7);//里面的个数可以更改
}
//传入的是不确定个数的int型参数
public static void multiArguments(int ... nums){
System.out.println(nums.length);
for(int num : nums){
num=1;
}
for(int num : nums){
System.out.println(num);
}
System.out.println();
}
public static void multiArguments(double ... nums){
System.out.println(nums.length);
for(int i=0;i<nums.length;i++){
System.out.print(nums[i]+" ");
}
System.out.println();
}
}
注意:一个参数列表当中最多只能出现一个可变长参数,如有多个可变长参数编译报错;而且如果还有其他类型的数据,一定要放在可变长参数前后面,放在后面的话,运行后传入的数据在都被可变长参数拿走了。
三、foreach循环
其实是一个简化过后的for循环
for(循环数据类型 循环变量名 : 可迭代对象 ){
循环体;
}
/*
for(循环数据类型 循环变量名 : 可迭代对象 ){
循环体;
}
num其实表示的是nums[i] i∈[0~nums.length)
只不过在foreach中 屏蔽掉了i的具体行为
数组是可迭代对象当中的一种 并且数组可以通过角标访问
所以目前你可以认为num等效于nums[i]
但是并不代表所有的可迭代对象都有角标支持!
有些可迭代对象的元素访问顺序是比较复杂的,所以foreach就是为了避免这些复杂才出现的
foreach有什么样的一个缺点呢
它仅仅只能访问元素 不能对元素进行修改
num仅仅是nums[i]的一个备份 改num不代表改nums[i]
如果仅仅访问元素的话 foreach更简单
*/
再上边那个知识点中已经有了foreach的应用,这里就不再展示代码了。
for(int num : nums){//改num不等于该变nums[i]
num=1;
}
for(int num : nums){
System.out.println(num);
}
System.out.println();
四、Arrays类
是关于数组的工具类;Math、Scanner、String(不是工具类)。
函数:
static int binarySearch(int[] a, int key)
使用二分搜索法来搜索指定的 int 型数组,以获得指定的值。 |
public static int binarySearch(Integer[] srcArray, int des) {
//定义初始最小、最大索引
int start = 0;
int end = srcArray.length - 1;
//确保不会出现重复查找,越界
while (start <= end) {
//计算出中间索引值
int middle = (end + start)>>>1 ;//防止溢出
if (des == srcArray[middle]) {
return middle;
//判断下限
} else if (des < srcArray[middle]) {
end = middle - 1;
//判断上限
} else {
start = middle + 1;
}
}
//若没有,则返回-1
return -1;
}
static void sort(int[] a)
对指定的 int 型数组按数字升序进行排序 |
一般而言用插入排序
public static void sort(int[] arr){
int e;
int j;
for(int i=1;i<arr.length;i++){
e = arr[i];
int index = i;
for(j=i;j>0;j--){
if(arr[j-1]>e){
arr[j] = arr[j-1];
index = j-1;
}
}
arr[index] = e;
}
for(int i=1;i<arr.length;i++){
for(int j=i;j>0;j--){
if(arr[j-1]>arr[j]){
swap(arr,j);
}
}
}
System.out.println(Arrays.toString(arr));
}
Arrays.sort()使用了两种排序方法,快速排序和优化的归并排序。
快速排序主要是对那些基本类型数据(int,short,long等)排序, 而归并排序用于对Object类型进行排序。
使用不同类型的排序算法主要是由于快速排序是不稳定的,而归并排序是稳定的。这里的稳定是指比较相等的数据在排序之后仍然按照排序之前的前后顺序排列。对于基本数据类型,稳定性没有意义,而对于Object类型,稳定性是比较重要的,因为对象相等的判断可能只是判断关键属性,最好保持相等对象的非关键属性的顺序与排序前一致;另外一个原因是由于归并排序相对而言比较次数比快速排序少,移动(对象引用的移动)次数比快速排序多,而对于对象来说,比较一般比移动耗时。
此外,对大数组排序。快速排序的sort()采用递归实现,数组规模太大时会发生堆栈溢出,而归并排序sort()采用非递归实现,不存在此问题。总结:
首先先判断需要排序的数据量是否大于60。
小于60:使用插入排序,插入排序是稳定的
大于60的数据量会根据数据类型选择排序方式:
基本类型:使用快速排序。因为基本类型。1、2都是指向同一个常量池不需要考虑稳定性。
Object类型:使用归并排序。因为归并排序具有稳定性。
注意:不管是快速排序还是归并排序,在二分的时候小于60的数据量依旧会使用插入排序。
static int[] copyOf(int[] original, int newLength)
复制指定的数组,截取或用 0 填充(如有必要),以使副本具有指定的长度。 |
public static int[] copyOf(int[] arr,int newLen){
int[] newArr=new int[newLen];
for(int i=0;i<arr.length;i++){
newArr[i]=arr[i];
}
return newArr;
}
static String toString(int[] a)
返回指定数组内容的字符串表示形式。 |
public static void toString(int[] arr){
//[1,2,3,4,5,6,7,8,9]
String s="[";
for(int i=0;i<arr.length;i++){
if(i==arr.length-1){
s+=arr[i]+"]";
}else{
s+=arr[i]+",";
}
}
System.out.println(s);
}
static boolean equals(int[] a, int[] a2)
如果两个指定的 int 型数组彼此相等,则返回 true。 |
public static boolean equals(int[] list1,int[] list2){
//判断两个数组是否完全相同
//1.先判断长度
if(list1.length!=list2.length){
return false;
}
//2.再依次判断元素大小
for(int i=0;i<list1.length;i++){
if(list1[i]!=list2[i]){
return false;
}
}
return true;
}
五、多返回值处理
Java的函数仅仅只能返回单一的值;
如果需要一次性返回多个值怎么办;将个值封装在一个数组当中即可,后期会学到集合/映射。这个到后边再补充。
如果是C/C++语言的话 只需要传x 和 y的指针(就是x和y的地址)即可,而且move这个函数不需要返回值。
java只能拿到常量在常量池的地址,拿不到变量的地址,所以需要把多返回值封装到一个数组中进行返回即可。
class Test02{//java
public static void main(String[] args){
//传入一个坐标点,将坐标点进行移动
int x=0;
int y=0;
int[] res=move(x,y,10,10);
x=res[0];
y=res[1];
System.out.println("x="+x);
System.out.println("y="+y);
}
public static int[] move(int x,int y,int deltx,int delty){
x+=deltx;
y+=delty;
return new int[]{x,y};
}
}
#include<stdio.h>//c/c++
void move(int *x,int *y,int deltx,int delty);
int main(void)
{
int x=0;
int y=0;
move(&x,&y,10,10);
printf("%d,%d",x,y);
return 0;
}
void move(int *x,int *y,int deltx,int delty)
{
*x+=deltx;
*y+=delty;
}