Java 学习之路——数组

简介: 数组(Array)是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。

Java 学习之路——数组


数组的概述


  1. 数组(Array)是多个相同类型数据一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。


  1. 数组的常见概念:
  • 数组名
  • 下标(或索引)
  • 元素
  • 数组的长度(元素的个数),一旦确定就不可以修改。


3.数组本身是引用数据类型,而数组中的元素可以是任何数据类型,包括基本数据类型和引用数据类型。


4.创建数组对象会在内存中开辟一整块连续的空间,而数组名中引用的是这块连续空间的首地址。


5.数组的长度一旦确定,就不能修改


6.可以直接通过下标(或索引)的方式调用指定位置的元素,速度很快。


7.数组的分类:

  • 按照维度:一维数组、二维数组、三维数组...
  • 按照元素的数据类型分:基本数据类型元素的数组、引用数据类型元素的数组(即对象数组)。


一维数组的使用


  1. 一维数组的声明和初始化:
int num;  // 声明
num = 10; // 初始化
int id = 1001;  // 声明 + 初始化
int[] ids;  // 声明
// 静态初始化:数组的初始化和数组元素的赋值操作同时进行。
ids = new int[]{1001,1002,1003,1004}; // 初始化
// 动态初始化:数组的初始化和数组元素的赋值操作分开进行。
String[] = new String[5];

2.调用数组的指定位置的元素:通过角标的方式调用。


  • 数组的角标(或索引)从 0 开始,到数组的长度 -1 结束。
names[0] = "XXX";

3.获取数组的长度:(属性:length)

// names.length
System.out.println(names.length);

4.遍历数组:

for(int i = 0;i < names.length;i++){
  System.out.println(names[i]);
}

5.数组元素的默认初始化值:

数组元素类型 数组元素的默认初始化值
整数类型 0
浮点类型 0.0
char 类型 0 或 '\u0000' ,而非 '0'
Boolean 类型 false
引用数据类型 String null

6.数组的内存解析:


  • 栈内存:栈内存首先是一片内存区域,存储的都是局部变量,凡是定义在方法中的都是局部变量(方法外的是全局变量),for循环内部定义的也是局部变量,是先加载函数才能进行局部变量的定义,所以方法先进栈,然后再定义变量,变量有自己的作用域,一旦离开作用域,变量就会被释放。栈内存的更新速度很快,因为局部变量的生命周期都很短。


  • 堆内存:存储的是数组和对象(其实数组就是对象),凡是new建立的都是在堆中,堆中存放的都是实体(对象),实体用于封装数据,而且是封装多个(实体的多个属性),如果一个数据消失,这个实体也没有消失,还可以用,所以堆是不会随时释放的,但是栈不一样,栈里存放的都是单个变量,变量被释放了,那就没有了。堆里的实体虽然不会被释放,但是会被当成垃圾,Java有垃圾回收机制不定时的收取。


  • 堆和栈的联系:


  • 堆分配了一个地址,把堆的地址赋给arr,arr就通过地址指向了数组。所以arr想操纵数组时,就通过地址,而不是直接把实体都赋给它。这种我们不再叫他基本数据类型,而叫引用数据类型。称为arr引用了堆内存当中的实体。


  • 堆和栈的区别:


  • 栈内存存储的是局部变量而堆内存存储的是实体;
  • 栈内存的更新速度要快于堆内存,因为局部变量的生命周期很短;
  • 栈内存存放的变量生命周期一旦结束就会被释放,而堆内存存放的实体会被垃圾回收机制不定时的回收。


二维数组的使用


  1. Java 语言里提供了支持多维数组的语法。


  1. 如果说可以把一维数组当成几何中的线性图形,那么二维数组就相当于是一个表格。


  1. 对于二维数组的理解,可以看成是一堆一维数组 array1 又作为另一个一维数组 array2 的元素而存在。其实,从数组底层的运行机制来看,其实没有多维数组


  1. 二维数组分为外层数组内层数组
int[] arr = new int[]{1,2,3}; // 一维数组
// 静态初始化
int[][] arr1 = new int[][]{{1,2,3},{4,5},{6,7,8}};
// 动态初始化1
String[][] arr2 = new String[3][2];
// 动态初始化2
String[][] arr3 = new String[3][];
// 以下这种方式也是对的
int[] arr4 = {1,2,3,4,5,6}; // 类型判断

5.遍历二维数组:

// 使用两个 for 循环对二维数组进行遍历。
for(int i = 0;i < arr.length;i++){
  for(int j = 0;j < arr[i].length;j++){
    System.out.println(arr[i][j] + "   ");
  }
  System.out.println();
}

6.数组元素的默认初始值:


  • 外层数组的默认初始值是地址值
  • 内层数组的默认值和一维数组的默认值相同。


Arrays 工具类的使用


  1. java.util.Arrays 类即为操作数组的工具类,包含了用来操作数组(比如排序和搜索)的各种方法。
序号 方法 说明
1 boolean equals(int[] a,int[] b) 判断两个数组是否相等。

2

String toString(int[] a) 输出数组信息。

3

void fill(int[] a,int val) 将指定值填充到数组之中。

4

void sort(int[] a) 对数组进行排序。

5

int binarySearch(int[] a,int key) 对排序后的数组进行二分法检索指定的值。


数组使用中的常见异常


  1. 数组角标越界的异常:ArrayIndexOutOfBoundsExcetion 。
int[] arr = new int[]{1,2,3,4,5};
// 右侧越界
for(int i = 0;i <= arr.length;i++){
  System.out.println(arr[i]);
}
// 左侧越界
System.out.println(arr[-2]);

2.空指针异常:NullPointerException 。

// 情况一:
int[] arr1 = new int[]{1,2,3,4,5};
arr1 = null;
System.out.println(arr1[0]);
// 情况二:
int[][] arr2 = new int[4][];
System.out.println(arr2[0][0]);
// 情况三:
String[] arr3 = new String[]{"AA","BB","CC"};
arr3[0] = null;
System.out.println(arr3[0].toString());


数组中涉及到的常见算法


  1. 数组元素的赋值(杨辉三角、回型数等)。


  1. 求数值型数组中元素的最大值、最小值、平均数、总和等。


  1. 数组的复制、反转、查找(线性查找、二分法查找)。


  • 数组的复制
int[] arr1,arr2;
arr1 = new int[]{2,3,5,7,11,13,17,19};
arr2 = new int[arr1.length];
for(int i = 0;i<arr2.length;i++){
  arr2[i] = arr1[i];
}

数组的反转

// 方法一
for(int i = 0;i < arr.length / 2;i++){
  String temp = arr[i];
  arr[i] = arr[arr.length - i - 1];
  arr[arr.length - i - 1] = temp
}
// 方法二
for(int i = 0,j = arr.length - 1;i < j;i++,j--){
  String temp = arr[i];
  arr[i] = arr[j];
  arr[j] = temp;
}

线性查找

String dest = "BB";
boolean isFlag = true;
for(int i = 0;i < arr.length;i++){
  if(dest.equals(arr[i])){
    System.out.println("找到了指定的元素,位置为:" + i);
    isFlag = false;
    break;
  }
}
if(isFlag){
  Syetem.out.println("很遗憾没有找到。");
}

二分法查找(熟悉)


  • 前提:所要查找的数组必须有序。
int[] arr2 = new int[]{-98,-34,2,34,54,66,79,105,210,333};
int dest1 = -34;
int head = 0;
int end = arr2.length - 1;
boolean isFlag1 = true;
while(head <= end){
  int middle = (head + end) / 2;
  if(dest1 == arr2[middle]){
    System.out.println("找到了指定的元素,位置为" + middle);
    isFlag1 = false;
    break;
  }else if(arr2[middle] > dest1){
    end = middle - 1;
  }else{
    head = middle + 1;
  }
  if(isFlag){
    System.out.println("很遗憾,没有找到!")
  }
}

4.数组元素的排序算法。


  • 衡量排序算法的优劣:


  • 时间复杂度:分析关键字的比较次数和记录的移动次数。
  • 空间复杂度:分析排序算法中需要多少辅助内存。
  • 定性:若两个记录 A 和 B 的关键字值相等,但排序后 A 、B 的先后次序保持不变,则称为这种算法是稳定的。


  • 排序算法分类:内部排序外部排序


  • 内部排序:整个排序过程不需要借助于外部存储器(如磁盘等),所有排序操作都在内存中完成。
  • 外部排序:参与排序的数据非常多,数据量非常大,计算机无法把整个排序过程放在内存中完成,必须借助于外部存储器(如磁盘)。外部排序最常见的是多路归并排序。可以认为外部排序是由多次内部排序组成。


  • 十大内部排序算法:


  • 选择排序
  • 直接选择排序、堆排序
  • 交换排序
  • 冒泡排序、快速排序
  • 插入排序
  • 直接插入排序、折半插入排序、Shell 排序
  • 归并排序
  • 桶式排序
  • 基数排序


冒泡排序


  1. 冒泡排序的原理非常简单,它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。


  1. 排他思想:


  • 比较相邻的元素。如果第一个比第二个大(升序),就交换他们两个。


  • 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。


  • 针对所有的元素重复以上的步骤,除了最后一个。


  • 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较为止。
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];
      arr[j] = arr[j + 1];
      arr[j + 1] = temp;
    }
  }
}


快速排序


  1. 快速排序通常明显比同为 O(nlogn) 的其他算法更快,因此常被采用,而且快速排序采用了分治法的思想,所以在很多笔试面试中经常看到快速排序的影子。可见掌握快速排序的重要性。


  1. 快速排序(Quick Sort)由图灵奖获得者 Tony Hoare 发明,被列为20 世纪十大算法之一,是迄今为止所有内排序算法中速度最快的一种。冒泡排序的升级版,交换排序的一种。快速排序的时间复杂程度为 O(nlog(n)) 。


算法


  1. 算法的五大特征:
输入(Input) 有 0 个或多个输入数据,这些输入必须有清楚的描述和定义。
输出(Output) 至少有 1 个或多个输出结果,不可以没有输出结果。
有穷性(有限性,Finiteness) 算法在有限的步骤之后会自动结束而不会无限循环,并且每一个步骤可以在可接受的时间内完成。
确定性(明确性,Definiteness) 算法中的每一步都有确定的含义,不会出现二义性。
算法中的每一步都有确定的含义,不会出现二义性。 算法的每一步都是清楚可行的,能让用户用纸笔计算而求出结果。
  • 说明:满足确定性的算法也称为:确定性算法。
  • 不要求终止的计算描述,这种描述被称为过程(procedure)。
相关文章
|
2月前
|
XML Java 编译器
Java学习十六—掌握注解:让编程更简单
Java 注解(Annotation)是一种特殊的语法结构,可以在代码中嵌入元数据。它们不直接影响代码的运行,但可以通过工具和框架提供额外的信息,帮助在编译、部署或运行时进行处理。
99 43
Java学习十六—掌握注解:让编程更简单
|
1月前
|
Java 大数据 API
14天Java基础学习——第1天:Java入门和环境搭建
本文介绍了Java的基础知识,包括Java的简介、历史和应用领域。详细讲解了如何安装JDK并配置环境变量,以及如何使用IntelliJ IDEA创建和运行Java项目。通过示例代码“HelloWorld.java”,展示了从编写到运行的全过程。适合初学者快速入门Java编程。
|
2月前
|
存储 SQL 小程序
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
这篇文章详细介绍了Java虚拟机(JVM)的运行时数据区域和JVM指令集,包括程序计数器、虚拟机栈、本地方法栈、直接内存、方法区和堆,以及栈帧的组成部分和执行流程。
43 2
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
|
1月前
|
JavaScript Java 项目管理
Java毕设学习 基于SpringBoot + Vue 的医院管理系统 持续给大家寻找Java毕设学习项目(附源码)
基于SpringBoot + Vue的医院管理系统,涵盖医院、患者、挂号、药物、检查、病床、排班管理和数据分析等功能。开发工具为IDEA和HBuilder X,环境需配置jdk8、Node.js14、MySQL8。文末提供源码下载链接。
|
2月前
|
存储 缓存 算法
Java 数组
【10月更文挑战第19天】Java 数组是一种非常实用的数据结构,它为我们提供了一种简单而有效的方式来存储和管理数据。通过合理地使用数组,我们能够提高程序的运行效率和代码的可读性。更加深入地了解和掌握 Java 数组的特性和应用,为我们的编程之旅增添更多的精彩。
35 4
|
2月前
|
存储 缓存 算法
提高 Java 数组性能的方法
【10月更文挑战第19天】深入探讨了提高 Java 数组性能的多种方法。通过合理运用这些策略,我们可以在处理数组时获得更好的性能表现,提升程序的运行效率。
42 2
|
2月前
|
存储 Java
Java“(array) <X> Not Initialized” (数组未初始化)错误解决
在Java中,遇到“(array) &lt;X&gt; Not Initialized”(数组未初始化)错误时,表示数组变量已被声明但尚未初始化。解决方法是在使用数组之前,通过指定数组的大小和类型来初始化数组,例如:`int[] arr = new int[5];` 或 `String[] strArr = new String[10];`。
95 2
|
2月前
|
小程序 Oracle Java
JVM知识体系学习一:JVM了解基础、java编译后class文件的类结构详解,class分析工具 javap 和 jclasslib 的使用
这篇文章是关于JVM基础知识的介绍,包括JVM的跨平台和跨语言特性、Class文件格式的详细解析,以及如何使用javap和jclasslib工具来分析Class文件。
59 0
JVM知识体系学习一:JVM了解基础、java编译后class文件的类结构详解,class分析工具 javap 和 jclasslib 的使用
|
2月前
|
前端开发 Java 应用服务中间件
Javaweb学习
【10月更文挑战第1天】Javaweb学习
38 2
|
2月前
|
存储 算法 Java
带你学习java的数组军队列
带你学习java的数组军队列
39 0