数组
数组的概念
为什么学数组:能够存储多个变量的容器。
数组是存储相同数据类型的一组连续数据的容器。
数组的本质还是变量,只不过这个变量存储的是地址。
将地址赋值给一个变量必须通过new方式。
如:double[] scores = new double[3];
数组的初始化
1.动态初始化:
数据类型[] 数组名 =new 数据类型[数组中元素的个数];
2.静态初始化:
①数据类型[] 数组名 ={元素1,元素2,元素3… 元素n};
②数据类型[] 数组名=数据类型[] {元素1,元素2,元素3… 元素n};
数组的特点:
1.数组也是一个变量,同样需要先声明再赋值后使用;
2.数据的数据类型可以是八大基本数据类型,也可以是引用数据类型;
3.数组的命名规范同变量一样,但是一般是复数;
4.数组是引用数据类型,没有地址默认赋值为null;
异常情况:
一:ArrayIndexOutOfBoundsException
异常名称: 数组索引超出边界异常
产生原因: 索引不在 [0,数组的长度-1]
解决办法: 检查索引是否在范围之内
二: NullPointerException
异常名称: 空指针异常
产生原因: 对象[数组 类]没有new,就访问了对象的元素、内容
解决办法: 找到相对应错误行的那个引用类型,new之
数组的遍历:
import java.util.Arrays;
/*
* 数组的遍历: 访问数组的每一个元素
*/
public class ArrayDemo {
public static void main(String[] args) {
int[] arr = {11, 22, 33, 44, 55, 66};
double[] arr2 = {2.0,3.0,4.0};
//一:通过方法的for循环遍历输出
printArray(arr);
printArray(arr2);
//二:利用系统JRE提供的Arrays工具快速输出
System.out.println(Arrays.toString(arr));
System.out.println(Arrays.toString(arr2));
}
}
/*
* 功能: 遍历数组
* 返回值类型: void
* 参数列表: int[] arr
* 方法名: printArray
*/
public static void printArray(int[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
public static void printArray(double[] arr) {
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
值传递和引用传递
传递: 实参传递形参的过程
当形参是基本数据类型的时候,传递的是数值本身。
当形参是引用数据类型(数组、类、接口)的时候,传递的是地址。
当存在多个引用指向同一个堆区空间的时候,有任何一个引用修改了堆区的内容,都会影响到所有的引用。
数组的常见思想
一:求和、求最值、倒置
import java.util.Arrays;
import javax.naming.directory.SearchControls;
/*
有一个数列:8, 4, 2, 1, 23, 344, 12
A 循环输出数列的值。arrayToString(略)
B 求数列中所有数值的和。
C 求出最大值。
D 将数组倒置并输出
*/
public class Demo02 {
public static void main(String[] args) {
//定义数组
int[] array = { 8, 4, 2, 1, 23, 344, 12 };
int sum = 0;
int greatestNum = 0;
//A.循环输入数列的值
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
//B.求数列中所有数的和
sum += array[i];
}
System.out.println("数列中所有数之和为: " + sum);
//求最大值
for (int i = 0; (i + 1) < array.length; i++) {
if (array[i + 1] > array[i]) {
greatestNum = array[i + 1];
} else {
greatestNum = array[i];
}
}
System.out.println("数列中最大值为:" + greatestNum);
//倒置方法一:从数组最后一个开始遍历到第一个拼接
System.out.println("倒置结果为: " + reverseArrayToString(array));
//倒置方法二:第一个数和最后一个数交换,第二个数和倒数第二个交换,如此下去。
reverseArray(array);
System.out.println("倒置后为: " + Arrays.toString(array));
}
//将数组倒置输出
/* 1.返回值类型:String
* 2.参数列表:int[] array
* 3.方法名:reverseArrayToString
*/
public static String reverseArrayToString(int[] array) {
String result = "";
//1.循环遍历前先拼接
result += "[";
//2.遍历数组中的每一个元素
for (int i = array.length - 1; i >= 0; i--) {
//3.获取每一个元素
if (i != 0) {
//拼接元素+","
result += array[i] + ",";
} else {
result += array[i];
}
}
//4.遍历结束,拼接“]”
result += "]";
return result;
}
//数组倒置
/* 1.返回值类型:String
* 2.参数列表:int[] array
* 3.方法名:reverseArray
*
*/
public static void reverseArray(int[] array) {
/*
* 1.int[] array = { 8, 4, 2, 1, 23, 344, 12 };
* array[0]与array[6] 对换
* array[1]与array[5] 对换
* array[2]与array[4] 对换
*/
for (int i = 0; i < array.length / 2; i++) {
int temp = 0;
temp = array[i];
array[i] = array[array.length - 1 - i];
array[array.length - 1 - i] = temp;
}
}
}
二:查找数组中是否存在某个数(全局查找,二分法查找)
import java.util.Arrays;
//有一个数列:8, 4, 2, 1, 23, 344, 12
public class Demo02_1 {
public static void main(String[] args) {
int[] array = { 8, 4, 2, 1, 23, 344, 12 };
int index = searchNum(array, 344);
if (index != -1) {
System.out.println("数列中找到该数,位置为:" + index);
} else {
System.out.println("数列中没找到该数");
}
Arrays.sort(array);
System.out.println("排序后:" + Arrays.toString(array));
int index1 = binarySearch(array, 344);
System.out.println("位置为:" + index1);
}
//方法一:全局查找
public static int searchNum(int[] array, int num) {
int index = -1;
for (int i = 0; i < array.length; i++) {
if (array[i] == num) {
index = i;
break;
}
}
return index;
}
//二分法查找
/* 功能,查找一个数是否存在并输出位置
* 返回值类型:int
* 参数列表:int array ,int num, int mid
* 方法名:binarySearch
*/
public static int binarySearch(int[] array, int num) {
// 定义最小索引和最大索引
int min = 0;
int max = array.length - 1;
//计算中间索引
int mid = (min + max) / 2;
while (array[mid] != num) {
//mid>num,往左边找
if (array[mid] > num) {
max = mid - 1;
//mid<num,往右边找
} else if (array[mid] < num) {
min = mid + 1;
}
if (min > max) {
return -1;
}
//重新计算中间索引
mid = (min + max) / 2;
}
return mid;
}
}
数组排序
import java.util.Arrays;
public class Demo02_2 {
public static void main(String[] args) {
int[] array = { 8, 4, 2, 1, 23, 344, 12 };
//冒泡排序
bubbleSort(array);
System.out.println(Arrays.toString(array));
//选择排序
selectSort(array);
System.out.println(Arrays.toString(array));
//方法三:插入排序
insertSort(array);
System.out.println(Arrays.toString(array));
}
//冒泡排序
public static void bubbleSort(int[] array) {
for (int i = 0; i < array.length - 1; i++) {
for (int j = 0; j < array.length - 1 - i; j++) {
if (array[j] > array[j + 1]) {
int temp = 0;
temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
}
//选择排序
public static void selectSort(int[] array) {
for (int i = 0; i < array.length - 1; i++) {
for (int j = i; j < array.length - 1; j++) {
if (array[j] > array[j + 1]) {
int temp = 0;
temp = array[j];
array[j] = array[i + 1];
array[i + 1] = temp;
}
}
}
}
//方法三:插入排序
public static void insertSort(int[] arr) {
for (int i = 1; i < arr.length; i++) {
for (int j = 0; j < i; j++) {
if (arr[j] > arr[i]) {
int temp = 0;
temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
}
}
}
}
Arrays工具类
import java.util.Arrays;
import com.sun.xml.internal.bind.v2.runtime.unmarshaller.XsiNilLoader.Array;
/*
* Arrays工具类
* Java 索引原则: 左闭右开
*
* @param src the source array.
* @param srcPos starting position in the source array.
* @param dest the destination array.
* @param destPos starting position in the destination data.
* @param length the number of array elements to be copied.
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
Java 23种设计模式
创建型模型: 创建对象的方式 ,有一种叫做原型模式
创建对象的方式:
1.new
2.拷贝 System.arrayCopy clone
3.反射
提高思维的题目
增删查改
数组也是一种数据结构【数据的存储方式】
如果需要增加就必须扩容和缩容
*/
public class ArrayDemo08 {
public static void main(String[] args) {
int[] arr = { 35, 11, 33, 44, 72, 13, 55 };
// 打印输出数组
System.out.println("数组中所有元素的个数: " + Arrays.toString(arr));
// 排序
Arrays.sort(arr);
// System.out.println("排序后: " + Arrays.toString(arr));
// 对数组一部分进行排序
// Arrays.sort(arr, 1, 5);
System.out.println("排序后: " + Arrays.toString(arr));
// 二分查找
int index = Arrays.binarySearch(arr, 72);
System.out.println(index);
// 将数组转换成集合[后面讲解泛型和集合的时候讲解] Arrays.asList(arr)
int[] newArr = Arrays.copyOf(arr, arr.length);
System.out.println("旧数组: " + Arrays.toString(arr));
System.out.println("新数组: " + Arrays.toString(newArr));
// copyOf是后面学习集合 ArrayList动态扩容的原理
int[] newArr2 = Arrays.copyOf(arr, arr.length + 1);
System.out.println("新数组2: " + Arrays.toString(newArr2));
int[] newArr3 = Arrays.copyOf(arr, arr.length - 1);
System.out.println("新数组3: " + Arrays.toString(newArr3));
int[] srcArr = {34, 45, 12, 89, 72};
int[] descArr = new int[srcArr.length];
System.out.println("拷贝前:" + Arrays.toString(descArr));
// System.arraycopy(srcArr, 0, descArr, 0, srcArr.length);
// System.out.println("拷贝后:" + Arrays.toString(descArr));
descArr = new int[3];
System.arraycopy(srcArr, 1, descArr, 0, 3);
System.out.println("拷贝后:" + Arrays.toString(descArr));
int[] descArr2 = Arrays.copyOfRange(srcArr, 1, 4);
System.out.println("拷贝后:" + Arrays.toString(descArr2));
System.out.println(Arrays.equals(descArr, descArr2));
Arrays.fill(srcArr, 100);
System.out.println("填充后: " + Arrays.toString(srcArr));
Arrays.fill(srcArr, 1, 4, 200);
System.out.println("填充部分后: " + Arrays.toString(srcArr));
}
}
输出结果如下图
数组的增删查改
import java.util.Arrays;
/*
* 数组的 基本操作 【增删查改】
* 其实数组也是一种数据结构
* 特点:
* 1.有索引
* 2.查询和修改效率高,方便
* 3.增加和删除的效率低
*/
public class ArrayDemo09 {
static int[] srcArr;
public static void main(String[] args) {
srcArr = new int[] {11, 22, 33, 44};
System.out.println(Arrays.toString(srcArr));
add(55);
System.out.println(Arrays.toString(srcArr));
add(66);
System.out.println(Arrays.toString(srcArr));
insert(srcArr.length, 100);
System.out.println(Arrays.toString(srcArr));
remove(6);
System.out.println(Arrays.toString(srcArr));
System.out.println(get(0));
set(1, 200);
System.out.println(Arrays.toString(srcArr));
}
/*
* 动态扩容的原理
* 往数组中动态添加一个元素
* 返回值类型: void
* 参数列表: int num
* 方法名: add
*/
/*public static void add(int num) {
// 利用System.arraycopy方法处理
int[] descArr = new int[srcArr.length + 1];
// 复制数组
System.arraycopy(srcArr, 0, descArr, 0, srcArr.length);
// 将num赋值到目标数组的最后一个位置
descArr[descArr.length - 1] = num;
// 地址传递
srcArr = descArr;
}*/
public static void add(int num) {
int[] descArr = Arrays.copyOf(srcArr, srcArr.length + 1);
descArr[descArr.length - 1] = num;
srcArr = descArr;
}
/*
* 往数组的任意位置插入一个元素
* 返回值类型: void
* 参数列表: int index, int num
* 方法名: insert
*/
public static void insert(int index, int num) {
int[] descArr = new int[srcArr.length + 1];
System.arraycopy(srcArr, 0, descArr, 0, index);
descArr[index] = num;
System.arraycopy(srcArr, index, descArr, index + 1, srcArr.length - index);
srcArr = descArr;
}
/*
* 将数组中的某个索引处的元素删除
* 返回值类型: void
* 参数列表: int index
* 方法名: remove
*/
public static void remove(int index) {
int[] descArr = new int[srcArr.length - 1];
System.arraycopy(srcArr, 0, descArr, 0, index);
System.arraycopy(srcArr, index + 1, descArr, index, descArr.length - index);
srcArr = descArr;
}
public static void delete(int fromIndex, int toIndex) {
int[] newArr = new int[srcArr.length - (toIndex - fromIndex)];
if (fromIndex < 0 || toIndex > srcArr.length) {
System.out.println("不存在的索引值!!!");
return;
} else if (fromIndex == 0) {
System.arraycopy(srcArr, toIndex, newArr, 0, srcArr.length - toIndex);
} else if (fromIndex > 0 && toIndex < srcArr.length) {
System.arraycopy(srcArr, 0, newArr, 0, fromIndex);
System.arraycopy(srcArr, toIndex, newArr, fromIndex, srcArr.length - toIndex);
} else if (toIndex == srcArr.length) {
System.arraycopy(srcArr, 0, newArr, 0, fromIndex);
}
srcArr = newArr;
}
public static int get(int index) {
return srcArr[index];
}
public static void set(int index, int num) {
srcArr[index] = num;
}
}
输入结果如下:
foreach遍历
为什么有了普通for遍历,还需要学习foreach遍历? -> 简化遍历
语句格式:for(元素类型 元素变量 : 遍历对象){使用元素变量};
例子:int[] arr = { 25, 31, 26, 77, 18 };
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}——普通for
for (int i : arr) {
System.out.println(i);
}——foreach
foreach 是集合和数组的专属遍历方式。
可变参数
可变参数: 类型相同,个数不同的一种形参。
格式: 参数类型… 变量名
public static int add(int... args) { //----参数个数可变
// System.out.println(args); // [I@7852e922------地址
int sum = 0;
for (int i : args) {
sum += i;
}
return sum;
}
二维数组
/*
* 二维数组的静态初始化
* 数据类型[][] 数组名 = {{1,2,3}, {4,5}, {6}};
* 数据类型[][] 数组名 = new 数据类型[][]{{1,2,3}, {4,5}, {6}};
*
*数据类型[][] 数组名 = new 数据类型[m][];
*m必不可少,n可省略
*
* 二维数组的遍历
*/
public class TwoArrayDemo {
public static void main(String[] args) {
int[][] arr = { { 1, 2, 3 }, { 4, 5 }, { 6 } };
arr = new int[][] { { 1, 2, 3 }, { 4, 5 }, { 6 } };
// 二维数组的遍历方式
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + "\t");
}
System.out.println();
}
}
}