相信大家对C/C++中的数组相关操作比较熟悉,而它在Java中的使用有些不一样的地方。
主要有:
1)声明是用elementType [ ] array;的形式(当然C/C++中的声明方式如elementType array[ ]也行,但在Java中不推荐),其中array叫做引用变量。与C/C++不同的是声明一个数组并不分配内存空间,只有创建的时候才分配;
2)创建:elementType [ ] array = new elementType [size];这样才会分配内存空间;
3)数组作为参数传递时,传递的是引用(java中没有指针,但是我感觉引用和指针从对内存中变量值的改变来讲有一丁点形似),所以被调方法体中对变量的改变也会改变调用者参数的值,这一点和C/C++有很大区别的!
4)针对Java的数组,还有个专门的for-each循环,这个用起来也是很方便的。
5)数组的复制方式不同,内存的变化是不一样的,如数组list2 = list1的操作,将list1的引用赋值给了list2,而list2原来的引用就会被Java虚拟机当成垃圾自动清除;还有方法调用中作为参数传递;System类中的arraycopy;
对于以上几点的不同,给出一个简单的程序帮助理解,请童鞋们跑跑程序自己体会。源代码如下所示:
package Arrays;
public class arraysPractice {
//数组值传递的几种方式,注意其中内存值的变化
public static void main(String [] args){
int[] list1 = new int[10];
int[] list2 = new int[10];
for(int i = 0;i < 10;i++){
list1[i] = i;
list2[i] = i+1;
}
System.out.println("list1 is ");
for(int u:list1)//for-each循环
System.out.print(u+" ");
System.out.println("\nlist2 is ");
for(int u:list2)
System.out.print(u+" ");
System.out.println();
System.out.println("list2 to list1,and list2 is ");
list2 = list1;//将list1的引用值复制给了list2,list2原来引用的数组不能继续引用
for(int u:list2)
System.out.print(u+" ");
System.out.println();
System.out.println("arraycoppy list2 to list1 ");
System.arraycopy(list2, 0, list1, 0, list1.length);//System类方法传递数组
//list1和list2具有相同的内容,但有独立的内存空间
for(int u:list2)
System.out.print(u+" ");
//给方法传递的是这个引用,参数传递的共享信息,即方法中的数组和传递的数组是一样的,值会以期改变
printArray(new int[]{3,1,2,6,4,2});//给方法传递数组,匿名数组
int x = 1;
int[] y = new int[10];
m(x,y);
System.out.println("\nx is "+x);
System.out.println("y[0] is +"+y[0]);
int[] a = {1,2};
System.out.println("Befor invoking swap");
System.out.println("array is {"+a[0]+","+a[1]+"}");
swap(a[0],a[1]);
System.out.println("After invoking swap");
System.out.println("array is {"+a[0]+","+a[1]+"}");
System.out.println("Befor invoking swapFirstTwoInArray");
System.out.println("array is {"+a[0]+","+a[1]+"}");
swapFirstTwoInArray(a);
System.out.println("After invoking swapFirstTwoInArray");
System.out.println("array is {"+a[0]+","+a[1]+"}");
}
public static void swap(int n1,int n2){
int temp = n1;
n1 = n2;
n2 = temp;
}
public static void swapFirstTwoInArray(int[] array){
int temp = array[0];
array[0] = array[1];
array[1] = temp;
}
public static void m(int number,int[] numbers){
number = 1001;
numbers[0] = 5555;
}
public static void printArray(int[] array){
System.out.println("\nprintArray is ");
for(int i = 0;i < array.length;i++)
System.out.print(array[i]+" ");
}
}
运行结果如右图所示:
理解了上述数组的基本概念之后,就可以进行诸如排序,查找方法的设计了,之前介绍过用方法的思想进行编程,所以接下来的设计都基于用方法来实现,这样main方法可以用方法的“集合”来编写,看起来方便,便于理解,而且代码重用性也很高。对后续的开发而言更加方便。
示例一:数组建立、查找、乱序、排序(线性和二分)集锦(为了熟悉数组,一定自己先进行设计)。代码如下所示:
package Blog;
import java.util.Scanner;
public class blogTryProject {
//数组建立、查找、乱序、排序集锦
public static void main(String [] args){ //main方法
int[] check = creatChars(10);
printTheNumberForLinearFind(linearFind(check, 11),11);//线性查找及其打印
printTheNumberForLinearFind(linearFind(check, 3),3);
printTheNumberForMidFind(midFind(check,16), 16);//二分查找及其打印
printTheNumberForMidFind(midFind(check,2), 2);
upSet(check);//随机乱序目标数组
check = chooseSort(check);//选择排序
printArray(check);//打印数组
upSet(check);
check = insertSort(check);
printArray(check);
}
//插入法排序
public static int[] insertSort(int[] chars){
System.out.println("\ninsertSort");
for(int i = 1;i < chars.length;i++){
for(int j = 0;j < i;j++){
if(chars[i] < chars[j]){
int temp = chars[i];
chars[i] = chars[j];
chars[j] = temp;
}
}
}
return chars;
}
//选择法排序
public static int[] chooseSort(int[] chars){
System.out.println("\nchooseSort");
for(int i = 0;i <chars.length;i++){
int currentMin = chars[i];
int currentMinIndex = i;
for(int j = i + 1;j < chars.length;j++){
if(currentMin > chars[j]){
currentMin = chars[j];
currentMinIndex = j;
}
}
if(currentMinIndex != i){
chars[currentMinIndex] = chars[i];
chars[i] = currentMin;
}
}
return chars;
}
//乱序
public static void upSet(int[] chars) {
System.out.print("\n随意打乱前的数组为:");
for(int u:chars){
System.out.print(u+" ");
}
for(int i = 0;i < chars.length;i++){
int index = (int)(Math.random()*chars.length);
int temp = chars[i];
chars[i] = chars[index];
chars[index] = temp;
}
System.out.print("\n随意打乱后的数组为:");
for(int u:chars){
System.out.print(u+" ");
}
}
//打印二分法查找的数组元素位置
public static void printTheNumberForMidFind(int i,int key){
if(i >= 0)
System.out.println(key+"是数组的元素!");
else
System.out.println(key+"不是数组的元素!");
}
//打印线性法查找的数组元素位置
public static void printTheNumberForLinearFind(int i,int key){
if(i == -1)
System.out.println(key+"不是数组的元素!");
else
System.out.println(key+"是数组的第"+(i+1)+"个元素!");
}
//二分查找
public static int midFind(int[] check,int key){
int low = 0;
int high = check.length - 1;
int mid = (low + high) / 2;
while(low <= high){
if(check[mid] == key)
return mid;
else if(check[mid] > key){
high = mid - 1;
mid = (low + high) / 2;
}
else{
low = mid + 1;
mid = (low + high) / 2;
}
}
return -low - 1;
}
//线性查找
public static int linearFind(int[] check,int key){
for(int i = 0;i < check.length;i++){
if(key == check[i])
return i;
}
return -1;
}
//创建数组
public static int[] creatChars(int number){
int[] chars = new int[number];
for(int i = 0;i < chars.length;i++)
chars[i] = i+1;
return chars;
}
//打印数组
public static void printArray(int[] chars){
for(int u:chars)
System.out.print(u+" ");
}
}
运行效果如右图所示:
通过上面的学习,作者发现用方法去打印不同的数据类型的数组时需要重新编写方法,用起来很不方便,所以有必要介绍方法的重载,以满足同一功能不同数据类型的需求。重载 就是方法有同样的名称(为了方便程序的阅读识别与编程通常其功能也相同),但是参数列表不相同的情形,这样的同名不同参数的方法之间,互相称之为重载方法。
重载关心的是参数:有参无参,参数类型不同,参数数量不同,不同类型的参数顺序不同,都可以实现方法的重载。而返回值类型的不同、修饰符的不同对重载是没有印象的。
Java中的重载和C/C++中的重载也是有所区别的,后者是“一劳永逸“,前者到目前我的理解是要将不同数据类型的操作复制集成在一个类中的,在调用时先声明一个类,再以调用类中方法的形式使用。下面请看示例程序。
示例二:方法的重载举例。源代码如下所示:
package Arrays;
import java.util.Scanner;
import java.util.Arrays;
public class array {
//一维数组排序、查找及相关方法的重载
public static void main(String [] args){
printSort PS = new printSort();//打印类的函数重载
printFind PF = new printFind();
midFind FM = new midFind();//查找类的函数重载
double[] numbers = {6.0,4.4,1.9,2.9,3.4,3.5};
PS.beforAndAfterSortPrint(numbers);
char[] chars = {'a','A','4','F','D','P'};
PS.beforAndAfterSortPrint(chars);
FM.binarySearch(numbers, 3.4);
FM.binarySearch(chars, 'A');
//Arrays类集成了很多对数组操作的方法,用起来很方便,它包含在java.lang包中,属于预定义类
Arrays.fill(numbers, 3.3);
PF.print(numbers);
Arrays.fill(chars, 0,3,'G');
PF.print(chars);
}
}
class printFind{ //查找打印类,即打印方法的重载
void print(double[]chars){
System.out.println();
for(double u:chars)
System.out.print(u+" ");
System.out.println();
}
void print(char[]chars){
System.out.println();
for(char u:chars)
System.out.print(u+" ");
System.out.println();
}
}
class midFind{ //显示二分查找结果的类
void binarySearch(double[] chars,double num){
System.out.println("\nnumbers(10)的二分查找结果为"
+Arrays.binarySearch(chars, num));
}
void binarySearch(int[] chars,int num){
System.out.println("\nnumbers(10)的二分查找结果为"
+Arrays.binarySearch(chars, num));
}
void binarySearch(char[] chars,char num){
System.out.println("\nnumbers(10)的二分查找结果为"
+Arrays.binarySearch(chars, num));
}
}
class printSort{ //打印排序前后数组元素的类
void beforAndAfterSortPrint(double[] numbers){
overLoad ol = new overLoad();//方法的重载
System.out.println("\nBefore sort");
ol.printArray(numbers);
Arrays.sort(numbers);
System.out.println("\nAfter sort");
ol.printArray(numbers);
}
void beforAndAfterSortPrint(int[] numbers){
overLoad ol = new overLoad();//方法的重载
System.out.println("\nBefore sort");
ol.printArray(numbers);
Arrays.sort(numbers);
System.out.println("\nAfter sort");
ol.printArray(numbers);
}
void beforAndAfterSortPrint(char[] numbers){
overLoad ol = new overLoad();//方法的重载
System.out.println("\nBefore sort");
ol.printArray(numbers);
Arrays.sort(numbers);
System.out.println("\nAfter sort");
ol.printArray(numbers);
}
}
class overLoad{ //直接打印的类
void printArray(double[] chars){
for(double u:chars)
System.out.print(u+" ");
}
void printArray(int[] chars){
for(double u:chars)
System.out.print(u+" ");
}
void printArray(char[] chars){
for(char u:chars)
System.out.print(u+" ");
}
}
运行结果如右图所示:
可以看到上述main方法的编写十分简洁明了,并且后续编程需要相关方法操作时直接调用即可,无需重新编写代码,开发效率成倍提高!