一维数组
- 数组是相同类型数据的有序集合
- 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成。
- 每一个数据称作一个数组元素,每个数组元素通过下标来访问。
数组声明创建
Java使用new操作符来创建数组,语法如下:
dataType[] arrayReVar = new dataType[arraySize];
三种初始化
- 静态初始化
int[] a = {1,2,3};
Ma[] mas = {new Ma(1,2),new Ma(2,2)};//创建Ma类 引用类型Ma
- 动态初始化
int[] b = new int[2];
b[0]=1;
b[1]=2;
- 数组的默认初始化
数组是引用类型,它的元素相当于类的实例变量,因此数组一经分配空间,其中的每个元素也被按照实例变量同样的方法被隐式初始化
数组的四个基本特点
- 长度是确定的。数组一旦被创建,大小不可以改变。如果越界,则报:ArrayIndexOutofBounds
- 其元素必须是相同类型,不允许出现混合类型。
- 数组中的元素可以是任何数据类型,包括基本类型和引用类型。
- 数组变量属于引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量。数组本身是在堆中的。
数组的使用
- for-each循环
- 数组作为方法入参
- 数组作为返回值
public class Demo02 {
public static void main(String[] args) {
//动态初始化
int[] arrays = new int[4];
arrays[0]=1;
arrays[1]=2;
arrays[2]=3;
arrays[3]=4;
//jdk1.5以上,没有下标,适合打印输出
//元素类型 变量名: 数组名
for (int array : arrays) {
System.out.println(array);
}
//打印数组
print(arrays);
//使用Arrays类遍历数组
System.out.println(Arrays.toString(arrays));
int[] reserve = reserve(arrays);
//打印反转数组
print(reserve);
}
//打印数组
//数组作为方法入参
public static void print(int[] arrays){
for (int i = 0; i < arrays.length; i++) {
System.out.println(arrays[i]);
}
}
//反转数组
//数组作为返回值
public static int[] reserve(int[] arrays){
int[] result = new int[arrays.length]; //输出数组
for (int i = 0, j = result.length-1; i<arrays.length ; i++,j--) {
result[j] = arrays[i];
}
return result;
}
}
数组的拷贝与扩容
数组长度一旦确定,不可变,如果原数组满了,想存储更多的元素,只能创建一个空间更大的新数组,然后将原数组拷贝过去,由此达到扩容的目的,但是扩容是比较折损性能的,尽量在使用数组时候预估好长度,减少扩容次数。
public class Demo06 {
public static void main(String[] args) {
int [] src = {1,2,3,4,5}; //源数组
int srcPos = 0; //源数组起始下标
int [] dest = new int[10]; //目标数组
int destPos = 0; //目标数组起始下标
int length = src.length; //拷贝多少个元素
//拷贝
System.arraycopy(src,srcPos,dest,destPos,length);
//打印
for (int num:dest) {
System.out.print(num+" ");
}
}
}
结果如下:
二维数组
- 二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组。
- 语法
int[][] a = new int[2][5];
//可以看成一个两行五列的数组
- 遍历二维数组
public class Demo03 {
public static void main(String[] args) {
int[][] a = {{1,2},{1,3}};
for (int i = 0; i <a.length ; i++) {
for (int j = 0; j < a[i].length; j++) {
System.out.print(a[i][j]+" ");
}
System.out.println();
}
}
}
排序和查找算法
冒泡排序、选择排序、二分法查找
冒泡排序
两层循环,外层冒泡轮数,里层依次比较,时间复杂度为O(n2)
实现步骤:重复扫描待排序序列,并比较每一对相邻的元素,当该对元素顺序不正确时进行交换,重复直到没有任何两个元素可以交换。
import java.util.Arrays;
public class Demo04 {
public static void main(String[] args) {
int[] a = {1,4,3,2,8,43,32,98,66};
int[] sort = sort(a);
System.out.println(Arrays.toString(sort));
}
//冒泡排序
public static int[] sort(int[] a){
int t = 0;
//外循环:判断排序的轮数(每一轮比较都会产生一个最大的数)
for (int i = 0; i < a.length-1; i++) {
//内循环:比较判断两个数,找出最大的数
for (int j = 0; j < a.length-i-1; j++) {
if(a[j]<a[j+1]){
t = a[j];
a[j] = a[j+1];
a[j+1] = t;
}
}
}
return a;
}
}
选择排序
实现步骤:找出一个最小数交换到最前面,然后再剩下的数中找个最小的交换到剩下数的前面,重复此步骤,直到所有数排好。对于有N个数组来说,过程进行N-1次(0<=i<N-1)
import java.util.Arrays;
public class Demo07 {
public static void main(String[] args) {
int [] data = {2,1,7,8,10};
int[] sort = sort(data);
System.out.println(Arrays.toString(sort));
}
public static int[] sort(int [] a){
//外循环:判断排序的轮数(每一轮比较都会产生一个最小的数)
for(int i = 0;i<a.length;i++){
int min = i; //用变量min记下基数
//内循环:比较判断两个数,找出最小的数
for (int j = i+1; j < a.length; j++) {
//比基数还小的数则交换
if(a[j]<a[min]){
min = j;//记下序号j
}
}//交换位置
if(min!=i){
int t = a[i];
a[i] = a[min];
a[min] = t;
}
}
return a;
}
}
二分法查找
二分法查找又称折半法查找,是一种快速查找元素的算法,建立在已经排好序的基础上查找。基本思想是将n个元素分成大致相等的两部分,取a[n/2]与x做比较,如果x=a[n/2],则找到x,如果x<a[n/2],则在数组a的左半部分继续搜索x,如果x>a[n/2],则在数组a的右半部分继续搜索x。
实现代码如下:
public class Demo08 {
public static void main(String[] args) {
int [] a = {1,2,3,4,5,6,7,8,9,10};
System.out.println("搜索元素7的下标是"+search(a, 7));
}
public static int search(int [] data,int value){
int begin = 0; //起始下标
int end = data.length-1; //结束下标
while(begin<= end){ //只要开始下标在结束下标左边就继续找
int mid = (begin+end)/2; //获取中间元素下标
if(value == data[mid]){ //如果中间元素正好等于目标元素则查找成功
return mid; //返回下标
}else if(value>data[mid]){ //如果查找元素大于中间元素,则要在右边搜索
begin = mid + 1;//此时起始下标要在中间元素下标加1
}else if(value<data[mid]){ //如果查找元素小于中间元素,则要在左边搜索
end = mid - 1;//此时结束下标要在中间元素下标减1
}
}
return -1;
}
}
稀疏数组
当一个数组中大部分元素是0,或者是一个相同的值时,可以使用稀疏数组来保存该数组。
稀疏数组的处理方式是:
记录数组一共有几行几列,以及不同值的数量
把具有不同值元素的行列及其值记录在一个小规模的数组中,从而缩小数据的规模。
实现代码:
public class Demo05 {
public static void main(String[] args) {
//定义一个二维数组 11*11 五子棋 黑棋:1 白棋:2
int[][] a = new int[10][10];
a[1][2] = 1;
a[2][3] = 2;
System.out.println("输出原始数组:");
for (int[] ints : a) {
for (int anInt : ints) {
System.out.print(anInt+" ");
}
System.out.println();
}
System.out.println("***********");
//转换为稀疏数组保存
//获取有效值的个数
int sum = 0;
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if(a[i][j]!=0){
sum++;
}
}
}
System.out.println("有效值个数:"+sum);
//创建一个稀疏数组
//sum+1表示 有第0行
//3是行、列、值
int[][] b = new int[sum+1][3];
b[0][0] = 10;
b[0][1] = 10;
b[0][2] = sum;
//遍历二维数组,将非零的数,存放在稀疏数组
int count = 0;
for (int i = 0; i <a.length; i++) {
for (int j = 0; j < a[i].length; j++) {
if(a[i][j]!=0){
count++;
b[count][0] = i;
b[count][1] = j;
b[count][2] = a[i][j];
}
}
}
/*
for (int i = 0; i < b.length; i++) {
System.out.println(b[i][0]+"\t"+b[i][1]+"\t"+b[i][2]+"\t");
}
*/
for (int[] ints : b) {
for (int anInt : ints) {
System.out.print(anInt+"\t");
}
System.out.println();
}
//还原稀疏数组
System.out.println("还原稀疏数组");
//读取稀疏数组 b[0][0]行 b[0][1]列
int[][] c = new int[b[0][0]][b[0][1]];
for (int i = 1; i < b.length; i++) {
c[b[i][0]][b[i][1]] = b[i][2];
}
for (int[] ints : c) {
for (int anInt : ints) {
System.out.print(anInt+"\t");
}
System.out.println();
}
}
}
结果如下:
数组工具类
- Arrays.toString()方法
参数是数组,最终返回一个字符串
import java.util.Arrays;
public class Demo09 {
public static void main(String[] args) {
int [] array = {1,2,3,4,5};
String s = Arrays.toString(array);
System.out.println(s);
}
}
结果如下:
2. Arrays.sort()方法
对数组排序,还可以对数组的某一段排序
//排序
import java.util.Arrays;
public class Demo09 {
public static void main(String[] args) {
int [] arr = {21,32,11,45,2};
Arrays.sort(arr);
for (int num:arr
) {
System.out.print(num+" ");
}
}
}
//对数组某一段排序
import java.util.Arrays;
public class Demo09 {
public static void main(String[] args) {
int [] arr = {21,32,11,45,2};
Arrays.sort(arr,0,2); //对下标0到2的元素排序
for (int num:arr) {
System.out.print(num+" ");
}
}
}
- Arrays.binarySearch()方法
二分法查找,返回查找元素下标
import java.util.Arrays;
public class Demo09 {
public static void main(String[] args) {
//二分法查找
int [] a = {56,90,110,120,800,1000};
System.out.println(Arrays.binarySearch(a, 120));
System.out.println(Arrays.binarySearch(a, 178));
}
}
结果如下:
4. Arrays.fill()方法
fill方法是向数组填充新元素,数组的原始元素会被覆盖。
import java.util.Arrays;
public class Demo09 {
public static void main(String[] args) {
int [] a = {56,90,110,120,800,1000};
Arrays.fill(a,2,5,0); //在a数组从2下标开始到5下标结束不包括下标5,填充值是00
System.out.println(Arrays.toString(a));
}
}
结果如下:
5. Arrays.copyOf()方法
通过原数组拷贝生成新数组,如果拷贝长度大于原数组长度,新数组会自动填充默认值。
import java.util.Arrays;
public class Demo09 {
public static void main(String[] args) {
int [] num ={1,2,3,4,5};
int[] num1 = Arrays.copyOf(num, 3);
System.out.println(Arrays.toString(num1));
int[] num2 = Arrays.copyOf(num,5);
System.out.println(Arrays.toString(num2));
int[] num3 = Arrays.copyOf(num,7);
System.out.println(Arrays.toString(num3));
}
}
结果如下: