欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JavaSE 数组

程序员文章站 2022-07-04 14:04:25
...

一、数组的定义

  • 数组是数据的集合,实际上是一个容器,可以同时容纳多个元素
  • 在Java中规定,数组一旦创建,数组长度不可变
  • 所有的数组对象都有length属性(Java自带属性),用来获取数组中元素的个数
System.out.println(arr.length);    //数组用的是length属性,后面不加(),String字符串用的是length方法,后面加()
  • 数组实际上是一种简单的数据结构

二、数组的类型

  • Java语言中的数组是一种引用数据类型,不属于基本数据类型,数组的父类是Object,但是数组当中可以存储基本数据类型或引用数据类型的数据,且Java中要求数组中的元素类型统一,比如int类型数组只能存储int类型,Person类型只能存储Person类型

三、数组在内存中的存储

  • 数组中不能直接存储Java对象,实际上存储的是对象的内存地址,而对象是存储在堆内存当中,即数组中存储内存地址,这个内存地址指向堆内存中的对象
  • 数组在内存存储的时候,数组中元素的内存地址是连续的,且每个元素占用的空间大小相同
  • 数组中首元素的内存地址作为整个数组对象的地址
  • 数组中每个元素都有下标,下标从0开始,以1递增,最后一个元素的下标是length-1,对数组中元素进行“存取”的时候,都需要通过下标来进行

四、数组的优点和缺点

  • 优点
    查询/检索某个下标对应的元素效率极高
    原因:
    1. 每一个元素的内存地址在空间存储上是连续的
    2. 每一个元素数据类型相同,所以占用空间大小一样
    3. 已知元素内存地址、元素占用空间的大小、下标,可以方便的通过一个数学表达式计算出某个下标上元素的内存地址(偏移量),即直接通过内存地址定位元素
  • 缺点
    1. 随机增删效率较低(最后一个元素除外)
    原因:
    为了保证数组中每个数组元素的内存地址连续,增删时会涉及到某些元素向前或向后位移的操作
    2. 数组无法存储大数据量
    原因:
    很难在内存空间上找到一块特别大的连续的内存空间

五、数组的分类

一维
二维(元素为一维数组的数组)
多维(数组元素是数组的数组)

六、数组的初始化

  • 静态初始化(创建数组时,已确定数组中存储哪些具体的元素,采用静态方式)
    一维数组的静态初始化
int[] arr = {1,2,3,4};
Object[] objs = {new Object(),new Object(),new Object(),new Object()};
......

二维数组的静态初始化

int[][] arr = {
					{1,2,3,4},
					{5,6},
					{1,8,9},
					{-1,-5}
				}
Object[] objs = {
						{new Object(),new Object()},
                        {new Object()},
                        {new Object()}
				};
......
  • 动态初始化(创建数组时,不确定将来数组中存储哪些元素,采用动态方式,预先分配内存空间)
    一维数组的动态初始化
int[] arr = new int[5];    //5表示数组的元素个数(初始化5个长度的int连续数组,每个元素默认值为0)
String[] arr = new String[6];    //初始化6个长度的String类型数组,每个元素默认值为null

二维数组的动态初始化

int[][] arr = new int[3][4];
int[][] arr = new int[3][];
int[][] arr = new int[][4];    //错误
Object[][] arr = new Object[3][4];
Object[][] arr = new Object[3][];
Person[][] arr = new Person[3][4];    //Person类型数组,里面可以存储Person类型对象以及Person类型的子类型
......

七、数组的遍历

  • 一维数组的遍历
for(int i = 0;i < arr.length;i++){
		System.out.println(arr[i]);
}
  • 二维数组的遍历
for(int i = 0;i < arr.length;i++){
		for(int j = 0;j < arr[i].length;j++){
			System.out.prnintln(arr[i][j]);
		}
		System.out.prnintln();
}

八、输出整个数组

使用java.util.Arrays工具类
工具类中的方法都是静态方法,直接使用类名调用即可

  • Arrays.toString();
    Arrays.toString(); 中不能传值,应该传变量名(任意数据类型)
import java.util.Arrays;
public class Test {
	public static void main(String[] args) {
		int[] arr = { 1, 2, 3, 4 };
		System.out.println(Arrays.toString(arr));    //输出[1, 2, 3, 4]
	}
}
  • 若是直接System.out.println(arr)会是什么情况?
public class Test {
	public static void main(String[] args) {
		int[] arr = { 1, 2, 3, 4 };
		System.out.println(arr);
	}
}

JavaSE 数组
[aaa@qq.com
[I:表示数组对象,@表示字符,后面使用8位16进制数保存内存的地址

  • API:
public static String toString(int[] a) {
    if (a == null)
        return "null";    // 不是值,在内存中没有地址,是一个字符串“null”
    int iMax = a.length - 1;    //最后一个元素的下标索引
    if (iMax == -1)
        return "[]";    // 创建了一个数组对象,并且在内存当中有地址,只不过值为空(空数组元素)

    StringBuilder b = new StringBuilder();    // StringBuilder可变长字符串
    b.append('[');
    for (int i = 0; ; i++) {    // 无条件,拿出所有元素
        b.append(a[i]);
        if (i == iMax)
            return b.append(']').toString();
        b.append(", ");
    }
}
  • 特殊:char类型
import java.util.Arrays;
public class Test {
	public static void main(String[] args) {
		char[] arr = new char[10];
		System.out.println(arr);
		System.out.println(Arrays.toString(arr));
	}
}

System.out.println(arr); 输出:不为空,但不显示
System.out.println(Arrays.toString(arr)); 输出:不为空,值为 \u0000,用“,”隔开
JavaSE 数组
利用循环赋值继而显示值

import java.util.Arrays;
public class Test {
	public static void main(String[] args) {
		char[] arr = new char[10];
		for (int i = 0; i < arr.length; i++) {
			arr[i] = (char) ('0' + i);
		}
		System.out.println(arr);
		System.out.println(Arrays.toString(arr));
	}
}

JavaSE 数组

九、数组的赋值与复制

  • for循环实现数组的赋值
import java.util.Arrays;
public class Test {
	public static void main(String[] args) {
		int[] arr1 = { 1, 2, 3, 4 };
		int[] arr2 = new int[arr1.length];
		for (int i = 0; i < arr1.length; i++) {
			// 将arr1中的每个元素赋值给arr2中的每个元素
			arr2[i] = arr1[i];
		}
		System.out.println(Arrays.toString(arr1));
		System.out.println(Arrays.toString(arr2));
	}
}

JavaSE 数组

  • System.arraycopy(src, srcPos, dest, destPos, length); 实现数组的复制
    C++实现的复制(拷贝), native(调用C++)
    src, srcPos, dest, destPos, length:
    原数组、位置(原从哪拷贝)、目标数组、位置(目标从哪拷贝)、长度(拷贝多长)
import java.util.Arrays;
public class Test {
	public static void main(String[] args) {
		int[] arr1 = { 5, 6, 7, 8 };
		int[] arr2 = new int[arr1.length];
		System.arraycopy(arr1, 0, arr2, 0, arr1.length);    //全复制(拷贝)
		System.out.println(Arrays.toString(arr1));
		System.out.println(Arrays.toString(arr2));
	}
}

JavaSE 数组

十、数组的扩容/缩容

  • Arrays.copyOf(original, newLength); 实现数组的扩容/缩容
    original, newLength:
    要拷贝的数组,新长度

    API:
public static int[] copyOf(int[] original, int newLength) {
        int[] copy = new int[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;        
}

测试:

import java.util.Arrays;
public class Test {
	public static void main(String[] args) {
		int[] arr1 = { 5, 6, 7, 8 };
		int[] arr2 = Arrays.copyOf(arr1, 5);
		arr2[arr2.length - 1] = 34;
		System.out.println(Arrays.toString(arr1));
		System.out.println(Arrays.toString(arr2));
	}
}

JavaSE 数组

十一、数组的排序

  • Arrays.sort(); 默认升序,无返回值
    测试:
import java.util.Arrays;
public class Test {
	public static void main(String[] args) {
		int[] arr1 = { 1, 9, -6, 23, 34 };
		Arrays.sort(arr1);
		System.out.println(Arrays.toString(arr1));
	}
}

JavaSE 数组

补充一:选择排序

  • 将数组中每个元素与第一个元素比较,如果这个元素小于第一个元素,则交换这两个元素
package com.lzj.demo;

import java.util.Arrays;

/**
 * 选择排序 将数组中每个元素与第一个元素比较,如果这个元素小于第一个元素,则交换这两个元素
 * 
 * @author lzj
 * @version 1.0
 */
public class SelectionSort {
	public static void main(String[] args) {
		int[] arr = { 51, 2, 34, -12, 4, 12 };
		arr = sort(arr);
		System.out.println(Arrays.toString(arr));
	}

	/**
	 * 选择排序
	 * 
	 * @param arr 待排序数组
	 * @return 排好序数组
	 */
	public static int[] sort(int[] arr) {
		for (int i = 0; i < arr.length - 1; i++) {
			for (int j = i + 1; j < arr.length; j++) {
				if (arr[i] > arr[j]) {
					int temp = arr[i];
					arr[i] = arr[j];
					arr[j] = temp;
				}
			}
		}
		return arr;
	}
}

JavaSE 数组

补充二:冒泡排序

  • 比较相邻的元素,将小的放到前面,
package com.lzj.demo;

import java.util.Arrays;

/**
 * 冒泡排序 比较相邻的元素,将小的放到前面
 * 
 * @author lzj
 * @version 1.0
 */
public class BubbleSort {
	public static void main(String[] args) {
		int[] arr = { 51, 2, 34, -12, 4, 12 };
		arr = sort(arr);
		System.out.println(Arrays.toString(arr));
	}

	/**
	 * 冒泡排序
	 * 
	 * @param arr 待排序数组
	 * @return 排好序数组
	 */
	public static int[] sort(int[] arr) {
		for (int i = 0; i < arr.length - 1; i++) {
			for (int j = 0; j < arr.length - i - 1; j++) {
				if (arr[j] > arr[j + 1]) {
					int temp = arr[j];
					arr[j] = arr[j + 1];
					arr[j + 1] = temp;
				}
			}
		}
		return arr;
	}
}

JavaSE 数组

补充三:二分查找

  • 前提:带查找数组是已排好序的
package com.lzj.demo;

/**
 * 二分查找
 *
 * @author lzj
 * @version 1.0
 */
public class BinarySearch {
	public static void main(String[] args) {
		// int[] arr = { 1, 345, 56, 8, 6 };
		int[] arr = { 1, 5, 6, 8 };
		// int[] arr = { 9, -2, 5, 6 };
		int index = sort(arr, 6);
		System.out.println(index == -1 ? "该元素不存在!" : "该元素下标" + index);
	}

	/**
	 * 
	 * @param arr  带查找已排序数组
	 * @param dest 目标元素
	 * @return -1表示该元素不存在,其他表示返回该元素的下标
	 */
	public static int sort(int[] arr, int dest) {
		// 开始下标
		int begin = 0;
		// 结束下标
		int end = arr.length - 1;
		// 开始元素的下标只要在结束元素下标的左边,就有机会循环
		while (begin <= end) {
			// 中间下标
			int mid = (begin + end) / 2;
			if (arr[mid] == dest) {
				// 中间值与目标相等
				return mid;
			} else if (arr[mid] < dest) {
				// 目标在中间的右边
				begin = mid + 1;
			} else {
				// 目标在中间的左边
				end = mid - 1;
			}
		}
		return -1;
	}
}

JavaSE 数组