数组和引用总结
文章目录
- 数组和引用总结
- 一、数组的基本用法
- 1.什么是数组
- 2.一维数组的创建
- 3.二维数组的创建
- 4.数组的使用
- 4.1获取长度 & 访问元素
- 4.2遍历数组
- 4.3使用 for-each 遍历数组
- 5.数组的相关练习
- 5.1数组转字符串
- 5.2数组拷贝
- 5.3找数组中的最大元素
- 5.4求数组中元素的平均值
- 5.5查找数组中指定元素(顺序查找)
- 5.6查找数组中指定元素(二分查找)
- 5.7检查数组的有序性
- 5.8数组排序(冒泡排序)
- 5.9数组逆序
- 5.10数组数字排列
- 二、引用
- 1.什么是引用
- 2.引用的规则
一、数组的基本用法
1.什么是数组
数组本质上就是让我们能“批量”创建相同类型的变量。
注意:在Java中,数组中包含的变量必须是相同类型。
2.一维数组的创建
基本语法:
// 动态初始化
数据类型[] 数组名称 = new 数据类型 [] { 初始化数据 };
int[] arr = new int[]{1, 2, 3};
// 静态初始化
数据类型[] 数组名称 = { 初始化数据 };
int[] arr = {1, 2, 3};
注意: 静态初始化的时候, 数组元素个数和初始化数据的格式是一致的.
3.二维数组的创建
基本语法:
数据类型[][] 数组名称 = new 数据类型 [行数][列数] { 初始化数据 };
int[][] arr = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
for (int row = 0; row < arr.length; row++) {
for (int col = 0; col < arr[row].length; col++) {
System.out.printf("%d\t", arr[row][col]);
}
System.out.println("");
}
// 执行结果
1 2 3 4
5 6 7 8
9 10 11 12
4.数组的使用
4.1获取长度 & 访问元素
int[] arr = {1, 2, 3};
// 获取数组长度
System.out.println("length: " + arr.length); // 执行结果: 3
// 访问数组中的元素
System.out.println(arr[1]); // 执行结果: 2
System.out.println(arr[0]); // 执行结果: 1
arr[2] = 100;
System.out.println(arr[2]); // 执行结果: 100
注意事项
- 使用 arr.length 能够获取到数组的长度. . 这个操作为成员访问操作符. 后面在面向对象中会经常用到.
- 使用[ ] 按下标取数组元素. 需要注意, 下标从 0 开始计数
- 使用 [ ] 操作既能读取数据, 也能修改数据.
- 下标访问操作不能超出有效范围 [0, length - 1] , 如果超出有效范围, 会出现下标越界异常
C中数组下标越界和Java中的区别
C:未定义行为
Java:行为是确定的
4.2遍历数组
所谓 “遍历” 是指将数组中的所有元素都访问一遍, 不重不漏. 通常需要搭配循环语句.
int[] arr = {1, 2, 3};
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
// 执行结果
1
2
3
4.3使用 for-each 遍历数组
int[] arr = {1, 2, 3};
for (int x : arr) {
System.out.println(x);
}
// 执行结果
1
2
3
5.数组的相关练习
5.1数组转字符串
Java 中提供了 java.util.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]
自己实现:
import java.util.Arrays;
public class Test1 {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6};
String result = arrToString(arr);
System.out.println(result);
}
public static String arrToString(int[] arr) {
String result = "[";
//判定一下当前元素是否为最后一个,如果是,就不加逗号
for (int i = 0;i <= arr.length - 1;i++) {
result += arr[i];
if (i != arr.length - 1) {
result += ", ";
} else {
result += "";
}
}
result += "]";
return result;
}
}
5.2数组拷贝
import java.util.Arrays;
public class Test2 {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6};
//数组拷贝
// int[] arr2 = copyArray(arr);
int[] arr2 = Arrays.copyOf(arr,arr.length);
arr[0] = 10;
System.out.println(arr2[0]);
}
public static int[] copyArray(int[] arr) {
//首要操作,创建一个新的数组;
int[] result = new int[arr.length];
for (int i = 0;i <= arr.length - 1;i++) {
result[i] = arr[i];
}
return result;
}
}
5.3找数组中的最大元素
public class Test3 {
public static void main(String[] args) {
//寻找数组中的最大元素
int[] arr = {5, 7, 3, 8, 9, 1, 10};
int result = max(arr);
System.out.println(result);
}
//打擂台的方法,谁大谁留在台上,否则就下去
public static int max(int[] arr) {
int result = arr[0];
for (int i = 0;i <= arr.length-1;i++) {
if (arr[i] > result) {
result = arr[i];
}
}
return result;
}
}
5.4求数组中元素的平均值
public class Test4 {
public static void main(String[] args) {
//求数组平均值
int[] arr = {9,3,4,5,1,8,6,10};
double result = avg(arr);
System.out.println(result);
}
public static double avg(int[] arr) {
int sum = 0;
for (int x : arr) {
sum += x;
}
return (double)sum / arr.length;
}
}
5.5查找数组中指定元素(顺序查找)
代码在5.6二分查找中,未拆开
5.6查找数组中指定元素(二分查找)
public class Test5 {
public static void main(String[] args) {
//“查找”有两种风格
//1.给定位置,查找值
//2.给定值,查找位置(数组下标)
//查找数组元素的位置
//int[] arr = {8,5,6,9,3,7,1};
//int pos = search(arr,3);
//System.out.println(pos);
//二分查找
//二分查找必须应用于有序数组
int[] arr = {2,3,4,5,7,13};
int pos = binarySearch(arr,5);
System.out.println(pos);
}
//直接去整个数组的中间元素,用中间元素和待查找元素进行对比
public static int binarySearch(int[] arr, int toSearch) {
int left = 0;
int right = arr.length - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (toSearch < arr[mid]) {
//左侧区间查找,淘汰掉右侧区间
right = mid - 1;
} else if (toSearch > arr[mid]) {
//右侧区间查找,淘汰掉左侧区间
left = mid + 1;
} else {
//相等
return mid;
}
}
return -1;
}
public static int search(int[] arr, int toSearch) {
for (int i = 0;i <= arr.length - 1;i++) {
if (arr[i] == toSearch) {
return i;
}
}
//返回-1表示没找到
return -1;
}
}
5.7检查数组的有序性
public class Test6 {
public static void main(String[] args) {
//验证数组的有序性
int[] arr = {2,3,4,5,6,7};
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.8数组排序(冒泡排序)
import java.util.Arrays;
public class Test7 {
public static void main(String[] args) {
//冒泡排序(升序来算)
//一趟比较下来,就可以将最大的元素放到最后,或将最小的元素放到最前
int[] arr = {9,5,2,7,3,6};
bubbleSort(arr);
//Java标准库中提供了一个现成的排序算法Array.sort()
//Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
}
//这个代码,可以直接在方法内部修改数组的内容
//也可以创建新数组,以返回值的方式返回新数组
//数组这样的类型,在方法内部做出修改,也能影响到实参的内容
public static void bubbleSort(int[] arr) {
//如果从前往后遍历进行比较交换,就把最大元素放到最后
//如果从后往前遍历进行比较交换,就把最小元素放到最前
//[0,bound)已排序区间
//[bound,length)待排序区间
for (int bound = 0;bound < arr.length;bound++) {
for (int cur = 0;cur < arr.length - bound - 1;cur++) {
if (arr[cur] > arr[cur + 1]) {
int tmp = arr[cur];
arr[cur] = arr[cur + 1];
arr[cur + 1] = tmp;
}
}
}
}
}
5.9数组逆序
import java.util.Arrays;
public class Test8 {
public static void main(String[] args) {
int[] arr = {9,5,2,7,3,6,10};
//数组逆序
reverse(arr);
System.out.println(Arrays.toString(arr));
}
public static void reverse(int[] arr) {
int left = 0;
int right = arr.length - 1;
while (left < right) {
int tmp = arr[right];
arr[right] = arr[left];
arr[left] = tmp;
left++;
right--;
}
}
}
5.10数组数字排列
import java.util.Arrays;
public class Test9 {
public static void main(String[] args) {
int[] arr = {9,4,2,7,3,6,10};
//对数组进行重新排列
//排列之后偶数在前,奇数在后
//从前往后排列,找到一个奇数
//再从后往前,找到一个偶数
//交换这两元素,直到两个下标重合
transform(arr);
System.out.println(Arrays.toString(arr));
}
public static void transform(int[] arr) {
int left = 0;
int right = arr.length - 1;
while (left < right) {
while (left < right && arr[left] % 2 == 0) {
left++;
}
while (left < right && arr[right] % 2 != 0) {
right--;
}
if (left < right) {
int tmp = arr[right];
arr[right] = arr[left];
arr[left] = tmp;
}
}
}
}
二、引用
1.什么是引用
String s = "Hello World"; // 这里的 s 的类型是 String 类型的引用;该引用指向了一个String 类型的对象。
int[] a = { 1, 2, 3, 4, 5 }; // 这里的 a 的类型是 int[] 类型的引用;该引用指向了一个元素类型是 int 的数组类型对象。
引用其实通俗的讲也就是别名。
注意:
1.一个对象可以拥有多个别名;
2.一个引用只能对应到一个对象
2.引用的规则
注1:
(1)只有引用指向对象;没有对象指向引用;也没有引用指向引用;更没有对象指向对象;
(2)对象可以被多个引用指向;
(3)操作引用,其实操作的是引用指向的对象;
(4)一个对象至少得有一个引用指向,如果一个引用都没有了,说明这个对象无法在代码中被使用了,此时这个对象就会被垃圾回收器当成垃圾从而回收并释放内存空间;
注2:
“=”赋值操作的是引用的指向,对对象本身并无影响;
注3:
(1)引用是一种数据类型,用来指向对象;
(2)对引用进行大部分操作实际上都是操作的该引用指向的对象;
(3)当多个引用指向同一个对象时,通过哪个引用修改了对象,其他引用都可以看到对象;
(4)当一个引用不指向对象时,要求访问其指向的对象,就会遇到NullPointerException;
注3:
(1)引用和对象都是一种数据组织形式,所以都是存放在内存中的;
(2)对象一定保存在堆上,但引用则不一定;
(3)引用是一类只能用来指向对象的数据类型;
(4)引用可以指向对象,也可以不指向对象;
(5)解引用操作就是通过引用找到对象;
(6)Java中无法直接接触到对象,都是通过引用接触到对象;
(7)对一个空的引用做到解引用操作,会出现NullPointerException;
(8)JVM为了便于管理,将其管理的内存人为划分为6个区域:
①PC区;②虚拟机栈;③本地方法栈;④堆;⑤方法区;⑥运行时常量池;
注4:
(1)空指针表示指针中存的地址对应的内存是一个非法内存;
(2)空引用表示该引用里面的所持有的地址对应的对象,是一个非法的对象;
注5:
(1)null和0号地址,不一定直接相关;
(2)null存的地址,不一定是0;
(3)不能针对null这样的引用进行“解引用”,指的就是不能够访问这个对象的成员;
注6:
(1)Build:编译错误; 编译一次
(2)Exception:运行错误; 运行可能是N次
注7:
(1)使用null可以表示一个非法值;
(2)null不能赋值给内置类型,只能赋值给引用类型
eg:不能赋值为int,可以赋值给Integer。