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)。
相关文章
|
1月前
|
存储 Java 索引
Java快速入门之数组、方法
### Java快速入门之数组与方法简介 #### 一、数组 数组是一种容器,用于存储同种数据类型的多个值。定义数组时需指定数据类型,如`int[]`只能存储整数。数组的初始化分为静态和动态两种: - **静态初始化**:直接指定元素,系统自动计算长度,如`int[] arr = {1, 2, 3};` - **动态初始化**:手动指定长度,系统给定默认值,如`int[] arr = new int[3];` 数组访问通过索引完成,索引从0开始,最大索引为`数组.length - 1`。遍历数组常用`for`循环。常见操作包括求和、找最值、统计特定条件元素等。
|
1月前
|
存储 Java 索引
Java基础(六):数组
Java基础(六):数组
30 10
Java基础(六):数组
|
26天前
|
Java 调度 开发者
Java线程池ExecutorService学习和使用
通过学习和使用Java中的 `ExecutorService`,可以显著提升并发编程的效率和代码的可维护性。合理配置线程池参数,结合实际应用场景,可以实现高效、可靠的并发处理。希望本文提供的示例和思路能够帮助开发者深入理解并应用 `ExecutorService`,实现更高效的并发程序。
34 10
|
29天前
|
存储 Java C++
Java数组:静态初始化与动态初始化详解
本文介绍了Java中数组的定义、特点及初始化方式。
62 12
|
29天前
|
Java 数据库连接 数据库
【潜意识Java】深度分析黑马项目《苍穹外卖》在Java学习中的重要性
《苍穹外卖》项目对Java学习至关重要。它涵盖了用户管理、商品查询、订单处理等模块,涉及Spring Boot、MyBatis、Redis等技术栈。
80 4
|
29天前
|
前端开发 Java 数据库连接
【潜意识Java】深度解读JavaWeb开发在Java学习中的重要性
深度解读JavaWeb开发在Java学习中的重要性
30 4
|
29天前
|
存储 移动开发 算法
【潜意识Java】Java基础教程:从零开始的学习之旅
本文介绍了 Java 编程语言的基础知识,涵盖从简介、程序结构到面向对象编程的核心概念。首先,Java 是一种高级、跨平台的面向对象语言,支持“一次编写,到处运行”。接着,文章详细讲解了 Java 程序的基本结构,包括包声明、导入语句、类声明和 main 方法。随后,深入探讨了基础语法,如数据类型、变量、控制结构、方法和数组。此外,还介绍了面向对象编程的关键概念,例如类与对象、继承和多态。最后,针对常见的编程错误提供了调试技巧,并总结了学习 Java 的重要性和方法。适合初学者逐步掌握 Java 编程。
52 1
|
4月前
|
XML Java 编译器
Java学习十六—掌握注解:让编程更简单
Java 注解(Annotation)是一种特殊的语法结构,可以在代码中嵌入元数据。它们不直接影响代码的运行,但可以通过工具和框架提供额外的信息,帮助在编译、部署或运行时进行处理。
124 43
Java学习十六—掌握注解:让编程更简单
|
3月前
|
Java 大数据 API
14天Java基础学习——第1天:Java入门和环境搭建
本文介绍了Java的基础知识,包括Java的简介、历史和应用领域。详细讲解了如何安装JDK并配置环境变量,以及如何使用IntelliJ IDEA创建和运行Java项目。通过示例代码“HelloWorld.java”,展示了从编写到运行的全过程。适合初学者快速入门Java编程。
|
3月前
|
JavaScript Java 项目管理
Java毕设学习 基于SpringBoot + Vue 的医院管理系统 持续给大家寻找Java毕设学习项目(附源码)
基于SpringBoot + Vue的医院管理系统,涵盖医院、患者、挂号、药物、检查、病床、排班管理和数据分析等功能。开发工具为IDEA和HBuilder X,环境需配置jdk8、Node.js14、MySQL8。文末提供源码下载链接。