数组
1.数组的定义及基本应用
1.1 数组的定义
- 概念:一组连续的存储空间,存储多个相同数据类型的值。
- 特点:类型相同,长度固定。
public class TestDemo1 {
public static void main(String[] args) {
//其中int[] a表示声明int数组类型变量,定义变量名为a。
//new int[5]表示分配长度为5的来纳许空间
int[] a = new int[5];
}
}
- 数组中的每个数据格被称为数据元素。
- 对每个元素进行赋值或者取值的操作被称为元素的访问。
- 访问数组时,需要使用下标(从0开始,一次+1,自动生成),下标也即是索引。
- 访问的语法:数组名[下标]; //例如: 存:a[0]=10; 取:a[0];
public class TestDemo1 {
public static void main(String[] args) {
//其中int[] a表示声明int数组类型变量,定义变量名为a。
//new int[5]表示分配长度为5的来纳许空间
int[] a = new int[5];
a[0] = 10;//赋值
int sum = a[0] + 5;
System.out.println(sum);
}
}
- 有效下标范围:0~数组长度-1
- 如上例中如果访问a[5],则会抛出异常ArrayIndexOutOfBoundException(数组越界异常)
1.2 数组的遍历
package com.array;
import java.util.Scanner;
/**
* @Classname TestDemo1
* @Description 数组声明
* @Date 2020/7/19 21:42
* @Author Anonymous
*/
public class TestDemo1 {
public static void main(String[] args) {
//控制台输入5名学生成绩,并保存到数组中
double[] scores = new double[3];
//循环存入数组,scores.length指的是数组的长度
for (int i = 0; i < scores.length; i++) {
System.out.println("请输入第" + (i+1) + "名学生成绩");
scores[i] = new Scanner(System.in).nextDouble();
}
//循环打印数组元素
for (int i = 0; i < scores.length; i++) {
System.out.println(scores[i]);
}
}
}
//访问数组最后一个元素:scores[scores.length-1];
1.3 数组的默认值
数据类型 | 默认初始化值 |
---|---|
byte,short,int,long | 0 |
float,double | 0.0 |
char | 一个空字符,即’\u0000’ |
boolean | false |
引用数据类型 | null,表示变量不引用任何对象 |
1.4 数组创建语法
1.4.1 动态初始化
先声明,再分配空间
//第一种写法
int[] x = new int[100];
//第二种写法
int[] x;
x = new int[100];
1.4.2 动态初始化
声明和赋值是同步的
//第一种写法
int[] arr = {1,2,3,4};//此种方法不可以换行,会报错
//第二种写法
int[] arr = new int[]{1,2,3,4};//推荐,因为可以将变量声明到外面
//可以换行
int[] arr;
arr = new int[]{1,2,3,4};
2.数组的复制及扩容
- 创建数组时,必须显示指定长度,且创建之后不可改变长度
扩容的思路:
创建大于原数组长度的新数组
将原数组中的元素依次复制到新数组中
package com.array;
import javax.print.DocFlavor;
import java.util.Arrays;
/**
* @Classname TestDemo2
* @Description TODO
* @Date 2020/7/19 22:41
* @Author Anonymous
*/
public class TestDemo2 {
public static void main(String[] args) {
//原数组
int[] oldArray = new int[]{1,2,3,4};
//扩容步骤1:创建比原数组更大的新数组
//int[] newArray = new int[oldArray.length * 2];
//扩容步骤2:将原数组的数据依次复制到新数组中
//1.自己实现
/**
for (int i = 0; i < oldArray.length; i++) {
newArray[i] = oldArray[i];
}
*/
/*
* 2.利用jdk提供的API实现
* System.arrayCopy(原数组,原数组起始位置,新数组,新数组起始位置,长度);
**/
//System.arraycopy(oldArray,0,newArray,0,oldArray.length);
/*
* 3.利用java.util包下的Array的copyOf方法
* Arrays.copyOf(原数组,新长度);//返回带有原值的新数组
**/
int[] newArray = Arrays.copyOf(oldArray, oldArray.length * 2);
//遍历访问
for (int i = 0; i < newArray.length; i++) {
System.out.print(newArray[i] + "\t");
}
System.out.println();
}
}
注意:前两种方式都需要有新数组声明,而Arrays.copyOf不需要,它的返回值就是新数组
3.数组的高级应用(插入,删除,扩容)
//此方法相当于集合中的添加方法
package com.array;
import java.util.Arrays;
/**
* @Classname TestDemo3
* @Description 数组的插入,扩容
* @Date 2020/7/19 23:06
* @Author Anonymous
*/
public class TestAddress {
static int[] nums = new int[5];
public static void main(String[] args) {
nums[0] = 11;
nums[1] = 22;
nums[2] = 33;
nums[3] = 0;
insert(55);
print();
}
public static void insert(int value){//position=2
for (int i = 0; i < nums.length; i++) {
if (nums[i] == 0){
nums[i] = value;
}
}
}
public static void print(){
//遍历的方法
for (int i = 0; i < nums.length; i++) {
System.out.print(nums[i] + "\t");
}
System.out.println();
}
}
//可以看到此时把有效元素的0也给覆盖了,因此,要想使有效元素的值不被覆盖,则需要声明一个变量来记录数组中有效元素的个数,然后在插入即可,代码如下:
//11 22 33 55 55
package com.array;
import java.util.Arrays;
/**
* @Classname TestDemo3
* @Description 数组的插入,扩容
* @Date 2020/7/19 23:06
* @Author Anonymous
*/
public class TestAddress {
static int[] nums = new int[5];
static int size = 4;//有效元素的个数,也可以代表下一个无效元素的插入位置(下标)
public static void main(String[] args) {
nums[0] = 11;
nums[1] = 22;
nums[2] = 33;
nums[3] = 0;
insert(55);
print();
}
public static void insert(int value){//position=2
nums[size] = value;
size++;
}
public static void print(){
//遍历的方法
for (int i = 0; i < size; i++) {
System.out.print(nums[i] + "\t");
}
System.out.println();
}
}
地址的替换
数组作为引用类型之一,其变量中存储的是数组的地址
完成元素复制后,需将新数组地址,赋值给原变量进行替换
//此方法相当于集合中的在指定位置添加值得方法
package com.array;
import java.util.Arrays;
/**
* @Classname TestDemo3
* @Description 数组的插入,扩容
* @Date 2020/7/19 23:06
* @Author Anonymous
*/
public class TestDemo3 {
static int[] nums = new int[5];
static int size = 0;//有效元素的个数,也可以代表下一个无效元素的插入位置(下标)
public static void main(String[] args) {
System.out.println(nums);
insert(0,11);
insert(1,22);
print();
insert(2,33);
print();
insert(3,20);
insert(4,50);
insert(5,60);
insert(6,60);
print();
//insert(4,88);
// insert(6,20);
System.out.println(nums);
}
public static void insert(int position,int value){//position=2
if (position < 0 || position > size){
System.out.println("你好,用户,您输入的位置有错,请输入一个从0到" + size + "的整数");
return;
}
if (nums.length == size){
expand();
}
//将元数据依次往后移动
for (int i = size; i > position ; i--) {
nums[i] = nums[i-1];
}
//新值存入目标位置
nums[position] = value;
size++;
}
//数组的扩容
public static void expand(){
//将原数组扩容到2倍并得到一个新数组(带有原值)
int[] newArray = Arrays.copyOf(nums, nums.length * 2);
//替换引用,也即是将原nums中指向长度为5的地址,替换成现在指向长度为10的新数组
nums = newArray;
}
public static void print(){
//遍历的方法
//小于size说明遍历的都是有效数组的元素,因为将来要做扩容,没有用的空间不要动,所以用的是size,而不是nums.length
for (int i = 0; i < size; i++) {
System.out.print(nums[i] + "\t");
}
System.out.println();
}
}
//[I@5fd0d5ae
//11 22
//11 22 33
//11 22 33 20 50 60 60
//[I@52cc8049
//remove
package com.array;
import java.util.Arrays;
/**
* @Classname TestDemo3
* @Description 数组的插入,扩容
* @Date 2020/7/19 23:06
* @Author Anonymous
*/
public class TestDemo3 {
static int[] nums = new int[5];
static int size = 0;//有效元素的个数,也可以代表下一个无效元素的插入位置(下标)
public static void main(String[] args) {
insert(0,11);
insert(1,22);
insert(2,33);
insert(3,20);
insert(4,50);
insert(5,60);
print();
replace(0,10);
print();
remove(5);
print();
}
public static void insert(int position,int value){//position=2
if (position < 0 || position > size){
System.out.println("你好,用户,您输入的位置有错,请输入一个从0到" + size + "的整数");
return;
}
if (nums.length == size){
expand();
}
//将元数据依次往后移动
for (int i = size; i > position ; i--) {
nums[i] = nums[i-1];
}
//新值存入目标位置
nums[position] = value;
size++;
}
//移除
public static void remove(int position){
if (position < 0 || position > size){
System.out.println("你好,用户,您输入的位置有错,请输入一个从0到" + size + "的整数");
return;
}
for (int i = position; i < size - 1; i++) {
//元素依次往前移动
//如果是删除最后一个元素,则循环不满足条件,会直接执行size--,相当于也会移除
nums[i] = nums[i+1];
}
size--;
}
//替换
public static void replace(int position,int value){
nums[position] = value;
}
//数组的扩容
public static void expand(){
//将原数组扩容到2倍并得到一个新数组(带有原值)
int[] newArray = Arrays.copyOf(nums, nums.length * 2);
//替换引用,也即是将原nums中指向长度为5的地址,替换成现在指向长度为10的新数组
nums = newArray;
}
public static void print(){
//遍历的方法
for (int i = 0; i < size; i++) {
System.out.print(nums[i] + "\t");
}
System.out.println();
}
}
4.数组的类型的参数
4.1 数组类型的参数
package com.array;
/**
* @Classname TestDemo4
* @Description 数组作为参数传递
* @Date 2020/7/20 17:38
* @Author Anonymous
*/
public class TestDemo4 {
public static void main(String[] args) {
int[] array = new int[]{1,2,3,4,5};
printArray(array);
}
public static void printArray(int[] newArray){
for (int i = 0; i < newArray.length; i++) {
System.out.println(newArray[i]);
}
}
}
方法调用时,将array中的地址赋值给newArray,此时两者指向同一个数组
也就是假设array的地址是0x0000A001,参数传递后,newArray的地址也就变成了0x0000A001
所以运行结果为1,2,3,4,5
package com.array;
import java.util.Arrays;
/**
* @Classname TestDemo5
* @Description 数组类型的参数
* @Date 2020/7/20 18:10
* @Author Anonymous
*/
public class TestDemo5 {
public static void main(String[] args) {
int n = 10;
//m1(n);
//System.out.println(n);//10
// 因为基本类型的赋值就是值的复制,一方的改变不影响另一方。
// 相当于把主函数中的n=10复制到m1方法中的形参中,
// 当m1方法中n++之后,也就不存在了,所以打印的还是主函数中的n的值
// int result = m2(n);
// System.out.println(result);//10
//int[] array = {11,22,33};//假设array的地址是0x1234
//m3(array);
//System.out.println(array[0]);//11
int[] form = {1,2,3,4};
m4(form);
System.out.println(form[0]);
}
public static void m1(int n){
n++;
}
public static int m2(int n){
return n++;
}
public static void m3(int[] nums){//当array传过来时,nums指向了0x1234
nums = Arrays.copyOf(nums, nums.length * 2);
//将nums扩容两倍之后交给一个新数组nums,此时nums指向的地址假设为0x5678,
// 然后将nums的第一个元素赋值为88,和之前的array数组无关,故调用处打印的还是11
nums[0] = 88;
}
public static void m4(int[] to){
to[0] = 888;
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VpuJw09t-1595336910553)(C:\Users\86182\Pictures\Saved Pictures\微信图片_20200721125503.jpg)]
4.2 数组类型的返回值
package com.array;
/**
* @Classname TestReturnArray
* @Description 数组作为返回值
* @Date 2020/7/20 21:31
* @Author Anonymous
*/
public class TestReturnArray {
public static void main(String[] args) {
int[] nums = {1,2,3,4,5,6};
int[] newNums = copyOf(nums, nums.length * 2);
for (int i = 0; i < newNums.length; i++) {
System.out.print(newNums[i] + "\t");
}
}
//接收一个整数数组,并返回一个更大的包含原有数组的新数组
public static int[] copyOf(int[] array, int length){
int[] newArray = new int[length];
for (int i = 0; i < array.length; i++) {
newArray[i] = array[i];
}
return newArray;
}
}
public class TestReturnedValue{
public static void main(String[] args){
int[] oa = {111,222,333,444,555};//0x0000A111
int[] na = expand(oa);
for(int i = 0;i < na.length;++i){
System.out.println(na[i]);
}
}
public static int[] expand(int[] oldArray){//0x0000A111
int[] newArray = new int[oldArray.length * 2];//0x0000B222
for(int i = 0;i < oldArray.length;i++){
newArray[i] = oldArray[i];
}
return newArray;//0x0000B222
}
}
5.可变长参数
概念:可以接收多个同类型实参,个数不限,使用方式与数组相同
语法:数据类型…形参名 //必须定义在形参列表的最后,且只能由一个
package com.array;
import java.util.EnumSet;
/**
* @Classname TestChangeLength
* @Description 可变长参数
* @Date 2020/7/21 13:01
* @Author Anonymous
*/
public class TestChangeLength {
public static void main(String[] args) {
//答应1 2 3 4 5
//int[] nums = {1,2,3,4,5};
//printArray(nums);//可变长参数作为形参可以直接接收数组
printArray(1,2,3,4,5,6,7);
}
//在整个形参位置中,可变长参数必须位于最后而且必须只能有一个
public static void printArray(int position,int value,int...array){
System.out.println(array);//打印的是地址,说明可变长数组就是数组,只是别人做了封装
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + "\t");
}
System.out.println();
}
}
6.排序
6.1冒泡排序
冒泡排序:相邻的亮哥哥值比较大小,互换位置,每轮比较之后最大值斗会跑在最后
分析:数组长度就是外层循环的次数,而内层循环是比较的次数,假如第一次循环i=0时候,需要比较(数组长度-1)次,当i=1时候,需要比较(数组长度-2)次,可知,第i次循环加上比较的次数刚好等于数组长度。
package com.array;
/**
* @Classname TestSort
* @Description 冒泡排序
* @Date 2020/7/21 16:06
* @Author Anonymous
*/
public class TestSort {
public static void main(String[] args) {
int[] array = {10,9,37,8,65,48};
int[] afterSort = sort(array);
printArray(afterSort);
}
//冒泡排序方法
public static int[] sort(int[] array){
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array.length - i - 1; j++) {
if (array[j] > array[j+1]){
int temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
return array;
}
//遍历数组的方法
public static void printArray(int[] array){
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + "\t");
}
System.out.println();
}
}
6.2 选择排序
选择排序:固定值与其他值依次比较大小,互换位置
package com.array;
/**
* @Classname TestSelectSort
* @Description 选择排序
* @Date 2020/7/21 16:36
* @Author Anonymous
*/
public class TestSelectSort {
public static void main(String[] args) {
int[] array = {51,10,45,9,3,88};
sort(array);
printArray(array);
}
public static void sort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[minIndex]){
minIndex = j;
}
}
//交换
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
//遍历数组的方法
public static void printArray(int[] arr) {
if (arr == null){
return;
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
System.out.println();
}
}
6.3 JDK排序
java.util.Arrays.sort(数组名); //JDK提供(升序)
package com.array;
import java.util.Arrays;
/**
* @Classname TestSort2
* @Description TODO
* @Date 2020/7/21 16:28
* @Author Anonymous
*/
public class TestSort2 {
public static void main(String[] args) {
int[] array = {51,10,45,9,3,88};
Arrays.sort(array);
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + "\t");
}
System.out.println();
}
}
7.二维数组
概念:一维数组中的一维数组;数组中的元素,还是数组
package com.array;
/**
* @Classname TestDemo6
* @Description 二维数组
* @Date 2020/7/21 19:53
* @Author Anonymous
*/
public class TestDemo6 {
public static void main(String[] args) {
//3指的是高维下标(行号),5指的是低维下标(列号)
int[][] array = new int[3][5];
array[0][0] = 10;
array[0][1] = 20;
array[0][2] = 30;
array[0][3] = 40;
array[0][4] = 50;
array[1][0] = 100;
array[1][1] = 200;
array[1][2] = 300;
array[1][3] = 400;
array[1][4] = 500;
array[2][0] = 1000;
array[2][1] = 2000;
array[2][2] = 3000;
array[2][3] = 4000;
array[2][4] = 5000;
//System.out.println(array[0]);//打印的是地址,代表的是数组
System.out.println(array[0].length);//5
/*
for (int i = 0; i < array[0].length; i++) {
System.out.print(array[0][i] + "\t");
}
System.out.println();
*/
//二维数组遍历
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
System.out.print(array[i][j] + "\t");
}
System.out.println();
}
}
}
二维数组的创建语法:
1.先声明,再分配空间
数据类型[][] 数组名;
数组名 = new 数据类型[高维长度][低维长度]
2.声明并分配空间
数据类型[][] 数组名 = new 数据类型[高维长度][低维长度]
3.声明并赋值(繁)
数据类型[][] 数组名 = new 数据类型[高维长度][] //不规则数组,自行new低维数组
4.声明并赋值(简)
数据类型[][] 数组名 = {{1,2,3},{4,5},{7,8,9,10}}
package com.array;
/**
* @Classname TestDemo6
* @Description 二维数组
* @Date 2020/7/21 19:53
* @Author Anonymous
*/
public class TestDemo6 {
public static void main(String[] args) {
int[][] array = new int[][]{{1,2,3},{4,5},{6,7,8,9}};
//二维数组遍历
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
System.out.print(array[i][j] + "\t");
}
System.out.println();
}
int[][] a = new int[3][];
//System.out.println(a[0][0]);//Error
System.out.println(a[0]);//null
System.out.println(a[1]);//null
System.out.println(a[2]);//null
a[0] = new int[3];
a[1] = new int[4];
a[2] = new int[5];
System.out.println(a[0]);//[I@34c45dca
System.out.println(a[1]);//[I@52cc8049
System.out.println(a[2]);//[I@5b6f7412
//二维数组遍历
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[i].length; j++) {
System.out.print(a[i][j] + "\t");
}
System.out.println();
}
}
}
杨辉三角:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
可知:第i行有i列
每行的第一个和最后一个元素都为1
当前数(非第一列和最后一列)等于上面一个数+上面一个数的左边的数
package com.array;
import java.util.Scanner;
/**
* @Classname TestDemo7
* @Description 杨辉三角
* @Date 2020/7/21 20:35
* @Author Anonymous
*/
public class TestDemo7 {
public static void main(String[] args) {
System.out.println("请输入行号:");
//创建二维数组,定义行,但是没有定义列
int rows = new Scanner(System.in).nextInt();
int[][] arr = new int[rows][];
//动态为列开辟空间
for (int i = 0; i < arr.length; i++) {
arr[i] = new int[i+1];
}
//赋值操作
for (int i = 0; i < arr.length; i++) {
//第i行第1列,即每行的第一列
arr[i][0] = 1;
//第i行第i列,即每行的最后一个元素
arr[i][i] = 1;
//下面是杨辉三角的核心部分
//注意此时的j应从1开始,因为每一行的第一个数我们已经赋值过了
for (int j = 1; j < i; j++) {
//当前数值==上一行该列的数+上一行该列左边的数
arr[i][j] = arr[i-1][j] + arr[i-1][j-1];
}
}
//循环打印二维数组
for (int m = 0; m < arr.length; m++) {
for (int n = 0; n < arr[m].length; n++) {
System.out.print(arr[m][n] + "\t");
}
//换行
System.out.println();
}
}
}