目录
1.3数组的使用(返回数组长度/获取数组中的元素/遍历数组)
1.4数组拷贝(浅拷贝/深拷贝)
1.5数组的应用(顺序查找/二分查找/检查数组的有序性/数组逆序/数组数字排列/二维数组)
1数组
一组相同数据类型的集合,长度固定
1.1数组的创建-动态数组
//动态初始化
数组类型[]数组名称=new 数据类型[长度];
int[]data=new int[3];//数组声明并初始化:
开辟数组空间后,所有数组内容为其数据类型的默认值 访问数组元素使用数组名称框[索引下标],索引从0开始 当访问下标超出数组长度时,会抛出运行时异常ArrayIndexOutofBoundsException(数组 越界异常)
-
数组属性:length表示数组长度 数组名称.length返回此数组长度
1.2数组的创建-静态数组
声明数组的同时将数组内容赋值。
数据类型[]数组名称=new 数据类型[]{值1,值2,值3… …};
或者简写:数据类型[]数组名称={值1,值2,值3… …};
eg.int[]data={1,2,3}
长度:数组长度依然固定,数组名称.length返回此数组长度超出范围 :ArrayIndexOutofBoundsException(数组 越界异常)
1.3数组的使用
a.返回数组长度
int[] arr={1,2,3};
System.out.println(arr.length)
b.获取数组中的元素
int[] arr={1,2,3}
System.out.println(arr[0]);
注意:下标访问数组的有效范围是[0,length-1]
c.遍历数组
- 使用for循环
int[] arr={1,2,3}
for(int i=0;i<arr.length;i++){
System.out.println(arr[i]);
}
- 使用for-each循环
int[] arr={1,2,3}
for(int x:arr){
System.out.println(x);
}
1.3数组的引用传递
引用是什么?
在栈上开辟了一小块内存空间保存一个地址
什么是创建引用?
创建了一个很小的变量,这个变量保存了一个整数,这个整数就是内存中的一个地址
引用数据类型int a=10;
Int[]data=new int[3]//new开辟新空间
data称为数组的引用(保存在栈内存上,指向堆内存),任何一个引用一定指向一块堆内存空间
总结:
Java 将数组设定成引用类型, 这样的话后续进行数组参数传参, 其实只是将数组的地址传入到函数形参中. 这样可以避免对整个数组的拷贝(数组可能比较长, 那么拷贝开销就会很大).
null空引用
一个无效的引用.
int[] arr = null;
表示一个无效的内存位置. 因此不能对这个内存进行任何读写操作.
一旦尝试读写, 就会抛出 NullPointerException.
引用传递:多个栈内存共享一块堆内存地址(可以类比:多个遥控器控制一个空调~~)
数组与方法的相互操作—引用传递方法接收数组方法返回数组方法修改数组java对数组的支持(JDK对数组的支持:)
数组排序
Java.util.Arrays.sort(数组名称)——(系统自带排序方法:静态方法):
支持所有数据类型,默认为升序排序,内部为双轴快速排序Java中对数组的支持
1.4数组拷贝
将一个数组的部分内容替换为另一个数组的部分内容(必须是连续的)
深拷贝:Arrays.copyof(原数组名称,新数组长度)
原理:
创建了一个新的数组对象,将原来的数组的所有元素拷贝到新的数组对象中,修改原数组->不会影响新数组
举例:
package se.SE.practice;
import java.util.Arrays;
public class array {
//数组拷贝
public static void main(String[] args) {
int[] arr={1,2,3,4,5,6};
int[] newarr=Arrays.copyOf(arr,arr.length);
for(int s:newarr){
System.out.print(s+" ");
}
}
}
//输出:1 2 3 4 5 6
浅拷贝:System.arraycopy(源数组名称,源数组开始点,目标数组名称,目标数组开始点,拷贝长度)
package se.SE.practice;
import java.util.Arrays;
public class array {
//数组拷贝
public static void main(String[] args) {
int[] arr={1,2,3,4,5,6};
int[] newarr1=new int[10];
int[] newarr=Arrays.copyOf(arr,arr.length);//Arrays.copyOf(原数组名称,现数组长度)
System.out.println("数组arr:"+Arrays.toString(arr));
System.out.println("数组newarr:"+Arrays.toString(newarr));
System.arraycopy(arr,0,newarr1,2,2);//System.arraycopy(原数组名称,原数组开始点,目标数组名称,目标数组开始点,拷贝的长度)
System.out.println("数组newarr1:"+Arrays.toString(newarr1));
}
}
//输出:
//数组arr:[1, 2, 3, 4, 5, 6]
//数组newarr:[1, 2, 3, 4, 5, 6]
//数组newarr1:[0, 0, 1, 2, 0, 0, 0, 0, 0, 0]
数组全拷贝类集的动态扩容就是使用此方法!(数组的容量扩大),此方法是native方法
效率更高:System.arraycopy
因为它没有创建新的对象(也就是在堆内存中没有分配空间),而是增加一个引用变量和之前的引用指向相同的堆空间。
1.5数组的应用
查找数组中的指定元素(顺序查找)
定义find函数返回的是当前的数字对应的数组下标(整型)
package se.SE.practice;
public class array {
public static void main(String[] args) {
int[] arr={1,2,3,4,5,6,7,8,9,10};
System.out.println("数组的下标为:"+find(arr,5));
}
public static int find(int[] array,int tofind){
for(int i=0;i<array.length;i++){
if(array[i]==tofind){
return i;
}
}
return -1;
}
//输出:
//数组的下标为:4
查找数组元素中的指定元素(二分查找)
针对有序数组,可以采用更加高效的二分查找法
二分查找
就是将有序的数组分成两部分,拿升序为例
如果要查找的数字比数组中间值小,就在中值左边查找
反之,则在右边
package se.SE.practice;
//二分查找
public class array {
public static void main(String[] args) {
int[] arr={1,2,3,4,5,6,7,8,9,10};
System.out.println("数组的下标为:"+binaryfind(arr,5));
}
public static int binaryfind(int[] array,int tofind){
int left=0;
int right=array.length-1;
while (left<right){
int mid=(left+right)/2;
//去mid左侧遍历找tofind=array[mid]
if(tofind<array[mid]){
right=mid-1;
}
//去mid右侧遍历找tofind=array[mid]
if(tofind>array[mid]){
left=mid+1;
}else {
//找到了!
return mid;
}
}
return -1;
}
检查数组的有序性
给定一个整型数组判断其是否序:循环遍历数组,判断前一个数是否小于后一个数
//给定一个数组,判断它是否有序(例子为判断是否升序)
public class array {
public static void main(String[] args) {
int[] arr={1,2,3,4,5,6,7,8,9,10};
System.out.println("数组升序排列正确吗?(true表示正确/false表示不正确) :"+isSorted(arr,5));
}
public static boolean isSorted(int[] array,int tofind) {
for(int i=0;i<array.length;i++){
if(array[i]<array[i+1]){
return true;
}else {
return false;
}
}
return false;
}
//输出:
//数组升序排列正确吗?(true表示正确/false表示不正确) :
//true
数组逆序
给定一个数组,将其逆序排列
思路:设定两个下标, 分别指向第一个元素和最后一个元素. 交换两个位置的元素.
然后让前一个下标自增, 后一个下标自减, 循环继续即可.
例子:给定数组为
int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
package se.SE.practice;
import java.util.Arrays;
public class array {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
reverse(arr);
System.out.println(Arrays.toString(arr));
}
public static void reverse(int[] array) {
int left=0;
int right=array.length-1;
for(int i=0;i<array.length;i++){
if(left<right){
int tmp=array[left];
array[left]=array[right];
array[right]=tmp;
}
left++;
right--;
}
}
//输出:
//[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
数组数字排列
给定一个数组,数组的前半部分放偶数,后半部分放奇数
首先,我们需要对偶数和奇数有一个基本的认识,能够被二整除的数是偶数,0也是偶数,不能被二整除的数就是奇数
那么偶数可以表示为某数%2==0奇数反之
思路:设定两个下标left,right分别指向第一个元素和最后一个元素,
left向右遍历,发现第一个奇数,right向左遍历发现的第一个偶数,两者交换,继续遍历,直至两个下标相遇结束
//偶数放前面,奇数放后面
public class array {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
transform(arr);
System.out.println(Arrays.toString(arr));
}
public static void transform(int[] array) {
int left=0;
int right=array.length-1;
while (left<right){
while (left<right&&array[left]%2==0){
left++;
}
while (left<right&&array[right]%2!=0){
right--;
}
int tmp=array[left];
array[left]=array[right];
array[right]=tmp;
}
}
//输出:[10, 2, 8, 4, 6, 5, 7, 3, 9, 1]
二维数组
本质上也就是一维数组,只不过每个元素又是一个一维数组
数据类型[][] 数组名称 = new 数据类型 [行数][列数] { 初始化数据 };
public class array {
public static void main(String[] args) {
int[][] arr = {{1,2,3,4},{5,6,8,9},{5,8,0,4},{4,7,8,9}};
for(int row=0;row<arr.length;row++){
for(int col=0;col<arr[row].length;col++){
System.out.print(arr[row][col]+" ");
}
System.out.println(" ");
}
}