【Java宝典】——探索数组的奥秘之旅
Java数组的创建和使用
·
🌈个人主页: Aileen_0v0
🔥热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法
💫个人格言:“没有罗马,那就自己创造罗马~”
文章目录
Java数组常见报错
①:ArrayIndexOutOfBoundsException(数组索引超出范围)
public static void main(String[] args) {
//java常见报错1:
boolean[] array2 = new boolean[10];
System.out.println(array2[10]);
}
②:NullPointerException(空指针异常)
public static void main(String[] args) {
//java常见报错2:
int[] array = null;
System.out.println("数组的长度是: " +array.length);
}
数组的三种遍历方式
public static void main(String[] args) {
int[] array = {1,2,3,4};
//Java循环遍历方式1:访问下标形式
for (int i = 0 ; i < array.length; i++){
System.out.print(array[i]+" ");
}
System.out.println();
//Java循环遍历方式2:for-each 只是遍历程序,不能通过下标访问
for (int Aileen : array){
System.out.print(Aileen + " ");
}
System.out.println();
//Java遍历循环方式3:toString将数组转换为字符串
String ret= Arrays.toString(array);
System.out.println(ret);
}
public class X {
public static void main(String[] args) {
int[] array1 = new int[3];
array1[0] = 10;
array1[1] = 20;
array1[2] = 30;
System.out.println(array1);
int[] array2 = new int[]{1,2,3,4,5};
array2[0] = 100;
array2[1] = 200;
System.out.println(array2);
array1 = array2;
array1[2] = 300;
array1[3] = 400;
array2[4] = 500;
System.out.println(array1);
System.out.println(array2);
}
}
array1这个引用 指向 array2这个引用所指向的对象 |
array1 和 array2这两个引用 指向 的都是array2这个引用所指向的对象 |
0x87这个对象 当没有引用 再指向这个对象,就被JVM回收了. |
int[] array = null; 代表array这个引用 不指向任何对象. 这就意味着0不能调用它的下标,长度等 |
Java中栈和堆的关系
栈(Stack)是一种后进先出(LIFO)的数据结构,用于存储方法调用和局部变量。 每当一个方法被调用时,Java虚拟机会为该方法创建一个栈帧,并将其推入栈中。 栈帧包含了方法的参数、局部变量以及方法返回时需要的信息。 当方法执行完毕后,对应的栈帧会被弹出,释放相应的内存空间。 |
堆(Heap)是用于动态分配对象的内存区域。 在Java中,所有通过new关键字创建的对象都存储在堆中。 堆是一种可扩展的内存区域,它的大小可以根据需要进行调整。 堆中的对象可以被多个线程共享,因此需要进行线程安全的管理。 |
栈和堆之间的关系是:栈中存储了对堆中对象的引用。 当我们在栈中声明一个对象引用变量时,实际上只是在栈中创建了一个引用,而对象本身仍然存储在堆中。 通过引用变量,我们可以访问和操作堆中的对象。 |
Java中の数据类型
在Java中,数据类型可以分为基本数据类型和引用数据类型。
基本数据类型是Java语言中预定义的数据类型,它们包括整数类型(byte、short、int、long)、浮点数类型(float、double)、字符类型(char)和布尔类型(boolean)。 基本数据类型的值直接存储在变量中,它们占用固定的内存空间,并且在内存中分配的位置是连续的。 基本数据类型的赋值是将值直接复制给变量。 |
引用数据类型是由程序员定义的类、接口、数组等类型。 引用数据类型的变量存储的是对象的引用(内存地址),而不是对象本身。 引用数据类型的变量在内存中占用的空间大小是固定的,但它们指向的对象可以动态地分配和释放内存。 引用数据类型的赋值是将对象的引用复制给变量,多个变量可以指向同一个对象。 |
基本数据类型和引用数据类型的区别总结如下:
存储方式
:基本数据类型的值直接存储在变量中,而引用数据类型的变量存储的是对象的引用。内存分配
:基本数据类型在内存中分配的位置是连续的,而引用数据类型的对象可以动态地分配和释放内存。大小固定性
:基本数据类型占用固定的内存空间,而引用数据类型的变量在内存中占用的空间大小是固定的。赋值方式
:基本数据类型的赋值是将值直接复制给变量,而引用数据类型的赋值是将对象的引用复制给变量。
public class X {
public static void main(String[] args) {
int[] array = {1,2,3,4};
fun1(array);
//打印第一个函数的值
System.out.println(Arrays.toString(array));
System.out.println(array);
}
public static void fun1(int[] array22){
array22 = new int[]{11,22,33,44,55};
}
}
因为引用只是修改了形参(局部变量)的指向,当程序执行完以后,形参和其对应的堆上的地址就会自动销毁. 程序最后的打印结果是1,2,3,4所以说不是传了引用,就一定能够修改实参的值 |
①形参不能改变实参的值的情况(只修改指向)
因为引用只是修改了形参(局部变量-红色框框内)的指向[这两个引用分别指的是不同的对象.],当程序执行完以后,形参和其对应的堆上的地址(对象)就会自动销毁. 程序最后的打印结果是1,2,3,4所以说不是传了引用,就一定能够修改实参的值 |
引用变量当中存地址 引用指向对象 |
②形参可以改变实参的值的情况(修改同一个指向所指向的对象)
public class X {
public static void main(String[] args) {
int[] array = {1,2,3,4};
fun2(array);
for (int i = 0 ; i < array.length; i++){
System.out.print(array[i]+" ");
}
System.out.println();
System.out.println(array);
}
public static void fun2(int[] array11){
array11[0] = 99;
}
}
两个引用(array和array11)同时指向同一个对象,所以通过形参修改,实参也会跟着改变 |
从上面的例子也可以看出,形参和实参的名字可以一样也可以不一样. |
public class X {
public static void main(String[] args) {
int x = 10;
func4(x);
System.out.println(x);
}
public static void func4(int a){
a = 20;
}
}
从上面的例子可以看出, 传入基本数据类型,不能通过形参修改实参的数值. |
数组作为返回值进行进行返回
public class X {
public static void main(String[] args) {
int[] ret = func5();
System.out.println(
Arrays.toString(ret)
);
}
public static int[] func5(){
int[] array = {1,2,3,4};
return array;
}
}
首先创建的ret数组先访问函数func5, 其次为创建的array(引用)这个数组开辟一块空间然后指向堆上的地址0x99. 然后将array的值返回出来赋值给ret,并且指向array的对象, 最后打印并返回出array的值. |
数组练习
数组转字符串
public class X {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6};
//创建方法的对象
String ret = myToString(arr);
System.out.println(ret);
}
//自己创造的转为字符串的方法
public static String myToString(int[] arr) {
String ret = "[";
for (int i = 0; i < arr.length; i++) {
ret += arr[i];
if(i != arr.length-1 ){
ret += ",";}
}
ret += "]";
return ret;
}
}
public class X {
//但是下面这种写法漏了判断array是否为null的情况.
public static void main(String[] args) {
int[] array = null;
String ret = myToString(array);
System.out.println(array);
}
public static String myToString(int[] array){
//判断数组array为null的情况
if (array == null){
return "null";
}
String ret = "[";
for (int i=0;i < array.length;i++){
ret += array[i];
if (i != array.length- 1){
ret += ",";
}
}
ret += "]";
return ret;
}
}
数组的copy
public class X {
//但是下面这种写法漏了判断array是否为null的情况.
public static void main(String[] args) {
//先定义一个数组
int[] array = {1,2,4,5,8};
//开始复制:首先复制他原来的数组空间大小
int[] copy = new int [array.length];
//通过循环遍历,将原数组的值传入到新创建的数组
for (int i = 0; i < copy.length; i++) {
copy[i] = array[i];
}
//打印新创建数组的值
System.out.print(Arrays.toString(copy));
}
}
✨️ 数组的复制
方法1:使用copyof进行复制
import java.util.Arrays;
public class x {
public static void main(String[] args) {
int[] array ={1,2,3,4};
//拷贝 array 这个数组 ,长度为 array.length
int[] copy = Arrays.copyOf(array,array.length);
System.out.println(Arrays.toString(copy));
}
}
方法2:使用copyofRange进行部分复制
在JAVA中数组的复制from…to范围一般是左闭右开的,如下所示:
import java.util.Arrays;
public class x {
public static void main(String[] args) {
int[] array = {1,2,3,4,5};
int[] copy = Arrays.copyOfRange(array,1,3);
System.out.println(Arrays.toString(copy));
}
}
方法3:使用arraycopy进行复制
所有被native修饰的是由C/C++进行实现的,所有我们不能看到这个方法的源码,但是它的优点是运行速度比较快
import java.util.Arrays;
public class x {
public static void main(String[] args) {
int[] array = {1,2,3,4,5};
int[] dest = new int[array.length];
System.arraycopy(array,0,dest,0,array.length);
System.out.println(Arrays.toString(dest));
}
}
arraycopy方法括号里面参数的含义用通俗的话讲就是从array这个书架的0位置开始拿书把它放到dest这个书架的0位置,这些书的长度是array.length。
方法4:使用clone进行复制
import java.util.Arrays;
public class x {
public static void main(String[] args) {
int[] array = {1,2,3,4,5};
int[] copy = array.clone();
System.out.println(Arrays.toString(copy));
}
}
数组的扩容
将数组扩大2倍
public class X {
public static void main(String[] args) {
//数组扩容
int[] array = {1,2,3,4};
//拷贝array 这个数组 ,新的长度为 array.length * 2
array = Arrays.copyOf(array,array.length*2);
//array 指向了 新的数组空间
System.out.println(Arrays.toString(array));
}
}
顺序查找数组中的指定元素
法1:循环查找-有序无序都适用
public class FindElement {
// 主方法,程序的入口点
public static void main(String[] args) {
// 定义并初始化一个整型数组 array
int[] array = {1,2,5,4,5};
// 定义并初始化另一个整型数组 myarray
int[] myarray = {9,8,7,6,5};
// 调用 search 方法搜索数组 array 中的元素 556,并打印返回值
System.out.println(search(array, 556));
// 调用 search2 方法搜索数组 myarray 中的元素 8,并打印返回值
System.out.println(search2(myarray, 8));
}
// 定义一个静态方法 search,用于在整型数组中搜索给定的 key 值
public static int search(int[] array, int key) {
// 遍历数组
for (int i = 0; i < array.length; i++) {
// 如果找到 key 值,返回当前索引
if (array[i] == key) {
return i;
}
}
// 如果没有找到 key 值,返回 -1
return -1;
}
// 定义另一个静态方法 search2,与 search 方法功能相同,用于在整型数组中搜索给定的 key 值
public static int search2(int[] array, int key) {
// 遍历数组
for (int i = 0; i < array.length; i++) {
// 如果找到 key 值,返回当前索引
if (array[i] == key) {
return i;
}
}
// 如果没有找到 key 值,返回 -1
return -1;
}
}
法2:二分查找-使用前提:元素必须按照从小到大排序
import java.util.Arrays; // 导入 Arrays 类,用于数组操作
public class BinarySearch {
public static void main(String[] args) {
int[] array = {5, 3, 6, 8, 7}; // 定义并初始化一个整型数组
Arrays.sort(array); // 使用 Arrays 类的 sort 方法对数组进行排序
System.out.println(Arrays.toString(array)); // 打印排序后的数组,输出格式为 [3, 5, 6, 7, 8]
// 调用 binarySearch 方法在数组中搜索键值 111,并打印返回结果
System.out.println(binarySearch(array, 111));
}
// 定义一个静态方法 binarySearch,用于在排序后的数组中进行二分查找
public static int binarySearch(int[] array, int key) {
int i = 0; // 初始化左边界索引为 0
int j = array.length - 1; // 初始化右边界索引为数组长度减 1
while (i <= j) { // 当左边界索引小于等于右边界索引时,继续循环
int mid = (i + j) / 2; // 计算中间索引
if (array[mid] < key) { // 如果中间索引处的值小于键值,说明键值在右半部分
i = mid + 1; // 将左边界索引移动到中间索引的下一个位置
} else if (array[mid] == key) { // 如果中间索引处的值等于键值,返回中间索引
return mid; // 找到键值,返回其索引
} else { // 如果中间索引处的值大于键值,说明键值在左半部分
j = mid - 1; // 将右边界索引移动到中间索引的前一个位置
}
}
// 如果没有找到键值,返回 -1
return -1;
}
}
除了通过自己写二分查找以外,Java还可以直接调用Arrays库里面的binarySearch直接进行二分查找。
import java.util.Arrays; // 导入 Arrays 类,用于数组操作
public class BinarySearch {
public static void main(String[] args) {
int[] array = {5, 3, 6, 8, 7}; // 定义并初始化一个整型数组
Arrays.sort(array); // 使用 Arrays 类的 sort 方法对数组进行排序
System.out.println(Arrays.toString(array)); // 打印排序后的数组,输出格式为 [3, 5, 6, 7, 8]
// 调用 binarySearch 方法在数组中搜索键值 111,并打印返回结果
System.out.println(Arrays.binarySearch(array, 7));
}
}
我们除了通过使用Arrays类里面的sort进行从小到大排序以外,还可以利用reverse进行逆向排序。
import java.util.Arrays; // 导入Arrays类,用于调用数组相关的工具方法,如toString()
public class ReverseSorted {
public static void main(String[] args) {
int[] array = {1,2,3,31,14,5}; // 定义并初始化一个整型数组
reverse(array); // 调用reverse方法,传入数组作为参数
System.out.println(Arrays.toString(array)); // 打印数组的字符串表示,查看反转后的结果
}
public static void reverse(int[] array){ // 定义一个名为reverse的方法,用于反转数组
int i = 0; // 初始化索引i为0,指向数组的起始位置
int j = array.length-1; // 初始化索引j为数组长度减1,指向数组的末尾位置
while (i < j){ // 当索引i小于索引j时,继续循环
int temp = array[i]; // 将索引i处的元素暂存到临时变量temp
array[i] = array[j]; // 将索引j处的元素赋值给索引i处
array[j] = temp; // 将临时变量temp的值(原索引i处的元素)赋值给索引j处
i++; // 索引i向后移动一位
j--; // 索引j向前移动一位
}
}
}
通过Arrays中的equals关键字判断数组是否相等
import java.util.Arrays;
public class Equals {
public static void main(String[] args) {
int [] array1 = {1,8,4,5};
int [] array2 = {1,8,4,5};
int [] array3 = {1,2,3,3};
System.out.println(Arrays.equals(array1,array2));
System.out.println(Arrays.equals(array1,array3));
}
}
Arrays局部填充用fill关键字
import java.util.Arrays;
public class PartFill
{
public static void main(String[] args) {
int [] array = new int[10];
Arrays.fill(array,1,3,99);//下标1-2处填充为99
System.out.println(Arrays.toString(array));
}
}
冒泡排序
冒泡排序流程图
import java.util.Arrays;
public class BubbleSort {
public static void main(String[] args) {
int[] array = {1,5,3,2,9};
System.out.println(Arrays.toString(array));
bubbleSort(array);
System.out.println(Arrays.toString(array));
}
public static void bubbleSort(int[] array){
//循环要比较的趟数 , 5个数据比较4趟
for(int i = 0 ; i < array.length-1;i++ ){
//---优化:假设本来就有序,进入下面的循环则变为无序。
boolean order = false;//假设有序
//循环控制每趟比较次数 , 因为每一次比上一次少比较一趟
for (int j = 0; j < array.length - 1 - i;j++){
if (array[j] > array[j+1]) {
int temp = array[j];
array [j] = array[j+1];
array[j+1] = temp;
order = true;
}
}
//如果为false则有序,直接返回
if (order == false) {
return;
}
}
}
}
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
已为社区贡献7条内容
所有评论(0)