Java中关于数组的一些知识点

一、数组(一维)

对于声明变量,int score1 = 81; 等等这些操作,如果我们有四个成绩,是不是可以定义变量score 1234呢?但是,如果我们要定义400个成绩又当如何呢?

这就可以用到数组了,数组可以指定一个长度,然后在数组里可以存放这个长度范围的同类型元素,可以将数组理解为是一个巨大的“盒子”,里面可以按顺序存放多个类型相同的数据。不过,因为它是由长度范围的,所以长度在声明完成之后就是不能变化的了,对于一些总是需要增加一些信息进去的情况,就不适合于用数组了。如电话簿。你也许会想,能不能一开始就声明一个很长很长的长度用来放数据,但是声明很长是需要占内存的,会拖慢程序的运行速度。(对于这一"缺点",会在之后的集合中得到很好的应用)

 

那么,如何使用 Java 中的数组?Java 中操作数组只需要四个步骤:

 

1、 声明数组

语法:  数据类型[ ] 数组名; 或者 数据类型 数组名[ ];

其中,数组名可以是任意合法的变量名,如:

int[] scores;

double aArray[];

String[] names;

 

2、 分配空间

简单地说,就是指定数组中最多可存储多少个元素

语法: 数组名 = new 数据类型 [ 数组长度 ];

其中,数组长度就是数组中能存放元素的个数,如:

scores = new int[5];

aArray = new double[5];

names = new String[5];

其实,我们也可以将上面的两个步骤合并,在声明数组的同时为它分配空间,如:

int[] scores = new int[5];

关于该分配空间的过程是一个动态创建数组的过程

 

3、 赋值

分配空间后就可以向数组中放数据了,数组中元素都是通过下标来访问的,并且注意的是数组中的索引(即下标)是从0开始,到数组长度-1结束。例如向 scores 数组中存放学生成绩

scores[0] = 81;

scores[1] = 85;

scores[2] = 87;

scores[3] = 89;

scores[4] = 92;

 

4、 处理数组中数据

我们可以对赋值后的数组进行操作和处理,如获取并输出数组中元素的值

System.out.println("scores数组中的第一个元素是: " + scores[0]);

 

Java 中还提供了另外一种直接创建数组的方式,它将声明数组、分配空间和赋值合并完成,关于此种方式,称做静态创建数组。语法格式为:

数据类型   数组名[]  =  { 需要给数组赋值的内容(多个以逗号隔开) }; 如:

int scores[] = {81, 85, 87, 89, 92};

它等价于:

int[] scores = new int[]{81, 85, 87, 89, 92};

 

二、下面再介绍一些关于数组的基本操作:

  1. 遍历数组:

关于遍历数组主要有一维和二维两种,分别以for循环和foreach循环进行遍历。代码如下:

package com.rocking;

public class TraverseArray {

  public static void main(String[] args) {
    // TODO Auto-generated method stub
  
    int a[] = new int[]{1, 2, 3, 5, 98, 45, 15 ,546 , 49};

    int aa[][] = new int[][]{{12, 26, 56}, {15, 65, 48, 89}, {45, 29, 75, 64, 19}};

    //遍历一维数组(for 与 foreach两种方式)
    for (int i = 0; i < a.length; i++) {
      System.out.print(a[i]+" ");
    }
    System.out.println(
"\n>>>>>>>>>>>>>>>>>>>>>>>>>>>");     for (int i : a) {       System.out.print(i+" ");     }   
    System.out.println(
"\n/////////////////////////////");     //遍历二维数组(for 与 foreach两种方式)     for (int i = 0; i < aa.length; i++) {       for (int j = 0; j < aa[i].length; j++) {         System.out.print(aa[i][j]+" ");       }     }
    System.out.println(
"\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");     for (int[] i : aa) {       for (int j : i) {         System.out.print(j+" ");       }
    }   } }

 

可以看到,foreach语句进行遍历稍微简单一些。如果要引用数组或者集合的索引,则foreach语句无法做到,foreach仅仅老老实实地遍历数组或者集合一遍

关于foreach语句,需要将Compiler Compliance Level调成1.5或以上的等级。默认的是1.4;否则使用foreach语句会报如下的错误。[Syntax error, 'for each' statements are only available if source level is 1.5 or greater]。具体操作为:右键你建立的项目名,选择最下面的Properties,在打开的面板中选择Java Compiler。将右边JDK Compliance下的复选框取消选中,再将Compiler Compliance Level的等级调成1.5或以上,点击OK即可。

 

  1. 填充替换数组元素:

数组中的元素定义完成之后,可以通过Arrays类提供的fill()方法来对数组中的元素进行替换。该方法通过各种重载的形式可完成任意类型的数组元素的替换。

fill()方法有如下两种参数类型,①、fill(int[] a, int value)和②、fill(int[] a, int fromIndex, int toIndex, int value).

方法①可以将指定的int值分配给int型数组的每个元素;方法②将指定的int值分配给int型数组指定范围中的每个元素。指定的范围是从索引fromIndex(包括)一直到索引toIndex(不包括)。如果fromIndex == toIndex,则填充范围为空。如果指定的索引位置大于或等于要进行填充的数组的长度,则会报出ArrayIndexOutOfBoundsException(数组越界异常)

 

代码如下:

package com.rocking;

import java.util.Arrays;

public class LearnArrayFill {

public static void main(String[] args) {

// TODO Auto-generated method stub

int a[] = new int[]{1, 2, 3, 5, 98, 45, 15 ,56 , 49};

Arrays.fill(a, 6); //将数组中的所有元素都替换为value的值6

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

System.out.print(a[i]+" ");

}

System.out.println();

int b[] = new int[]{98, 3, 5, 45, 15 ,46 ,1, 2,  49};

Arrays.fill(b, 3, 5, 99); //将数组a中的a[3](包括第4个)到a[5](不包括第6个)之间的元素替换为value的值6

for (int i : b) {

System.out.print(i+" ");

}

}

}

 

  1. 对数组进行排序:

通过Arrays类提供的静态方法sort()即可实现对指定类型数组按数字升序进行排序。

主要有以下两种重载方式:

①、sort(Object[] a)

该形式是以升序的方式对数组中的所有元素进行排序。

 

②、sort(Object[] a, Object fromIndex, Object toIndex)

该形式是将索引位置从fromIndex(包括)toIndex(不包括)内的元素按照升序的顺序进行排序。

import java.util.Arrays;

public class LearnArraysSort {

public static void main(String[] args) {

// TODO Auto-generated method stub

int array[] = new int[]{98, 3, 5, 45, 15 ,46 ,1, 2,  49};

int[] a = {98, 3, 5, 45, 15 ,46 ,1, 2,  49};

Arrays.sort(array); //使用sort(Object[] array)重载形式,将数组中的所有元素按照升序的顺序排序

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

System.out.print(array[i]+">>");

//1>>2>>3>>5>>15>>45>>46>>49>>98>>

}

System.out.println("\n\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");

Arrays.sort(a, 3, 6); //将索引位置从fromIndex(包括)到toIndex(不包括)内的元素按照升序的顺序进行排序。

for (int i : a) {

System.out.print(i+"<<");

//98<<3<<5<<15<<45<<46<<1<<2<<49<<

}

System.out.println("\n\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");

String aa[] = {"AAB", "AAb", "aaB", "535", "001", "纳尼", "嗦嘎", "aab"};

Arrays.sort(aa);

for (String str : aa) {

System.out.print(str+"///");

//001///535///AAB///AAb///aaB///aab///嗦嘎///纳尼///

}

}

}

在上述代码中,String类型的数组的排序算法是按照字典编码顺序排的,因此我们可以看到:数字排列在字母的前面,字母排列在汉字的前面;并且大写字母排列在小写字母的前面。

 

  1. 复制数组:

对数组进行复制,需要用到Arrays类的copyOf()copyOfRange()方法;

copyOf(Object[] original, int newLength):复制数组到指定的长度。

copyOfRange(Object[] original, int fromIndex, int toIndex):将指定数组的指定长度复制到另一个新的数组中。

关于复制就有粘贴,所以这些数组调用了复制的方法,就需要有一个新的数组来接收它。

一言不合就贴代码:

import java.util.Arrays;

public class LearnArraysCopy {

public static void main(String[] args) {

// TODO Auto-generated method stub

int array11[] = new int[]{98, 3, 5, 45, 15 ,46 ,1, 2,  49};

String array21[] = {"AAB", "001", "纳尼", "aaB", "535", "嗦嘎", "aab", "AAb"};

//将数组array21中的长度为5的数组元素复制到新的数组array22中

String[] array22 = Arrays.copyOf(array21, 5);

for (String str : array22) {

System.out.print(str+"<<>>");

//AAB<<>>001<<>>纳尼<<>>aaB<<>>535<<>>

}

System.out.println("\n\n+++++++++++++++++++++++++++++++++++++++\n");

//将数组array11中的索引位置3(包括)到7(不包括)的元素复制到新的数组array12中

int[] array12 = Arrays.copyOfRange(array11, 3, 11);

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

System.out.print(array12[i]+">><<");

//45>><<15>><<46>><<1>><<2>><<49>><<0>><<0>><<

}

}

}

可以看到:我们可以将toIndex(newLenght)的数值设置为大于数组的长度,那么在新数组中就会以0(null)代替后面没有的元素,但是,如果将fromIndex设置为大于数组长度的值,就会报ArrayIndexOutOfBoundsException(数组越界异常)

 

  1. 数组查询:

对数组中元素的查询可以用二分搜索法来搜索指定类型的数组,以获得指定的值。不过使用二分查找法必须先对数组进行排序。如果没有对数组进行排序,则结果是不确定的。如果数组包含多个带有指定值的元素,则无法保证找到的是哪一个。

所以我们可以建立一个程序,如:LearnBinarySearch。然后在其中创建一个数组,首先调用Arrays类的sort()方法对数组进行排序。然后使用binarySearch()key值进行查找。

如果数组中存在这个key值,那么就返回该key值所在的索引值。如果key值不在,那么就返回第一次大于该key值的数值所在位置(1开始)的负值,注意此处说的是位置,从1开始;而不是索引的值(0开始)

当然,如果我们不先对数组进行排序又会怎么样呢?创建了一个数组 int array1[] = new int[]{98, 16, 9, 45, 13 ,46 ,1, 4,  49}; 然后分别对其中的每一个元素进行二分查找,返回的值只有13是返回一个4以及49返回一个8;其他的都是返回负值,然后不存在的数值返回的也是乱七八糟的负值。似乎没有规律可循。

package com.rocking;

 

import java.util.Arrays;

 

public class LearnBinarySearch {

 

public static void main(String[] args) {

// TODO Auto-generated method stub

//创建一个一维数组

int array1[] = new int[]{98, 16, 9, 45, 13 ,46 ,1, 4,  49};

//首先对数组进行排序

Arrays.sort(array1);

//遍历数组,查看现在数组的排序顺序(方便在后面比较查找的数值的索引值)

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

System.out.print(array1[i]+"  ");

}

System.out.println("\n\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");

//如果存在该数值,则返回一个查到的Key值的索引值

System.out.println(Arrays.binarySearch(array1, 46));

System.out.println("\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");

//如果数组中不存在该数值,则返回第一次大于该key值的数值所在位置(从1开始)的负值(注意是位置值而不是索引值)

//因为数组中的所有元素都比-5要大,所以返回的是数组中第一个元素的位置的负值,即-1

System.out.print(Arrays.binarySearch(array1, -5)+"  ");

//第一次大于7的数值是9,处于第3位;于是返回-3

System.out.print(Arrays.binarySearch(array1, 7)+"  ");

//第一次大于33的数值是45,处于第6位;于是返回-6

System.out.print(Arrays.binarySearch(array1, 33)+"  ");

//第一次大于120的数值在数组中不存在,于是返回最大位置值+1的负值,即-10

System.out.println(Arrays.binarySearch(array1, 120)+"  ");

System.out.println("\n<<<<<<<<<<<<<<>>>>>>>>>>>>>>\n");

NoSort ns = new NoSort();

ns.method();

}

}

class NoSort {

//在该方法中测试一下如果不先对数组进行排序,而进行二分查找会出现什么结果

void method() {

int array1[] = new int[]{98, 16, 9, 45, 13 ,46 ,1, 4,  49};

System.out.println(Arrays.binarySearch(array1, 46));

System.out.println("\n<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");

System.out.print(Arrays.binarySearch(array1, 7)+"  ");

System.out.print(Arrays.binarySearch(array1, 33)+"  ");

System.out.println(Arrays.binarySearch(array1, 47)+"  ");

}

}

 

上述过程中用到的只是binarySearch()方法的一种重载形式,它还有一种重载形式是指定范围内的查找;语法如下:

binarySearch(Object[] array, int fromIndex, int toIndex, Object key);

其中的array是数组名;fromIndex是开始查找的开始处索引值(包括)toIndex是查找的结束处索引值(不包括)key是要查找的元素

官方文档中提到,使用该方法同样需要先进行排序

package com.rocking;

 

import java.util.Arrays;

 

public class LearnBinarySearch2 {

 

public static void main(String[] args) {

int array1[] = new int[]{98, 16, 9, 45, 13 ,46 ,1, 4,  49};

Arrays.sort(array1);

int i = Arrays.binarySearch(array1, 2, 8, 46);

for (int j = 0; j < array1.length; j++) {

System.out.print(array1[j]+"  ");

}

System.out.println("\n46所处的索引位置是:"+i);

}

 

}

注意:如果指定的范围大于或等于数组的长度,会报出[ArrayIndexOutOfBoundsException]数组越界异常。

 

三、下面介绍一些关于数组的排序算法:

  1. 冒泡排序:

冒泡排序排序元素的过程总是将小数往前放,大数往后排;类似于水中上升的气泡,故作冒泡排序。

基本思想:比较相邻的元素值,如果两个元素前面的比后面的大,则将前面的小数往后排,后面的大数往前移。具体的原理图就不画了(贴个关于冒泡排序的动画效果的网址http://student.zjzk.cn/course_ware/data_structure/web/flashhtml/maopaopaixu.htm)。再唠叨一下程序的原理好了。

冒泡排序用到了双重的for循环。其中外层循环是用于控制排序的轮数的,最多需要的是数组长度-1轮。内层循环是用于比较相邻元素之间的数值大小,如果前面的元素大于后面的元素,则进行交换。对比的次数是和轮数有关的,每一轮的对比次数是不会超过数组长度-轮数的大小的。好了,又到了大家最喜欢的贴代码的环节了。代码如下:

package com.rocking;

public class MaoPao {

public static void main(String[] args) {

int score[] = {85, 90, 87, 100, 89, 81, 82, 92};

int temp;

        for (int i = 1; i < score.length; i++){    //最多做n-1趟排序  

            for(int j = 0 ;j < score.length - i; j++){    //每一个数最多进行数组长度-1-排列的趟数  

             //升序过程,

             if (score[j] > score[j+1]) {//如果前面的数值大于后面的数值,则将前面的数值换到后面的位置,而将后面的元素换到前边的位置,因此需要添加一个temp变量用来转换两个位置的数

temp = score[j];

score[j] = score[j+1];

score[j+1] = temp;

}

            }

            for(int j = 0; j<score.length; j++)  {

             System.out.print(score[j] +"  ");   

             }

            System.out.println();

        }

}

}

 

  1. 直接选择排序:

直接选择排序听名字就知道其是选择排序的一种,其排序速度比冒泡排序要快一些。

基本思想:在一个无序数组中,首先从前面第一个数开始,依次与后面的数值进行比较,假如是按从小到大的顺序排列,则从前依次往后比较之后,不断的用比较得到的新的最大的与后面的数进行比较。最终将两两比较后找到的最大的数值与最后一位数的位置进行互换。相当于是从数组中找到其中最大的一个数,将其位置与最后一位进行交换。然后除最末这个最大的数值,前面的数值又是一个无序组,在该无序组中,又找出最大的数值,与该无序组的最后一个数值进行位置交换,从而又在前面产生一个新的无序组。重复以上步骤,最终得到了一个从小到大排列的数组。同样贴上一个关于快速选择排序算法的网址http://student.zjzk.cn/course_ware/data_structure/web/flashhtml/zhijiexuanze.htm

根据其基本思想,可知其与冒泡排序类似,也是最多进行数组长度array.length - 1轮排序,且每次排序需要比较的不超过array.length - i(轮数)次。因此,该算法依旧是采用双重循环进行排序,只不过是在内部的实现过程有些许差异罢了。

一言不合就贴代码:

public class LearnFastChoiseSort {

public static void main(String[] args) {

LearnFastChoiseSort lfcs = new LearnFastChoiseSort();

lfcs.sort();

}

void sort() {

int array[] = new int[]{98, 3, 5, 45, 15 ,46 ,1, 2,  49};

//int max = array[0];

int temp;

int index;

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

index = 0;

for (int j = 1; j <= array.length-i; j++) {

if (array[index] > array[j]) {

index = j;

}

temp = array[array.length - i];

array[array.length - i] = array[index];

array[index] = temp;

}

}

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

System.out.print(array[i]+"  ");

}

}

}

 

  1. 反转排序:

顾名思义,反转排序是将数组中的元素由原来的顺序反过来排序。

基本原理:将数组中的最后一个元素与第一个元素进行替换,将倒数第二个元素和第二个元素进行替换......知道把所有的数组元素替换完毕。

感觉这种排序实现起来还蛮容易的,拿代码测试下:

public class LearnReversalSort {

public static void main(String[] args) {

int array[] = new int[]{98, 3, 5, 45, 15 ,46 ,1, 2,  49};

int temp;

for (int i = 1; i < array.length*0.5+1; i++) {

for (int j = i-1; j < i; j++) {

temp = array[j];

array[j] = array[array.length-i];

array[array.length-i] = temp;

}

}

for (int i : array) {

System.out.print(i+"  ");

}

}

}

因为每次排序只交换两个元素,即:只进行一次排序。且在第一轮是交换第一个与最后一个元素,第二趟是交换第二个和倒数第二个元素...以此类推。所以在内层for循环中采用int j = i-1; j < i; j++的条件。

posted on 2016-07-18 20:57  Rocking7189  阅读(537)  评论(0)    收藏  举报

导航