数组的增删改查
增加元素
PS:读取是文件中或数据库内容,然后存储到数组中,现阶段因为中这个条件,所以我们就是随机数进行添加数据
import java.util.Arrays;
import java.util.Scanner;
/**
* 增删改查操作
*/
public class CRUDArrayDemo {
public static void main(String[] args) {
//1.向数组中添加数据
int[] arr = new int[10];
System.out.println("请输入1~4数字执行数组操作");
Scanner input = new Scanner(System.in);
int num = input.nextInt();
switch (num){
case 1:
System.out.println("-----------------------------对数组增加值---------------------------");
inputArray(arr);
//Arrays 是数组的工具类 提供一些常用对数组操作 【排序,打印,查找,拷贝,填充,比较等等】
//toString将数组转换为字符串对象,将存储在数组中内容以字符串的形式输出
//参数是获取一个数组对象【数组名称】
System.out.println(Arrays.toString(arr));
break;
}
}
/*
向数组添加数组
*/
public static void inputArray(int[] arr){
/*
一个是普通for循环【操作数组下标】,通过对下标的获取操作,从而操作数组
即可以对数据进行赋值,也可以对数据进行取值操作
一个是增强for循环【foreach】 只能对数据中元素进行取值操作,取值之后可以对数据
进行 计算,判断,打印等等,当前循环是不能对数组进行赋值操作,原因在于是循环中会定义一个局部变量
这个变量会获取数组中每一个元素的值,操作时候等于是操作这个局部变量,而非是操作数组中元素
*/
//采用普通for循环
for(int i = 0;i<arr.length;i++){
//i变量就相当于是数组中的下标,根据i值的自增下标逐渐
arr[i] = (int)(Math.random()*100);
}
}
/*
打印数组中元素
*/
public static void outputArray(int[] arr){
if(arr == null){
System.out.println("null");
}
if(arr.length == 0){
System.out.println("[]");
}
System.out.print("[");
for(int i = 0;i<arr.length;i++){
if(i == arr.length-1){
System.out.print(arr[i]);
}else {
System.out.print(arr[i] + ",");
}
}
System.out.println("]");
}
}
修改数组中的元素
数组修改有两种方式:
1.直接指定下标,修改对应位置的值【对下标需要进行判断,是否超出范围】
PS: 数组的下标是从 【0】 开始到 【数组长度-1】结束 , 下标是不允许小于0 或 大于等于数组长度
/**
* 修改数组中指定位置的值
* @param arr 整数数组
* @param index 要修改位置的下标
* @param number 要修改的值
* @return true 修改成功, false 修改失败【1.index超出范围,2.没有number操出存储范围】
*/
public static boolean changeNumberForArray(int[] arr,int index,int number){
//获取int类型数据最大值 Integer.MAX_VALUE
//int maxValue = Integer.MAX_VALUE;
//获取int类型数据最小值 Integer.MIN_VALUE
//int minValue = Integer.MIN_VALUE;
for (int i = 0; i < arr.length; i++) {
//i值就是当前下标范围
if (index == i) { //index并没有超出范围,并且找到了
arr[index] = number; //修改了指定位置的值
//修改成功
return true;
}
}
return false;
}
2.指定一个数据,判断这个数据是否存在在数组中,如果存在着修改,否则不做任何修改
PS:就需要使用到数组的查找【线性查找,二分查找】
线性查找
线性查找又名顺序查找,就是遍历数组每一个元素进行比较,如果找到了就返回找到之后的值【返回下标】,否则没有找到就返回一个负数【返回-1】
好处在于:比较好写,适用于绝大部分的查找操作
坏处在于:之心高效率比较低【最坏情况时在最后一位置找到数据】
PS:这个查找方式即可以使用普通for循环 也可以使用增强for循环
/**
* 查找数组中的元素
* @param arr 整数数组
* @param number 要查找的数据
* @return 如果是int返回值 找到就是下标 找不到就是-1
* 如果是boolean返回值 找到就是true,找不到就是false
*/
public static boolean FindNumberForArray(int[] arr,int number){
for(int a : arr){
if(a == number){
return true;// 只要找到这个值,就停止寻找
}
}
return false; //没有找到值
}
二分查找
二分查找又名【折半查找】:使用这个查找法有一个必要前提【必须排序,默认升序】
通过计算得到一个中间值【中间索引】,通过这个索引获取当前对应下标【中间索引】值
然后用这个值跟要查找的值进行比较
1.如果当前值小于中间索引获取的值,就去当前数组的左半区继续查找
2.如果当前值大于中间索引获取的值,就去当前数组的右半区继续查找
PS:左右半区如何区分,是根据中间索引值划分,中间索引值的左边就是【左半区】,中间索引值的右边就是【右半区】
如何确定是否找到
1.当中间索引获取值 等于 要查找的值 就能证明找到了
2.当出现交叉的时候,就没有找打
PS:这个交叉指什么,开始值和结束值之间出现错位【开始值 > 结束值】
好处在于: 查找速度快,每一次查找都是原有数组长度的一半
坏处在于:存在必要的弊端【需要排序】,所以就限制部分数据
计算逻辑
PS:必须先排序,默认升序
1.先根据数据下标定义开始值【beginIndex】和结束值【endIndex】
PS:这个开始值默认是第一个数据下标,结束值是默认最后一个数据下标
2.通过beginIndex和endIndex计算中间值【middleIndex】
middleIndex = (beginIndex+endIndex)/2
3.数组中就会就会的到一个开始值、结束值、中间值
4.通过中间值即下标位置 获取对应数据
4.1 如果获取数据大于要比较数据 number > arr[middleIndex]
就去中间值右半区继续查找,需要重新计算中间
4.1.1 先移动开始值【beginIndex】 bginIndex = middleIndex+1
4.1.2 重复第2到第4步骤之间的操作
4.2 如果获取数据小于要比较数据 number < arr[middleIndex]
就去中间值的做边去继续查找,需要重新计算中间
4.2.1 先移动结束值【endIndex】 endIndex = middleIndex -1
4.2.1 重复第2到第4步骤之间的操作
5.如何是查找到了,如何是查找到
5.1 找到了 中间值获取的数据 等于 要查找值 arr[middleIndex] == number
5.2 找不到 即出现开始值和结束值 之间出现了交叉
beginIndex > endIndex
5.2.1 如果是向左移动是endIndex ,endIndex的最终值是 (0-1) --> endIndex = -1
beginIndex固定0 ,所以出现的就是 0 > -1 超出
5.2.2 如果是向右移动是beginIndex, beginIndex最终值 (数组长度-1 + 1) --> beginIndex = 数组长度
endIndex固定 数组长度-1 所以出现就是 数组长度 > 数组长度-1 超出
添加查询方法
/**
* 二分查找
* @param arr 要查找的数组
* @param number 要查找的数
* @return 找到了返回下标 找不到返回-1
*/
public static int binarySearch(int[] arr ,int number){
//1.定义开始值和结束值,并计算中间值
int beginIndex = 0;
int endIndex = arr.length-1;
int middleIndex = (beginIndex+endIndex)/2;
//因为不去定到底要找多少次,所以我选用死循环
while(true){
//开始查找缩小范围
if(number > arr[middleIndex]){
//修改开始索引值 即 向右半区进行查找
beginIndex = middleIndex + 1;
}else if(number < arr[middleIndex]){
//修改结束索引值 即 向左半区进行查找
endIndex = middleIndex-1;
}else{//隐藏条件 即 找到了 【number == arr[middleIndex]】
return middleIndex;
}
//只要不执行return middleIndex 证明没有找到了,就需要重新计算中间值
middleIndex = (beginIndex+endIndex)/2;
//做一个判断,是否出现了交叉
if(beginIndex > endIndex){
return -1;
}
}
}
删除数据
数组中是没有真正删除【原因在于数据是一个定长容器】,如果需要达到真正删除效果,就需要进行**【数组的扩容和减容操作】**
模拟删除数组中数据,用后一位数据覆盖前一位【这个操作方式只适用于基本数据类型】,记录删除的个数,在最终打印时将长度缩短【和这个打印必须是自己写】
如果是引用引用类型,建议赋值为【null】,需要注意若对数组进行其他操作,就建议进行后一位向前一位覆盖
/**
* 删除数组中元素
* @param arr 要删除的数组
* @param num 要删除数据
* @return 删除成功 会返回删除元素个数 ,如 删除失败 -1
*/
public static int removeNumber(int[] arr ,int num){
//判断数据是否存在数组中
if (FindNumberForArray(arr,num)){
//统计删除个数
int count = 0;
for(int i = 0 ;i<arr.length;i++){
if(arr[i] == num){
//前移覆盖 -1主要是为了防止越界
for(int j = i ; j<arr.length-1;j++){
arr[j] = arr[j+1];
}
count++;
//如果出现数据怎么办【不相邻】
i--;
}
}
return count;
}else{
return -1;
}
}
完整版本
import java.util.Arrays;
import java.util.Scanner;
/**
* 增删改查操作
*/
public class CRUDArrayDemo {
public static void main(String[] args) throws InterruptedException {
//1.向数组中添加数据
int[] arr = new int[10];
Scanner input = new Scanner(System.in);
while(true) {
System.out.println("请输入1~4数字执行数组操作");
int num = input.nextInt();
switch (num) {
case 1:
System.out.println("-----------------------------对数组增加值---------------------------");
inputArray(arr);
//Arrays 是数组的工具类 提供一些常用对数组操作 【排序,打印,查找,拷贝,填充,比较等等】
//toString将数组转换为字符串对象,将存储在数组中内容以字符串的形式输出
//参数是获取一个数组对象【数组名称】
System.out.println(Arrays.toString(arr));
break;
case 2:
System.out.println("-----------------------------对数组进行修改---------------------------");
System.out.println("请输入一个下标值:");
int index = input.nextInt();
System.out.println("请输入要修改的值:");
//Java是不能直接在控制台上获取字符,只能直接在控制台上获取字符串
//next 或 nextLine 控制台上获取字符串
//就需要使用到字符串中一个方法--》charAt()参数 下标 --》字符串底层实现就是一个字符数组【所以字符串支持下标】
//chatAt(0) 获取字符串第一个字符
//char ch = input.next().charAt(0);
int number = input.nextInt();
boolean b = changeNumberForArray(arr, index, number);
if (b) {
System.out.println("修改成功");
System.out.println(Arrays.toString(arr));
} else {
System.out.println("修改失败无法修改,下标或数据错误");
}
break;
case 3:
System.out.println("-----------------------------对数组进行查找--------------------------");
System.out.println("请输入8【顺序查找】和9【二分查找】之前值:");
int n= input.nextInt();
switch (n) {
case 8:
System.out.println("-----------------------------对数组进行顺序查找--------------------------");
System.out.println("请输入一个数据:");
int number1 = input.nextInt();
boolean b1 = FindNumberForArray(arr, number1);
if (b1) {
System.out.println("数组存在这个值的");
} else {
System.out.println("数组中是没有这个值");
}
break;
case 9:
System.out.println("-----------------------------对数组进行二分查找--------------------------");
System.out.println("请输入一个数据:");
int number2 = input.nextInt();
System.out.println("-----------------------数组正在排序为您查找中--------------------------");
//让线程休眠3秒
Thread.sleep(3000);
sortArray(arr);//排序
int index1 = binarySearch(arr, number2); //返回的是一个下标值
if(index1 >= 0){
System.out.println("数组中存在这个值");
}else{
System.out.println("数组中不存在这个值");
}
break;
}
case 4:
System.out.println("-----------------------------对数组进行删除操作--------------------------");
System.out.println("请输入一个要删除数据:");
int number3 = input.nextInt();
int i = removeNumber(arr, number3);//删除
removeNumberForArrayPrint(arr,i);//打印
break;
default:
return;
}
}
}
/*
向数组添加数组
*/
public static void inputArray(int[] arr){
/*
一个是普通for循环【操作数组下标】,通过对下标的获取操作,从而操作数组
即可以对数据进行赋值,也可以对数据进行取值操作
一个是增强for循环【foreach】 只能对数据中元素进行取值操作,取值之后可以对数据
进行 计算,判断,打印等等,当前循环是不能对数组进行赋值操作,原因在于是循环中会定义一个局部变量
这个变量会获取数组中每一个元素的值,操作时候等于是操作这个局部变量,而非是操作数组中元素
*/
//采用普通for循环
for(int i = 0;i<arr.length;i++){
//i变量就相当于是数组中的下标,根据i值的自增下标逐渐
arr[i] = (int)(Math.random()*100);
}
}
/*
打印数组中元素
*/
public static void outputArray(int[] arr){
if(arr == null){
System.out.println("null");
}
if(arr.length == 0){
System.out.println("[]");
}
System.out.print("[");
for(int i = 0;i<arr.length;i++){
if(i == arr.length-1){
System.out.print(arr[i]);
}else {
System.out.print(arr[i] + ",");
}
}
System.out.println("]");
}
/**
* 修改数组中指定位置的值
* @param arr 整数数组
* @param index 要修改位置的下标
* @param number 要修改的值
* @return true 修改成功, false 修改失败【1.index超出范围,2.没有number操出存储范围】
*/
public static boolean changeNumberForArray(int[] arr,int index,int number){
//获取int类型数据最大值 Integer.MAX_VALUE
//int maxValue = Integer.MAX_VALUE;
//获取int类型数据最小值 Integer.MIN_VALUE
//int minValue = Integer.MIN_VALUE;
for (int i = 0; i < arr.length; i++) {
//i值就是当前下标范围
if (index == i) { //index并没有超出范围,并且找到了
arr[index] = number; //修改了指定位置的值
//修改成功
return true;
}
}
return false;
}
/**
* 查找数组中的元素
* @param arr 整数数组
* @param number 要查找的数据
* @return 如果是int返回值 找到就是下标 找不到就是-1
* 如果是boolean返回值 找到就是true,找不到就是false
*/
public static boolean FindNumberForArray(int[] arr,int number){
for(int a : arr){
if(a == number){
return true;// 只要找到这个值,就停止寻找
}
}
return false; //没有找到值
}
/**
* 对数组进行排序
* @param arr
*/
public static void sortArray(int[] arr){
//1.选择排序--》固定一个位置,依次和后面的每一个数据进行比较,发生大于关系,就交换
//外层循环【循环的次数,当前比较次数,固定位置】
for(int i = 0;i<arr.length;i++){
//内层循环不结束,外层循环不能开启下一次,所以i值对于内层循环而言是固定值
//内层循环的开始值,应该是固定位置的下一位,因为一轮循环结束之后固定位置值一定是有序的【正确】
//下一轮比较的时候就不需要在此比较了
for(int j = i+1;j<arr.length;j++){
if(arr[i] > arr[j]){ //升序就是> 降序 <
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
}
/**
* 二分查找
* @param arr 要查找的数组
* @param number 要查找的数
* @return 找到了返回下标 找不到返回-1
*/
public static int binarySearch(int[] arr ,int number){
//1.定义开始值和结束值,并计算中间值
int beginIndex = 0;
int endIndex = arr.length-1;
int middleIndex = (beginIndex+endIndex)/2;
//因为不去定到底要找多少次,所以我选用死循环
while(true){
//开始查找缩小范围
if(number > arr[middleIndex]){
//修改开始索引值 即 向右半区进行查找
beginIndex = middleIndex + 1;
}else if(number < arr[middleIndex]){
//修改结束索引值 即 向左半区进行查找
endIndex = middleIndex-1;
}else{//隐藏条件 即 找到了 【number == arr[middleIndex]】
return middleIndex;
}
//只要不执行return middleIndex 证明没有找到了,就需要重新计算中间值
middleIndex = (beginIndex+endIndex)/2;
//做一个判断,是否出现了交叉
if(beginIndex > endIndex){
return -1;
}
}
}
/**
* 删除数组中元素
* @param arr 要删除的数组
* @param num 要删除数据
* @return 删除成功 会返回删除元素个数 ,如 删除失败 -1
*/
public static int removeNumber(int[] arr ,int num){
//判断数据是否存在数组中
if (FindNumberForArray(arr,num)){
//统计删除个数
int count = 0;
for(int i = 0 ;i<arr.length;i++){
if(arr[i] == num){
//前移覆盖 -1主要是为了防止越界
for(int j = i ; j<arr.length-1;j++){
arr[j] = arr[j+1];
}
count++;
//如果出现数据怎么办【不相邻】
i--;
}
}
return count;
}else{
return -1;
}
}
/*
配合删除使用打印
*/
public static void removeNumberForArrayPrint(int[] arr,int count){
if(count > 0){
System.out.print("[");
for(int i = 0;i<arr.length-count;i++){
if(i == arr.length-1-count) {
System.out.print(arr[i]);
}else{
System.out.print(arr[i]+",");
}
}
System.out.println("]");
}else{
System.out.println("当前数据不存在无法删除");
}
}
}
数据工具类Arrays和可变参数
Arrays工具类
Arrays工具类是JavaAPI中自带的一个工具类,主要的目的就是为了方便操作数组
-
-
static <T> List<T>
asList(T... a)
返回由指定数组支持的一个固定大小的列表。PS:就是数组为参数返回一个List集合
-
什么是可变参数?
可变参数是定义在方法参数列表总一种形式,这个参数类型的定义有一个特殊方式必须使用**【…】**,一个方法中的可变参数有且仅有一个,必须出现在所有定义参数的末尾
可变参数是一个比较好使用参数定义,既然是可变就意味着【什么都不传 或 传多个】,在方法体的内部对可变参数的操作是以一维数组从形式操作
/**
* 可变参数
*/
public class ArrayDemo {
public static void main(String[] args) {
// 调用方法传递参数
//1.可变参数就意味着什么都没有
showInfosArray();
//2.可以传递多个参数
showInfosArray(1,2,3,4,5,6,7,8,9);
//3.支持一维数组作为参数存在
int[] arr = {1,2,3,4,5};
showInfosArray(arr);
}
//形式必须是 数据类型... 变量名
public static void showInfosArray(int... arr){
//方法体的内部就是一个 一维数组
for(int i = 0 ;i<arr.length;i++){
System.out.println(arr[i]);
}
}
}
Arrays工具类常用方法
import java.util.Arrays;
import java.util.Comparator;
/**
* Arrays工具类常用方法
*/
public class ArraysDemo {
public static void main(String[] args) {
int[] arr = {1,23,23231,321,521,43,1,2,13,524,24,2};
//1.toString,以字符串的形式返回数组中的内容
String string = Arrays.toString(arr);
//这个字符串是数中内容拼接,可以直接用于打印,所以常用方式
System.out.println(Arrays.toString(arr));
//2.排序【默认升序,以先做所学无法降序】
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
//3.降序,第一个数组中必须是引用类型即基本数据类型对应包装类
// 需要实现一个Comparator接口 指定排序方式
// Integer[] arr2 = {1,2,4,2,6,2,643,25634,534,63,1234234,42};
// Arrays.sort(arr2, new Comparator<Integer>() {
// @Override
// public int compare(Integer o1, Integer o2) {
// return o2-o1;
// }
// });
// System.out.println(Arrays.toString(arr2));
// Arrays.sort(arr2,(o1,o2)->o1-o2);
// System.out.println(Arrays.toString(arr2));
//3.二分查找
int i = Arrays.binarySearch(arr, 23231);
if(i>=0){
System.out.println("找到了");
}else{
System.out.println("没有找了");
}
//4 复制数组,将原数组中数据复制到新数组中,并可以指定新数组长度
int[] newArr = Arrays.copyOf(arr,20);
System.out.println(Arrays.toString(newArr));
//5.拷贝指定范围内的数据
/*
第一个参数是要拷贝的数组,第二个参数是从什么位置开始拷贝【包含】,第三个参数是到什么位置【不包含】
参数二和参数三是下标,获取的这个下标范围内的数据
*/
int[] newArr_2 = Arrays.copyOfRange(arr,2,5);
System.out.println(Arrays.toString(newArr_2));
//6.使用指定数据填充数组【只能是固定值】
Arrays.fill(arr,0);
System.out.println(Arrays.toString(arr));
//7.引用类型的比较
/*
如果要比较一个基本数据类型是否相等,此时可以使用 == 比较
如果要比较一个引用类型是否相同,严禁使用 == 比较, 这里 == 比较的是 两个引用类型的地址
如果认为引用类型相等
1.只要当前引用类型中,存储的数据是一致【一样】的,就认为两个引用类型相等
引用类型比较不是地址,而是存储的内容
*/
int[] a1 = {1,2,3};
int[] a2 = {1,2,3};
System.out.println(a1 == a2); //false 比较的是地址
//判断两个数组是否相等
System.out.println(Arrays.equals(a1,a2));//true ,比较的是数组中存储的元素是否相等
//特殊的
String str = "abcd";
String str2 = "abcd";
System.out.println(str == str2);
Integer i1 = 123;
Integer i2 = 123;
System.out.println(i1 == i2);
}
}