Java基础知识整理【5】 (数组)

JVM内存图

在这里插入图片描述
ps:JVM内存的划分,根据人为的不同可以划分为不同的样式,上图是基本的内存图

程序计数器
当前线程所执行的字节码行号(执行到那个位置就添加对一个序号)

本地方法栈
为虚拟机使用native方法所提供的服务(java中有一些方法是使用native修饰,没有具体方法体,他们的实现是通过本地 系统C++类库或C类库进行实现)

Java虚拟基栈(栈空间)
描述Java方法执行的内存模型,每个方法执行的时候都会站在栈中创建一个栈帧,栈帧可以存储局部变量,操作栈,动态链
接,方法的出口等信息 ps:每一个方法,创建一个栈帧,栈帧张总存放了当前方的数据信息,当前反方执行完成之后,会还行弹栈,销毁栈帧
Java堆 被所有线程共享的一块存储区域,在虚拟机启动的时候会创建.所有对象都是开辟在堆空间中
ps:在堆开辟空间,需要使用一个关键字 new -->代表在堆中开辟了一块新空间
方法区
所有线程共享的区域,存储已被虚拟机加载的类信息(.class)、常量、静态变量,即实时编译所的到的数据都存在这个区 域

Java数组

声明变量–>>>数据类型 变量 = 值;
声明变量的作用是方便在代码中对数据的一种操作

当出现相对来说比较大的数据量是,使用变量进行管理就不回特别方便;此时java提供了一种数据结构,对大量数据进行储存并进行统一管理,这个数据结构就是–>>数组
1、数组储存数据的时候会记录数据的位置和具体值方便操作
2、数组是一个定长的数据结构(一旦确定数组大小,就不能存储超过范围的数据)
3、数组是开辟在堆空间,连续存的一个内存空间
4、数组中只能储存相同数据类型的元素(值)ps:不是绝对的,学习object后,数组也可以存所有object类型的数据(子类) 数组是一种数据结构,储存在数组中的数据是按照一定顺序排列而成的

数组中元素的数据类型
数组的可以声明成基本类型和引用数据类型

引用数据类型:数组,字符串,自定义类,集合等等
无论是基本数据类型还是引用数据类型,创建数组的时候,数组中都会存储默认值
在这里插入图片描述

整数类型存储默认值都是:0 
小数类型存储的默认值都是 0.0
char类型存储的是一个空字符-->不可见
引用类型存的是 null --> 空 --> 在堆中没有开辟 
ps:需要注意一个问题NullPoniterException空指针异常 这个异常的原因是因为,使用null进行一些操作

如何声明数组

/**
* 数组的四种创建方式 * @author JKMaster *
*/
public class ArrayDemo1 {
public static void main(String[] args) {
                // 1.标准创建 :创建数组的同时指定数组的大小
                //语法 数组中元素的数据类型[] 数组名 = new 数组中元素的数据类型[数组中元素的个数(即是数组的大小也是数组的长度)];
               //数组的数据类型是: 数据类型[]
                //[]之前的数据类型是:数组元素的数据类型即数组中可以存储什么样的值 
                int[] arr = new int[10];
                
                //2.先声明,然后在对数组进行赋值(创建类时,数组作为类的属性存在)
                 /*
                * 数组中元素的数据类型[] 数组名;
                ** 数组名 = new 数组中元素的数据类型[数组中元素的个数(即是数组的大小也是数组的长度)];
                **/
                int[] arr1;
                arr1 = new int[10];
                
                //3.创建数组的同时指定数组中元素
                //语法: 数组中元素的数据类型[] 数组名 = new 数组中元素的数据类型[]{元素1,元素2,元素3.....};
                 //ps:绝对不能再[]中写入数组大小,当前数组是根据后面{ }中的元素来决定数组多大的
                 int[] arr2 = new int[] {1,2,3,4,5};
                 //此时数组的大小即5
                 
                 //4.就是第三种简化
                 //语法: 数组中元素的数据类型[] 数组名 = {元素1,元素2,元素3.....}; 
                 int[] arr3 = {1,2,3,4,5};
                 }
     }

在这里插入图片描述

如何操作数组

import java.util.Arrays;
import java.util.Scanner;
/**
* 数组基本操作
* @author JKMaster *
*/
public class ArrayDemo2 {
public static void main(String[] args) { //创建数组
//数组中元素的数据类型[] 数组名 = new 数组中元素的数据类型[数组中元素的个数(即数组大小,数组长 度)]
          int[] arr = new int[10];
           //[I@70dea4e-->不是数组的地址
      //不能通过打印数组对象的方式来打印出数组中存储的元素                 System.out.println(arr);
     //创建数组的同时,数组是有默认元素值
     //整数默认值是都是0
     //若数组中存储的是引用类型,默认值是null一定要注意判断在使用不认会出现空指针异常 
     //若创建引用类型的时候,没有赋值之前(即开辟堆空间),不要使用 System.out.println(Arrays.toString(arr));
     //取出数组某一个元素的值怎么办?
    // 下标(角标) 从0开始 到当前数组长度-1结束
   //例如 有一个数组,数组的长度是5 它的下标就是 0,1,2,3,4
   //要修改数组中第一个元素的值
    //语法:数组名[下标值] = 值;

总结:
若访问数组中的元素,需要通过下标完成,下标范围 从0开始(第一位) 到 当前数组长度-1结束(最后一位)
数组名[下标值] = 值; --> (赋值)
数组类型 变量名 = 数组名[下标值] 或 System.out.println(数组名[下标]) --> (取值)
下标值不能是负数或大于等于数组长度,不然会出现一个异常
ArrayIndexOutOfBoundsException -->数组下标越界异常(数组中的下标超出了范围)

获取数组长度: 数组名.length --> 便捷的获取数组的最后一位的下标 数组名.length-1
//通过数组下标对应的元素进行修改
arr[0] = 100; System.out.println(Arrays.toString(arr));

//需要取出数组中的值 —>>>语法 数组名[下标值];

//ps:需要注意数组下标的值绝对不能是负数或是大于等于数组的长度 //ArrayIndexOutOfBoundsException -->数组下标越界异常(数组中的下标超出了范围) //System.out.println(“访问数组中的元素:”+arr[10]);

//获取数组长度
System.out.println(“数组的长度:”+arr.length); //访问数组中最后一个元素 System.out.println(“数组中最后一个元素是:”+arr[arr.length-1]);

如何给数组赋值
//1.静态赋值
int[] nums = {1,2,3,4,5,6};
//2.动态赋值
Scanner input = new Scanner(System.in);
arr2[0] = input.nextInt();
//使用随机数
arr2[1] = (int)(Math.random()*100); System.out.println(Arrays.toString(arr2));
} }

如何遍历数组

1、普通for循环
2、增强for循环(foreach)

/**
* 遍历数组的两种方式 * @author JKMaster *
*/
public class LoopArrayDemo {
                 public static void main(String[] args) {
                          int[] arr = new int[10]; 
                          //向数组中随机插入0-100之间值
                           //普通for循环
                           //i =0的原因是因为:若需要操作数组中的元素,需要使用下标 
                           //i作为循环变量,从0开始,数组中第一个元素的下标
                            //通过不断的自增i变量以达到操作数组下标的目的 
                            //当下标到达数组长度的时候,循环停止即可
                     for(int i = 0; i<arr.length;i++) {
                                 arr[i] = (int)(Math.random()*100);
                      }
                   //打印数组中的值
                    for(int i = 0;i<arr.length;i++) {
                            System.out.println("数组中第"+(i+1)+"位置的值是:"+arr[i]); }
                             System.out.println("-------------------------------------------------华丽的分割线---- -------------------------------------");
                             //增强for循环 /*
                             * 语法: for(数组中元素数据类型 变量名:数组名){ 操作当前变量就等于获取了数组存储的元素值
                             *  } */
                             * //通过增强for循环改变数组原有的值
                             * // 在for循环中相同定义了变量a 这个a获取数组每一个元素 /*
                             int ai[];
                             int l = (ai = arr).length;
                             for (int j = 0; j < l; j++){
                                       int a = ai[j];
                                       a = 0; 
                             }
*
*/
                       for(int a : arr) {
                        //这个所做的并不是给数组中修改值,而是给当前局部变量a修改值 a = 0;
                    }
                    //增强for循环对数组进行打印,不能赋值 System.out.println("通过增强for循环对数组中元素进行赋值");
                     for(int a1 : arr) {
                         System.out.println(a1);
                     }
              }
}

数组排序

数组中排序有很多种:冒泡,选择,插入,快排,堆,归并等排排序方式

冒泡排序:


         //打印没有排序之前数组值 System.out.println(Arrays.toString(arr));
         //对数组进行排序操作 //1.数组中所有的元素都需要进行一次比较,所以通过循环满足每一个元素比较 for(int i = 0 ;i<arr.length;i++) {
          //控制比较次数
         //arr.length-1的目的是为了方式数组下标越界异常 原因在于 j+1 会到大数组的长度 
         //-i随着比较次数的逐渐增多,每一次都会有一个正确数放到正确的位置,那么通过-i操作 
         //减少当前需要排序的元素个数
         for(int j = 0; j<arr.length-1-i;j++) {
         //具体元素的比较
                 if(arr[j] > arr[j+1]) { //交换
                    int tmp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = tmp;
                }
         }

选择排序:

//先确定循环的次数,有多少个元素就执行多次
      for(int i = 0;i<arr.length;i++) {
       //循环的次数即比较次数
       //j的初始变量值是i+1 即i的下位,因为i是固定比较值
                 for(int j = i+1;j<arr.length;j++) {
                 //具体数据的比较
                 //i值就是一个固定的元素值 
                      if(arr[i] > arr[j]) {
                            int tmp = arr[i];
                            arr[i] = arr[j];
                            arr[j] = tmp;
                     }
             }
     }

线性查找和二分查找

当前这两种查找方式都可以在数组查找出需要的数据

线性查找

/**
* 线性查找数据
* @param arr 是一个整数数组
* @param num 是要查找的值
* @return 返回的值正数就知道即下标 */
返回的是-1即没有找到
public static int LinearSearchNumber(int[] arr,int num) { //线性查找即顺序查找,将整个数组进行遍历比较每一个元素
for(int i = 0; i<arr.length;i++) {
            if(arr[i] == num) {
                return i;
             } 
}
//当循环是通过循环条件正常停止,即没有找到相同的数据所以此时返回-1
return -1; }

二分查找

  • 二分查找理论

1.先定义一个开始值beginIndex也就是起始的位置即下标第一位
2.在定义一个结束值endIndex也就是结束的为位置即下标的最后一位
3.通过 (beginIndex+endIndex)/2得到一个中值即middleIndex
4.通过中间值获取对应数组中的数据,然后和要比较的数据进行比较
4.1当前比较的值大于中间值所对应数据,此时就需要去中间值的右半区进行查找
需要重新计算中间值,需要移动开始值beginIndex = middleIndex+1
重计算中间值即 (beginIndex+endIndex)/2得到一个中值即middleIndex
4.2当前比较的值小于中间值所对应的数据,此时就需要去中间值的左半区进行查找 需要重新计算中间值,需要移动结束值endIndex = middleIndex-1重计算中间值即 (beginIndex+endIndex)/2得到一个中值即middleIndex
4.3 查找到当前数据,即中间值的位置就要查找的数据
4.4 没有找到出现了交叉 即 beginIndex > endIndex

在这里插入图片描述

传值和传址

在这里插入图片描述在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

数组工具类

import java.util.Arrays;

public class ArrayTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] arr = new int[10];
		for(int i=0;i<arr.length;i++) {
			arr[i]= (int)(Math.random()*100);
		}
		
		String str = Arrays.toString(arr);
		System.out.println(str);
		
		//排序(升序)
		Arrays.parallelSort(arr);
		System.out.println(Arrays.toString(arr));
		
		//二分查找
		/**
		 * 找到即下标,找不到负数
		 */
		int index = Arrays.binarySearch(arr, 20);
		
		//复制数组
		/**
		 * 深拷贝:数组的地址和内容都要复制
		 * 浅拷贝:只复制数组怼内容不复制数组怼地址
		 * 第一个参数是要复制的数组
		 * 第二个参数是复制的长度,这个长度不能为负数
		 * 这里是浅拷贝
		 */
		
		int[] newArr = Arrays.copyOf(arr, 15);
		System.out.println(Arrays.toString(newArr));
		
		/*
		 * 拷贝范围内的数组
		 * 
		 * 第一个参数要拷贝数组
		 * 第一个参数是开始的位置
		 * 第三个参数是结束的位置
		 * 包括开始但是不包括结束,参数是下标
		 * 能是负数 不能超过范围
		 */
		
		int[] newArr2 = Arrays.copyOfRange(arr, 2, 5);
		System.out.println(Arrays.toString(newArr2));

		
		/*
		 * 引用类型进行比较(不能使用==)
		 * 使用==判断引用类型,比较的是内存地址值,不是内容
		 * 需要使用equals进行判断
		 */
		int[] a1 = {1,2,3,4};
		int[] a2 = {1,2,3,4};
		System.out.println("a1和a2是一样吗?"+(Arrays.equals(a1, a2)));
				
		
		
	}

}

今日总结:JVM内存原理浅析,声明数组,数组赋值,操作数组,排序遍历问题,两种查找,传值和传址

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/root1994/article/details/88940756