java之数组

java之数组

数组的概述

  • 数组是存储多个变量(元素)的东西(容器)
  • 这多个变量的数据类型要要一致

数组:存储同一种数据类型的多个元素容器

数组定义格式

A:数据类型[] 数组名;

B:数据类型数组名[];

举例:

int[]arr; 定义了一个int类型的数组,数组名是arr

 int arr[] ;定义了一个int类型的变量,变量名是arr数组

//不推荐

因为第一种可以将类型int与变量名清晰地分开。

错误的声明数组的方式,声明数组的时候不能指定其大小

int [5] intErrorArray0;

int intErrorArray1[5];

数组初始化

java中数组必须先初始化,然后才能使用。

所谓初始话,就是为了数组中的数组元素分配内存空间。并为每个数组元素赋值。

数组的初始化方式

动态初始化

动态初始化:初始化时只指定数组长度,又系统为数组分配初始值。

格式: 数据类型[]数组名 = new 数据类型[数组长度]

举例:

int[]arr = new int[3];

左边:

 \*    int:说明数组中的元素的数据类型是int类型

 \*    []:说明这是一个数组

 \*    arr:是数组的名称

右边:

 \*    new:为数组分配内存空间

 \*    int:说明数组中的元素的数据类型是int类型

 \*    3:数组的长度,其实就是数组中的元素个数

\*    []:说明这是一个数组

注意:一旦创建了数组,就不能在改变它的长度(不过,当然可以改变单个的数组元素)。如果程序运行中需要经常扩展数组的大小,就应该使用另一种数据结构——数组列表(array list)

静态初始化

静态初始化;初始化时指定每个数组元素的初始值,由系统决定数组长度

例如:

 int[] smallPrimes = {2,3,5,7,11,13};

最后一个值后面允许有逗号,如果你要不断为数组增加值,这回很方便。

还可以声明一个匿名数组:

new int [] {17,19,23,29,31,37}

这会分配一个新数组并填入括号中提供的值,它会统计初始值的个数,并相应地设置数组大小。可以使用这种语法重新初始化一个数组而无须创建变量。例如:

array = new int[] {1, 2, 5, 89};

这个语句是下面语句的简写:

int[] tempArray = {1, 2, 5, 89};

array = tempArray;

注意:在Java中允许数组长度为0。在我们要编写一个结果为数组的方式时,如果碰巧结果为空,那么这种语法形式显得特别有用。此时可以创建一个长度为0的数组:值得注意的是:数组长度为0和null是不一样的,这个需要特别注意。null代表这个数组并不存在,长度为0表示这个数组不包含任何元素,但是数组是存在的。

访问数组元素

创建一个数字数组时,所有元素都初始化为0。

boolean数组的元素会初始化为false。

对象数组的元素则初始化为一个特殊值null,表示这些元素还未存放任何对象。

注意:访问超过了数组的元素,就会出现“array index out of bounds”异常。

想要获得数组中的元素个数,可以用array.length。

for each 循环

java有一种功能很强的循环结构,可以用来依次处理数组(或者其他元素集合)中的每个元素,而不必考虑指定下的值。

格式:

for(循环对象的类型 元素名:对象名){

语句

}

for 循环写法

int[] arr ={1,2,3,4,5};

for(int i = 0; i<arr.length; i++){

System.out.println(arr[i]);

}

for each格式

for(int data :arr){

System.out.println(data);

}

总结:for each循环语句显得更加、更不易出错,因为你不必为了下标的起始值和终止值而操心。如果需要用下标值时或者不想遍历所有元素的时候。

还有一个更加简单的方式打印数组中的所有值,即利用Arrays类的toString方法。调用Arrays.toString(a),返回一个包含数组元素的字符串,这些元素包括在中括号内,并用逗号分隔,例如,“[2,3,5,7,11,13]”。要想打印数组,只需要调用

System.out.print(Arrays.toString(a));

数组拷贝

分别为:for clone() System.arraycopy()Array.copyOf()

要研究数组的拷贝,先看看浅拷贝与深拷贝的概念:
概括起来讲,浅拷贝就是指两个对象公用一个值,一个的改变了另一个也会随之改变,深拷贝则是两个对象虽然值相等,但是相互独立互不影响。

一、For写法

       public static void main(String[] args) {
         int[] array1 = new int[]{1, 2, 8, 7, 6};
         int[] array2 = new int[array1.length];
         for (int i = 0;i < array1.length;i++){
        array2[i] = array1[i];
}

        System.out.println("array1 = " + Arrays.toString(array1));
        System.out.println("array2 = " + Arrays.toString(array2));
        System.out.println("======================");
    
        array2[0] = 100;
        System.out.println("array1 = " + Arrays.toString(array1));
        System.out.println("array2 = " + Arrays.toString(array2));

   }
   }

输出:
array1 = [1,2,8,7,6]
array1 = [1,2,8,7,6]

====================

array1 = [1,2,8,7,6]
array1 = [100,2,8,7,6]

由结果可以看出,当对复制数组的某个元素进行改变时,并不影响被复制数组对应元素,即对于基本数据类型来说for循环语句是深拷贝。

二、System.arraycopy()写法

public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);

参数说明:
src:源对象
srcPos:源数组中的起始位置
dest:目标数组对象
destPos:目标数据中的起始位置
length:要拷贝的数组元素的数量

System.arraycopy() 源码如下:

public class ArraycopyTest{
	public static void main(String[] args){
    	char[] c1 = new String("123456").toCharArray();
    	char[] c2 = new String("abcdef").toCharArray();
   	 	System.arraycopy(c1, 2, c2, 1, 2);
    	System.err.println(Arrays.toString(c1));
    	System.err.println(Arrays.toString(c2));
 	}
}

输出:
[1, 2, 3, 4, 5, 6][a, 3, 4, d, e, f]

注意:(1)、System.arraycopy() 在拷贝数组的时候,采用的使用潜拷贝,复制结果是一维的引用变量传递给副本的一维数组,修改副本时,会影响原来的数组。

       <font color="red">(2)、如果是数组比较大,那么使用System.arraycopy会比较有优势,因为其使用的是内存复制,省去了大量的数组寻址访问等时间。System.arraycopy()源码,可以看到是native方法:native关键字说明其修饰的方法是一个原生态方法,方法对应的实现不是在当前文件,而是在用其他语言(如C和C++)实现的文件中。 可以将native方法比作Java程序同C程序的接口。System.arraycopy是不安全的。</font>

三、copyOf写法

从代码可知,数组拷贝时调用的是本地方法 System.arraycopy() ;

Arrays.copyOf()方法返回的数组是新的数组对象,原数组对象仍是原数组对象,不变,该拷贝不会影响原来的数组。copyOf()的第二个自

变量指定要建立的新数组长度,如果新数组的长度超过原数组的长度,则保留数组默认值.

在java中,允许将一个数组变量拷贝到另一个数组变量。这时,两个变量将引用同一个数组

int luckyNumber = smallPrimes;

luckyNumbers[5] = 12;

这样smallPrimes也是12

希望将一个数组的所有值拷贝到一个新的数组中去,就要使用Arrays类的copyOf方法:

int[] copitedLuckNumbers = Arrays.copyOf(luckNumber,luckNumbers.length);

第2个参数时新数组的长度。这个方法通常用来增加数组的大小:

luckNumbers = Arrays.copyOf(luckyNumbers,2 * LuckNumbers.length);

copyOf与System.arraycopy()对比
int[] arr = {1,2,3,4,5};

int[] copied = new int[10];

System.out.println(Arrays.toString(copied));

System.arraycopy(arr, 0, copied, 1, 5);//5是复制的长度

System.out.println(Arrays.toString(copied));

输出:
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0][0, 1, 2, 3, 4, 5, 0, 0, 0, 0]

int[] copied = Arrays.copyOf(arr, 10); //10是新数组的长度

System.out.println(Arrays.toString(copied));

copied = Arrays.copyOf(arr, 3);

System.out.println(Arrays.toString(copied));

输出:
[1, 2, 3, 4, 5, 0, 0, 0, 0, 0][1, 2, 3]

区别Arrays.copyOf() 不只复制数组元素,也创建一个新数组。System.arrayCopy 只复制已有的数组。

四、clone方法

clone方法是从Object类继承过来的,基本数据类型(int ,boolean,char,byte,short,float ,double,long)都可以直接使用clone方法进行克隆,注意String类型是因为其值不可变所以才可以使用。是深拷贝。

int 类型示例
int[] a2 = a1.clone();
a1[0] = 666;
System.out.println(Arrays.toString(a1));   //[666, 3]
System.out.println(Arrays.toString(a2));   //[1, 3]
String类型示例
String[] a2 = a1.clone();
a1[0] = "b1"; //更改a1数组中元素的值
System.out.println(Arrays.toString(a1));   //[b1, a2]
System.out.println(Arrays.toString(a2));   //[a1, a2]

数组排序

对数组进行排序,可以使用Arrays类中的sort方法:

int[] a = new int[10000];

Arrays.sort(a)

这个方法使用了优化的快速排序算法。

多维数组

二维数组(也称为矩阵)储存这些信息。这个数组被称为balance。

初始化:

数据类型[][] [][] 数组名 = new 数据类型[数组长度] [数组长度]

二维数组定义时需要两个中括号,方式如下:

int[][] arr=new int[2][3];

int[][] arr =new int[3][];

定义二维数组arr以后,arr是二维数组,arr[i]是一维数组,arr[i][j]是数据。其中最左边的中括号里面必须有长度

二维数组的遍历

  int[][] arr2 = { {1,2},{3,4,5},{6,7,8,9,10} };
        int sum2 = 0;
        for (int i=0; i<arr2.length; i++) {
            for (int j=0; j<arr2[i].length; j++) {
                 //System.out.println(arr2[i][j])
                sum2 += arr2[i][j];
            }
        }
        System.out.println("sum2= "+ sum2);
    }
}

二维数组静态初始化与动态初始化的区别:数组范围不同,多占用了很多空间

java虚拟机的内存划分

为了提高效率,就对空间进行了不同区域的划分,因为每一篇区域都有特定的处理数据方式和内存管理方式

寄存器:给CPU用,与开发无关

本地方法栈:JVM在使用操作系统功能的时候用,和我们开法无关

方法区:存储可以运行的class文件

堆内存:存储对象或者数组,new来创建的,都存储在堆内存

方法栈:方法运行时使用内存,比mian方法运行,进入方法栈中执行。

程序执行流程:

1、main方法进入方法栈执行

2、创建数组,jvm会在堆内存中开辟空间,存储数组

3、数组在内存中会有自己的内存地址,以十六进制数表示

4、数组中有三个元素,默认值0

5、JVM将数组的内存地址赋值给引用类型变量arr

6、变量arr保存的是内存数组中的地址,而不是一个具体数值,因因此被称为引用数据类型
请添加图片描述

java常用API

Java常用API
输出数组 Arrays.toString()

  int[] array = { 1, 2, 3 };
 System.out.println(Arrays.toString(array));

数组转List Arrays.asList()

String[] array2 = {"a", "b", "c", "d"};
	System.out.println(array2);  // [Ljava.lang.String;@13b6d03
	List list = new ArrayList(Arrays.asList(array2));
	System.out.println(list);   // [a, b, c, d]
	list.add("GG");
	System.out.println(list);  // [a, b, c, d, GG]

数组转Set Arrays.asList()

String[] array = { "a", "b", "c", "d", "e" };
	Set set = new HashSet(Arrays.asList(array));
	System.out.println(set);

List转数组 toArray()

	List list = new ArrayList();
	list.add("a");
	list.add("b");
	list.add("c");
	String[] array = new String[list.size()];
	list.toArray(array);
	for (String s : array)
	System.out.println(s);

数组中是否包含某个值

String[] array = { "a", "b", "c", "d", "e" };
boolean isEle = Arrays.asList(array).contains("a");
System.out.println(isEle);

数组复制

int array[] = new int[] { 1, 2, 3, 4 };
int array1[] = new int[array.length];
System.arraycopy(array, 0, array1, 0, array.length);

数组合并

int[] array1 = { 1, 2, 3, 4, 5 };
int[] array2 = { 6, 7, 8, 9, 10 };
int[] array = org.apache.commons.lang.ArrayUtils.addAll(array1, array2);
System.out.println(Arrays.toString(array));
String数组转字符串(使用指定字符拼接)
String[] array = { "a", "b", "c" };
String str = org.apache.commons.lang.StringUtils.join(array, ", ");
System.out.println(str);

数组逆序

int[] array = { 1, 2, 3, 4, 5 };
org.apache.commons.lang.ArrayUtils.reverse(array);
System.out.println(Arrays.toString(array));

数组元素移除

int[] array = { 1, 2, 3, 4, 5 };
int[] removed = org.apache.commons.lang.ArrayUtils.removeElement(array, 3);
System.out.println(Arrays.toString(removed));  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值