JAVA中对数组的理解及数组经典例题详解
Posted 来学习的小张
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA中对数组的理解及数组经典例题详解相关的知识,希望对你有一定的参考价值。
前言
数组是一种数据结构,用来存储同一类型值的集合。通过一个整型下标可以访问数组中的每一个值。例如:如果a
是一个整型数组,a[i]
就是数组中下标为i
的整数。在声明数组变量时,需要指出数组类型(数据元素类型紧跟[]
和数组变量的名字。下面声明了整型数组a:int[]a
;这条语句只声明了变量a,并没有将a初始化为一个真正的数组。应该使用new运算符创建数组。int[] a = new int[100];
这条语句创建了一个可以存储100
个整数的数组。数组长度不要求是常量: new int[n]
会创建一个长度为n
的数组。
一、创建数组
数组本质上就是让我们能 “批量” 创建相同类型的变量。在 Java 中, 数组中包含的变量必须是相同类型。
创建数组的三种方式
方式一:
int[] arr = {1,2,3,4,5};
方式二:
int[] arr2 = new int[3];//定义数组长度为3,未初始化
方式三:
int[] arr3 = new int[]{1,2,3,4,5};//定义数组长度为5,初始化
二、 数组的使用
1.获取长度 & 访问元素
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
System.out.println(arr.length);//求数组的长度
System.out.println(arr[3]);//访问数组中的元素
arr[3] = 19;
System.out.println(arr[3]);//改变数组里面的内容
}
注意:
- 使用
arr.length
能够获取到数组的长度,.
这个操作为成员访问操作符,后面在面向对象中会经常用到. - 使用
[ ]
按下标取数组元素. 需要注意, 下标从0
开始计数. - 使用
[ ]
操作既能读取数据, 也能修改数据. - 下标访问操作不能超出有效范围
[0, length - 1]
, 如果超出有效范围, 会出现下标越界异常.
2.遍历数组
“遍历” 是指将数组中的所有元素都访问一遍, 不重不漏. 通常需要搭配循环语句.
2.1使用for循环
for
循环可以拿到下标。
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
for (int i = 0; i < arr.length; i++) { //for循环可以拿到下标
System.out.print(arr[i] + " "); //打印数组中的每个元素
}
2.2使用for each循环
语法格式:
for (int element : a)
System.out.println(element);
打印数组a的每一个元素,一个元素占一行。这个循环应该读作“循环a中的每一个元素”( for each element in a)。Java语言的设计者认为应该使用诸如foreach、in
这样的关键字,但这种循环语句并不是最初就包含在Java语言中的,而是后来添加进去的,并且没有人打算废除已经包含同名(例如System.in)方法或变量的旧代码。
for each
循环又称增强for
循环,可以打印数组中的每个元素 但是拿不到数组下标。
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
for (int x:arr) { //
System.out.print(x + " ");
}
2.3Arrays类的toString 方法
调用Arrays.toString(a)
,返回一个包含数组元素的字符串,这些元素被放置在括号内,并用逗号分隔,例如:“[2,3,5,7,11,13]”
。要想打印数组,可以调用:System.out.println(Arrays.toString(a));
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
//借助java的操作数组的工具类 Arrays.toString:将参数的数组以字符串的形式进行输出
String ret = Arrays.toString(arr);
System.out.println(ret);
}
三、数组作为方法的参数
3.1打印数组的内容
public static void printf(int[] a) {
for (int i = 0; i < a.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
printf(arr);//按引用传递(按值传递)
}
在这个代码中int[] a
是函数的形参, int[] arr
是函数实参.
3.2理解引用类型
public static void func1(int[] arr){
arr = new int[]{10,12,24,52,61};
}
public static void func2(int[] arr){
arr[0] = 521;
}
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
System.out.print(Arrays.toString(arr));// 1,2,3,4,5
System.out.println();
// func1(arr);//1,2,3,4,5 虽然传的是地址,但是传过去之后,形参只是改变了自己的指向而已。
func2(arr); //521,2,3,4,5
//在函数内部修改数组内容, 函数外部也发生改变.此时数组名 arr 是一个"引用".当传参的时候, 是按照引用传参.
System.out.print(Arrays.toString(arr));
}
所谓的 “引用” 本质上只是存了一个地址. Java 将数组设定成引用类型, 这样的话后续进行数组参数传参, 其实只是将数组的地址传入到函数形参中. 这样可以避免对整个数组的拷贝(数组可能比较长, 那么拷贝开销就会很大).
3.3认识null
public static void main4(String[] args) {
int[] arr = {1,2,3,4,5};
int[] arr2 = null;//代表这个引用不指向任何对象
System.out.println(arr2);//空指针异常
}
null
的作用类似于 C 语言中的 NULL
(空指针), 都是表示一个无效的内存位置。因此不能对这个内存进行任何读写操作。 一旦尝试读写, 就会抛出:NullPointerException
.
注意: Java 中并没有约定 null
和 0
号地址的内存有任何关联。
3.4 初识 JVM 内存区域划分
JVM 的内存被划分成了几个区域:
程序计数器 (PC Register)
: 只是一个很小的空间, 保存下一条执行的指令的地址.虚拟机栈(JVM Stack)
: 重点是存储局部变量表(当然也有其他信息). 我们刚才创建的int[] arr
这样的存储地址的引用就是在这里保存.本地方法栈(Native Method Stack)
: 本地方法栈与虚拟机栈的作用类似. 只不过保存的内容是Native
方法的局部变量. 在有些版本的JVM
实现中(例如HotSpot
), 本地方法栈和虚拟机栈是一起的.堆(Heap)
:JVM
所管理的最大内存区域. 使用new
创建的对象都是在堆上保存 (例如前面的new int[]{1, 2,3}
).方法区(Method Area)
: 用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据. 方法编译出的的字节码就是保存在这个区域.运行时常量池(Runtime Constant Pool)
: 是方法区的一部分, 存放字面量(字符串常量)与符号引用. (注意 从JDK1.7
开始, 运行时常量池在堆上).
Native 方法:
JVM 是一个基于 C++ 实现的程序. 在 Java 程序执行过程中, 本质上也需要调用 C++ 提供的一些函数进行和操作系统底层进行一些交互. 因此在 Java 开发中也会调用到一些 C++ 实现的函数.这里的 Native 方法就是指这些 C++ 实现的, 再由 Java 来调用的函数.
四、数组作为方法的返回值
写一个方法, 将数组中的每个元素都 * 2
/**
* 在原来的数组上扩大2倍
* @param arr
*/
public static void func(int[] arr){
for (int i = 0; i < arr.length; i++) {
arr[i] = 2 * arr[i];
System.out.print(arr + " ");
}
}
/**
* 不改变原数组,将数组扩大2倍,创建一个新的数组用来接收扩大2倍之后的值
* @param arr
* @return
*/
public static int[] func3(int[] arr){
int[] ret = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
ret[i] = 2 * arr[i];
}
return ret;
}
public static void main9(String[] args) {
int[] arr = {1,2,3,4,5};
func(arr);
int[] ret2 = func3(arr);
System.out.print(Arrays.toString(ret2));
}
五、数组练习
5.1 数组转字符串
/**
* 写一个方法将数组转字符串
* @param arr
* @return
*/
public static String myToString(int[] arr){
if(arr == null){
return null;
}
String ret = "[";
for (int i = 0; i < arr.length; i++) {
ret += arr[i];
if(i != arr.length - 1){
ret += ",";
}
}
ret += "]";
return ret;
}
public static void main10(String[] args) {
int[] arr = {1,2,3,4,5};
System.out.println(myToString(arr));
}
利用java所提供的Arrays包,也可以实现数组转字符串操作:
import java.util.Arrays
int[] arr = {1,2,3,4,5,6};
String newArr = Arrays.toString(arr);
System.out.println(newArr);//[1, 2, 3, 4, 5, 6]
5.2 找数组中的最大元素
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6};
System.out.println(maxNum(arr));
}
public static int maxNum(int[] arr){
if(arr == null){
return -1;
}
if(arr.length == 0){
return -1;
}
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
if(max < arr[i]){
max = arr[i];
}
}
return max;
}
5.3 求数组中元素的平均值
public static double avg(int[] arr){
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
return (double) sum/(double) arr.length;
}
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6};
System.out.println(avg(arr));
}
5.4 查找数组中指定元素(顺序查找)
给定一个数组, 再给定一个元素, 找出该元素在数组中的位置,返回数组的下标。
public static int findNum(int[] arr,int key){
for (int i = 0; i < arr.length; i++) {
if(arr[i] == key){
return i;
}
}
return -1;
}
public static void main11(String[] args) {
int[] arr = {4,5,2,8,44,2,0};
System.out.println(findNum(arr,8));
}
5.5 查找数组中指定元素(二分查找)
以升序数组为例, 二分查找的思路是先取中间位置的元素, 看要找的值比中间元素大还是小. 如果小, 就去左边找; 否则就去右边找。
public static int binarySearch(int[] arr,int k){
int l = 0;
int r = arr.length - 1;
while (l < r){
int mid = (l + r)/2;
if(arr[mid] > k){
r = mid - 1;
}
else if(arr[mid] < k){
l = mid + 1;
}
else
return mid;
}
return -1;
}
public static void main11(String[] args) {
int[] arr = {1,2,3,4,5,78,99};
System.out.println(binarySearch(arr,78));
System.out.println(Arrays.binarySearch(arr, 78)); //自带的二分查找
}
5.6检查数组的有序性
public static void main(String[] args) {
int[] arr = {1,2,3,10,5,6};
System.out.println(isSorted(arr));
}
public static boolean isSorted(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
if (arr[i] > arr[i + 1]) {
return false;
}
}
return true;
}
5.7数组排序(冒泡排序)
public static void main(String[] args) {
int[] arr = {3,5,6,1,2,9,0,8,4,7};
以上是关于JAVA中对数组的理解及数组经典例题详解的主要内容,如果未能解决你的问题,请参考以下文章