目录
数组
数组介绍:
数组的定义:
1.数据类型[ ] 数组名 = {数组元素/值};
2.数据类型 数组名[ ] = {数组元素/值};
一种是将方括号写在数据类型后,一种是将方括号写在数组名后,推荐写在数据类型后;
这里我们列举一个小例子,讲解下我们为什么要使用数组
public class Array01{
// 编写一个main方法
public static void main(String[] args){
// 这里有个题目:有六只鸡,求出它们的体重和,和平均体重
// 假如使用传统方法:
// 1.需要定义6个变量 double ,来存放6只鸡的体重
// 2.总体重 / 6 = 平均体重
double chicken1 = 15;
double chicken2 = 20.1;
double chicken3 = 22.6;
double chicken4 = 16.6;
double chicken5 = 15.2;
double chicken6 = 15.8;
double totalWeight = chicken1 + chicken2 + chicken3 + chicken4 + chicken5 + chicken6;
double avgWeight = totalWeight / 6;
System.out.println("总体重=" + totalWeight + "平均体重=" + avgWeight);
System.out.println("**********************使用数组来解决**********************")
// 传统的写法有一个弊端,如果我们需要计算600只鸡的总体重,及平均体重,那需要定义大量的变量,很不方便
// 下边我们先简单了解下数组,使用数组来完成上边问题
//
// 定义一个数组
// 解释下数组的结构
// 1.double[] 表示 是double 类型的数组,数组名为chicken
// 2.{1,2,3,4,5,6} 表示数组元素,数组的值,依次表示数组的第几个元素
double[] chicken = {1,2,3,4,5,6};
// 我们可以通过循环遍历,遍历数组中所有元素的值,并求和,使用for
// 1.我们可以通过chicken[下标]来访问数组的元素
// 下标是从0开始编号的比如第一个元素就是 chicken[0],第2个就是chicken[1],以此类推
// 2.通过for循环就可以访问数组的元素/值
// 3.使用totalWeight变量对每个元素进行累积
//
// 重点:可以通过 数组名.length 得到数组的大小/长度
double totalWeight = 0;
System.out.println("数组的长度=" + chicken.length);
for(int i = 0;i < chicken.length;i++){
System.out.println("第" + (i + 1) + "个元素的值= " + chicken[i]); // 这里使用循环访问了数组中的每个元素
totalWeight += chicken[i];
}
System.out.println("总体重=" + totalWeight + "平均体重=" + totalWight / chicken.length);
}
}
数组的使用
1.动态初始化(不指定数组元素/值)
第一种动态初始化
数据类型 数组名[ ] = new 数据类型[大小];
数组元素/值 根据数组的数据类型来指定
数据类型 | 默认初始值 |
---|---|
byte、short、int、long | 0 |
float、double | 0.0 |
char | 一个空字符,即"\u0000" |
boolean | false |
引用数据类型 | null,表示变量不引用任何对象 |
第二种动态初始化
先声明数组,在 new 分配内存空间
数据类型[ ] 数组名;
数组名 = new 数据类型[ 大小];
案例:
import java.util.Scanner;
public class Array02{
// 编写一个main方法
public static void main(String[] args){
// 数据类型 数组名[] = new 数据类型[大小];
// 数据类型[] 数组名 = new 数据类型[大小];
// 循环输入5个成绩,保存到double数组,并输出
//
// 1.定义一个Scanner对象,用来接收用户输入
// 2.定义一个double 数组,用来存放成绩
// 3.循环输入5个,使用for,循环5次
// 4.在使用for循环遍历输出
// scores ~ 成绩
// 创建一个Scanner对象,赋值给Scanner 类型的变量 myScanner
Scanner myScanner = new Scanner(System.in);
// 创建一个double数组,大小5
double scores[] = new double[5];
// 循环输入
for(int i = 0;i < scores.length;i++){
System.out.println("请输入第" + (i + 1) + "个同学的成绩:");
scores[i] = myScanner.nextDouble();
}
System.out.println("======数组的元素/值情况如下=====")
// 循环遍历输出
for(int i = 0;i < scores.length;i++){
System.out.println("请输入第" + (i + 1) + "个同学的成绩:" + scores[i]);
}
}
}
public class Array02{
// 编写一个main方法
public static void main(String[] args){
// 先声明
double scores[];
double[] cat;
// 这里只是声明一个数组变量,并为分配内存空间
}
}
2.静态初始化
语法格式: 数据类型[ ] 数组名 = {数据元素/值};
public class ArrayExercise{
// 编写一个main方法
public static void main(String[] args){
// 创建一个char类型的26个元素的数组,分别放置'A' - 'Z'
// 使用for循环打印出来
// 提示:char类型数据运算 'A' + 1 == 'B';
// 代码实现:
char[] charArr = new char[26];
int i = 0; // 控制数组的下标
for(char ch1 = 'A';ch1 <= 'Z';ch1++){
charArr[i] = ch1;
i++;
}
/*
// 另一种思路,可以试着理解一下
for(int i = 0;i < charArr.length;i++){
// 因为 'A' + 1 == 'B',使用for循环来赋值
// charArr 是 char[] 类型
// charArr[i] 是 char类型
charArr[i] = (char)('A' + i); // 'A' + i 是int类型赋值给char类型,需要强制转换类型
}
*/
for(i = 0;i < 26; i++){
// System.out.println("第" + (i + 1) + "个元素的值为" + charArr[i]);
System.out.print(charArr[i] + "\t");
}
}
public class ArrayExercise{
// 编写一个main方法
public static void main(String[] args){
// 求出数组中的最大值, 并找到对应的下标
int[] arr = {4,-1,9,10,23};
int max = arr[0]; // 定义一个变量存放最大值,并假如数组的第一个元素是最大值
int maxIndex = 0; // 用来获取最大值的下标
for(int i = 1;i < arr.length;i++){
// 如果数组的元素大于假设的最大值,则交换
if(arr[i] > max){
max = arr[i];
maxIndex = i; // 将当前最大值的下标赋值给maxIndex
}
}
System.out.println("数组中的最大值为:" + max + "最大值的下标为:" + maxIndex);
}
}
数组的赋值机制(重点)
基本数据类型赋值,这个值就是具体的数据,而且相互不受影响
int n1 = 2; int n2 = n1; // 当n2的值发生变化时n1的值并不受影响;
基本数据类型赋值,称这种赋值方式为,值拷贝(值传递)
n2的变化不回影响n1的值
int n1 = 10;
int n2 = n1;
n2 = 80; // 此时我们输出两个变量的值,看看n1的值受不受n2的影响
System.out.println("n1=" + n1);
System.out.println("n2=" + n2);
n1= 10n2= 80 // 并不受影响,我们称这种赋值方式为,值拷贝
数组在默认情况下是引用传递,赋的值是地址,赋值方式为引用传递
是一个地址arr2的变化会影响到arr1的值
int[] arr1 = {1,2,3};
int[] arr2 = arr1; // 把arr1的值赋值给arr2
arr2[0] = 100;// 更改arr2第一个元素的值,查看变化的情况
for(int i = 0;i <= arr1.length;i++){
// 打印输出arr1的值
System.out.print(arr[i] + "\t");}
打印结果: 100 2 3
Jvm中的内存被分为三部分(栈、堆、方法区)
public class ArrayCopy{
// 编写一个main方法
public static void main(String[] args){
// 将int[] arr1 = {10,20,30};拷贝到 arr2数组
// 要求arr2的数据空间是独立的
int[] arr1 = {10,20,30};
// 创建一个新的数组arr2,开辟新的空间
// 因为是拷贝arr1的值所以大小与arr1一致 ,arr1.length
int[] arr2 = new int[arr1.length];
// 遍历 arr1,把每个元素拷贝到arr2 对应的位置
for(int i = 0;i < arr1.length;i++){
arr2[i] = arr1[i];
}
// 打印输出两个数组的值
System.out.println("======arr2的元素值=====");
for(int i = 0;i < arr2.length;i++){
System.out.print(arr2[i] +"\t");
}
// 修改arr2的值查看变化
arr2[0] = 100;
// 遍历 arr1,把每个元素拷贝到arr2 对应的位置
for(int i = 0;i < arr1.length;i++){
arr2[i] = arr1[i];
}
// 打印输出两个数组的值
System.out.println("======arr2的元素值=====");
for(int i = 0;i < arr2.length;i++){
System.out.print(arr2[i] +"\t");
}
}
}
数组反转
这里可能考虑到数组个数为奇数,可能理解不了,奇数怎样互换,这里我们考虑,如果是奇数的话中间的那一个是不需要交换的,所以长度/2,付给int类型会自动取证,刚好排除掉中间的那一个
另一种方式实现数组反转
数组添加![](https://img-blog.csdnimg.cn/9739b90b2110427d9257dc51909f0676.png)
public class ArrayCopy{
// 编写一个main方法
public static void main(String[] args){
// 实现动态的给数组添加元素效果
// 1.原始数组使用静态分配int[] arr = {1,2,3}
// 2.增加元素,直接放在数组的最后 arr = {1,2,3,4}
// arrNew = {1,2,3,4}
// 3.用户可以通过如下方法来决定是否继续添加,添加成功,是否继续?y/n
//
// 思路分析
// 1.定义初始数组
// 2.数组下标必须在指定范围内使用,否则报错(下标异常)
// 如果我们想要增加元素,必须要给数组扩增一个位置;我们创建一个新的数组,大小原数组.length + 1
// 3.定义新数组 int[] arrNew = new int[arr.length + 1];
// 4.遍历原始数组,依次将原始数组中的元素拷贝到arrNew数组
// 5.将需要添加的值赋值给arrNeW[arrNew.length - 1]
// 6.将原始数组指向arrNew;arr = arrNew;那么原来的数组就被销毁
// 创建原始数组
int[] arr = {1,2,3};
Scanner myScanner = new Scanner(System.in);
do{
int[] arrNew = new int[arr.length + 1];
// 将原来数组中的值,拷贝给新数组
for(int i = 0;i < arr.length;i++){
arrNew[i] = arr[i];
}
System.out.println("输入要插入的值:");
int arrInput = myScanner.nextInt();
arrNew[arrNew.length - 1] = arrInput;
arr = arrNew;
// 判断是否继续添加
System.out.println("是否继续追加数据,y/n:");
addIF = myScanner.next().charAt(0);
if(addIF = 'n'){
break;
}
}while(true);
System.out.println("你退出了添加...");
}
}
对数组进行缩减
public class ArrayCopy{
// 编写一个main方法
public static void main(String[] args){
// 对数组进行缩减
// 当数组元素为一个是则不能在进行缩减
//
// 实现思路
// 1.定义一个新数组arrNew,大小arr.length - 1;
// arrNew = arr;
// 则缩减一个元素值
Scanner myScanner = new Scanner(System.in);
// 定义原始数组
int[] arr = {1,2,3,4,5,6};
do{
if(arr.length < 1){
System.out.prtinln("数组元素个数为1,不可在进行缩减")
break;
}
// 创建一个新数组 大小arr.length - 1;
int[] arrNew = new int[arr.length - 1];
arrNew = arr;
arr = arrNew;
for(int i = 0;i < arr.length;i++){
System.out.prtin(arr[i] + "\t");
}
System.out.println("是否继续进行数组缩减(y\n):")
char ch1 = myScaner.next().charAt(0);
if(ch1 == 'n'){
break;
}
}while(true);
}
}
排序
查找(顺序查找、二分查找):
顺序查找:依次比较,查看是否能找到
二分查找:二分查找前提是数组必须有序
定义两个变量来确定数组的首元素跟尾元素,用这两个元素来确定中间值
left--right
mid(中间值) = (left + right)/ 2;
首先找到中间值,将需要查找的值和中间值进行比较,如果==中间值,则找到了
如果小于中间值,要查找的值则在中间值左边,则right = mid - 1;
再次求出中间值,查看要查找的值在左边还是右边;一直按着个方法知道找到;
public SeqenceSearch{
// 编写一个main方法
// seqence~序列
public static void main(String[] args){
// 在一个序列中查找该班级是否有此名同学,并做出响应
// 使用顺序查找法;
// 定义一个数组,用来存放班级同学信息
String[] classInfo = {"张三","李四","王五","李六","刘华强"};
// 定义一个Scanner对象用来获取用户输入的查找信息
Scanner input = new Scanner(System.in);
System.out.println("请输入要查找的同学姓名:");
String searchName = input.next();
// 使用for循环遍历数组,依次比较要查找的同学姓名是否在班级信息数组里
for(int i = 0;i < classInfo.length;i++){
// 字符串比较equals
if(searchName.equals(classInfo[i])){
System.out.println(searchName + "同学在该班级中");
break;
}
}
System.out.println("没有找到");
}
}
多维数组(二维数组)dimensional~维度的
TwoDimensional(二维的)
二维数组的使用:
1.动态初始化-第一种方式
语法:数据类型[ ][ ] 数组名 = new 数据类型[大小][大小];
int[ ][ ] arr = new int[大小][大小]; // int[ ][ ] arr = new int[行][列];
example(例子):int[][] arr = new int[2][3];
二维数组在内存中的形式![](https://img-blog.csdnimg.cn/83457f1e71dd453392bffd9218e25339.png)
2.第二种方式:
1.先声明
2.后new分配空间
int[ ][ ] arr;
arr = new int[2][3];
3.第三种方式:(列数不确定)
public class TwoDimensionalArray02{
// 编写一个main方法
public static void main(String[] args){
int[][] arr1 = new int[5][]; // 这里只是创建了一个有2个一维数组的二维数组;但是没有给每一个二位数组分配空间,所以他们的值为null
// 如果未分配空间就是用会报异常~NullPointerException
for(int i = 0;i < arr1.length;i++){
//遍历二维数组中的每一个一维数组为它们分配空间
arr1[i] = new int[i + 1];
// 在遍历每一个一维数组为它们赋值
for(int j = 0;j < arr1[i].length;j++){
arr1[i][j] = j + 1;
}
}
// 遍历二维数组打印数组中的内容
for(int i = 0;i < arr1.length;i++){
for(int j = 0;j < arr1[i].length;j++){
System.out.print(arr1[i][j] + "\t");
}
System.out.println("");
}
}
}
4.第四种使用方式(静态初始化)
二维数组的练习~案例
1.遍历二维数组,并得到和
int[][] arr = {{4,6},{1,4,5,7},{-2}};
public class TwoDimensionalArrayExercise{
// 编写一个main方法
public static void main(String[] args){
// 定义二维数组
int[][] arr = {{4,6},{1,4,5,7},{-2}};
// 定义求和变量
int sum = 0;
// 使用for循环遍历二维数组
for(int i = 0;i < arr.length;i++){
for(int j = 0; j < arr[i].length;j++){
System.out.println("第" + (i + 1) + "行" + "第" + (j + 1) + "列的数据为:" + arr[i][j]);
sum += i;
}
System.out.println("");
}
System.out.println("遍历循环结束,所有元素的总和值为:" + sum);
}
}
2.打印杨辉三角
3.练习
二维数组使用细节和注意事项
本章作业
注: 这里需要注意一下第一题的D选项;
String strs[] = new Strgin[]{"a","b","c"}; // 这种写法也是正确的,大家可以到编译器试一下
第二题,因为是动态初始化,所以数组的所有的值都是根据数据类型来决定的,而boolean类型的默认值是false 其它数据类型在前边数组的使用中已经详细列举了;
public class Exercise{
// 编写一个main方法
public static void main(String[] args){
// 题目:已知有一个升序的数组;要求插入一个元素,数组依旧是升序;
// 思路分析;
// 1.定义一个升序的数组
// 2.在定义一个插入元素后的新数组 大小元素组大小 + 1;
// 3.定义Scanner对象接收插入的元素
// 4.使用for循环遍历原始数组,将每一个元素与,接收的元素相比较,如果小于接收的元素,则将该元素的下标存放到index的位置,这就是要插入元素的位置
// 5.然后使用值拷贝将原数组中的元素拷贝到新数组,当遍历到index的下标是将要插入的元素插入
// 6.将原数组内存单元指向新数组;
// 7.打印输出
// 定义一个升序的数组
int[] arr1 = {10,20,30,40,50,60,70,80,90,100};
int[] arrNew = new int[arr1.length + 1];
int index = -1;
// 定义Scanner对象,就收用户输入
Scanner myScanner = new Scanner(System.in);
System.out.println("请输入要插入的元素:");
int input = myScanner.nextInt();
// 使用for循环遍历
for(int i = 0;i < arr1.length;i++){
if (input <= arr1[i]){
index = i;
break;
}
}
// 此处加一个判断,用来判断当要插入的元素都不小于原数组中的元素的时候则index的值也为发生改变,则需要将它添加到末尾
if(index == -1){
index = arr1.length;// 因为数组的下标都是从0开始的,我们是在原数组的基础上扩展1个元素位置,所以可以使用原数组的长度
}
for(int i = 0,j = 0;i < arrNew.length;i++){
// 将原数组中的元素添加到值拷贝到新数组
// 不过需要跳过要插入的位置index
if(i != index){
arrNew[i] = arr1[j];
j++; // 因为如果都是用i来作为数组的下标的话如果中间插入了一个元素,i++则原数组的值拷贝会有遗漏,所以每当原数组中的值被添加到新数组中后自己定义一个下标变量来控制
}else{
arrNew[i] = input;
}
}
// arr1 = arrNew;
System.out.println("打印原数组arr1");
for(int i = 0;i < arr1.length;i++){
System.out.print(arr1[i] + " ");
}
// 打印输出插入后的
System.out.println("");
System.out.println("打印插入后的数组arrNew");
for(int i = 0;i < arrNew.length;i++){
System.out.print(arrNew[i] + " ");
}
}
}
(int)(Math.random() * 100) + 1
Math.random(),随机产生0.0到无限接近于1之间的小数,[0,1)
Math.random() * 100 生成0,99之间的小数再使用(int)强转类型将其变成整数
(int)(Math.random() * 100) 生成[0,99] 之间的整数 + 1生成[1,100]之间的整数
public class HomeWork05{
// 编写一个main方法
public static void main(String[] args){
// 题目:随机生成10个整数(1~100)范围保存到数组,并倒序打印,并求平均值、最大值和最大值的下标、并查找里面是否有8;
// 定义一个数组用来存放随机值
int[] arr = new int[10];
//使用(int)(Math.random() * 100) + 1; 来获取(1 ~ 100) 之间的随机整数;
// 使用for循环来对数组进行赋值
for(int i = 0;i < 10;i++){
arr[i] = (int)(Math.random() * 100) + 1;
}
// 先正序打印一下数组中的值
System.out.println("正序打印arr数组中的元素");
for(int i = 0;i < 10;i++){
System.out.print(arr[i] + "\t");
}
System.out.println("");
// 倒序打印数组中的值
System.out.println("倒序打印arr数组中的元素");
// 定义变量从来存放数组所有元素的和sumNum、最大值 maxNum、下标index
int sumNum = 0;
int maxNum = arr[0];
int index = 0;
boolean flag = false;
for(int i = arr.length - 1; i >= 0;i--){
sumNum += arr[i];
if (arr[i] > maxNum){
maxNum = arr[i];
index = i;
}
if (arr[i] == 8){
flag = true;
}
System.out.print(arr[i] + "\t");
}
System.out.println();
System.out.println("该数组中的平均值为:" + (sumNum / arr.length) + "最大值为:" + maxNum + "最大值的下标为:" + index);
if (flag){
System.out.println("该数组中存在数字 8 ");
}else{
System.out.println("该数组中不存在数字 8 ");
}
}
}
6.题
7.写出冒泡排序的代码
public class HomeWork{
// 编写一个main方法
public static void main(String[] args){
// 写出冒泡排序的代码
//
// 使用来个for循环
// 最外层决定比较的轮数
// 内层决定比较的次数
int[] arr = {10,202,99,2,45,993};
// 这种是从小到大,考虑从大到小
for(int i = 0;i < arr.length - 1;i++){
for(int j = 0;j < arr.length - 1 - i;j++){
if(arr[j] > arr[j + 1]){
int temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
// 输出打印
System.out.println("从小到大排列");
for(int i = 0;i < arr.length;i++){
System.out.print(arr[i] + "\t");
}
System.out.println("");
for(int i = 0;i < arr.length - 1;i++){
for(int j = 0;j < arr.length - 1 - i;j++){
if(arr[j] < arr[j + 1]){
int temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
// 输出打印
System.out.println("从大到小排列");
for(int i = 0;i < arr.length;i++){
System.out.print(arr[i] + "\t");
}
}
}