java—(7)数组相关


一、数组的定义及初始化
静态定义:
 String[] bArray = {"a","b","c", "d", "e"};
 String[] cArray = new String[]{"a","b","c","d","e"};
动态定义:
 String[] aArray = new String[5];
  
  
二、数组的存储(同对象一样)
Java中的数组存储两类事物: 基本类型(int,char,...),或者引用(对象指针).
当一个对象通过 new 创建,那么将在堆内存中分配一段空间,并且返回其引用(指针).
对于数组,也是同样的方式.
1. 一维数组
[java]  view plain copy
  1. int arr[] = new int[3];  
int[] arr 指向 包含3个整数的数组. 假设创建的是包含10个整数的数组,也是同样的用法 —— 分配指定大小的内存,并返回数组的引用。


2. 二维数组
二维数组又有什么区别呢?实际上,在Java中只有一维数组。二维数组本质上也是一维数组,只是数组中的每一个元素都指向了另一个一维数组而已。
[java]  view plain copy
  1. int[ ][ ] arr = new int[3][ ];  
  2. arr[0] = new int[3];  
  3. arr[1] = new int[5];  
  4. arr[2] = new int[4];  


同样的原理,多维数组也是如此.
3. 数组分配在内存的哪个区域?
Java中的数组,也是对象(继承Object),因此数组所在的区域和对象是一样的.
我们知道,      

JVM 运行时数据区

 包括 JVM栈,堆内存,以及其他区域. 看下面的关于对象的简单示例,我们一起来了解数组如何分配,以及引用保存在哪里.
[java]  view plain copy
  1. class A {  
  2.     int x;  
  3.     int y;  
  4. }  
  5. ...  
  6. public void m1() {  
  7.     int i = 0;  
  8.     m2();  
  9. }  
  10. public void m2() {  
  11.     A a = new A();  
  12. }  
  13. ...  

上面的代码片段中,让我们执行 m1()方法看看发生了什么:
  1.  当 m1 被调用时,一个新的栈帧(Frame-1)被压入JVM栈中,当然,相关的局部变量也在 Frame-1中创建,比如 i;
  2.  然后 m1调用m2,,又有一个新的栈帧(Frame-2)被压入到JVM栈中;   m2方法在堆内存中创建了A类的一个对象,此对象的引用保存在 Frame-2的局部变量 a 中. 此时,堆内存和栈内存看起来如下所示:


而 数组(Array)被当做Object处理,因此数组如何保存的,你应该明白了.
所有局部变量放在栈内存当中,(不管其是基本类型的变量还是引用类型的变量),但引用类型变量所引用的对象(包括数组、普通java对象)则总是存储在堆内存中。
java语言不允许直接访问堆内存中的数据,因此无法直接访问堆内存中的数组对象,程序将通过数组引用变量来访问数组。
在定义局部变量时:
基本类型产生了一个值存放在栈中,变量的值就是栈的地址处的值。
引用类型则产生了一个对象,存放在内存堆中,同时将内存堆对象的指针地址(引用地址)存放在了栈中,变量的值实际是栈中的引用地址。
关于数组在内存中的分布,首先,一定是在堆中申请了一段连续的内存,内存的占用要看数组的类型,如果是基本类型,如int,则按照每个元素4个字节方式存放,例如int[] x = new int[4]; 这个时候就产生了1个对象,4个元素,每个元素占4个字节,数组对象头还要占一些字节(应该是12个)。同时,返回堆中的数组对象首地址给栈中的变量。对于引用类型,数组中的元素要存放数组的引用指针,一般也是4个字节来表示一个元素,即使这个数组的引用为null,一样要为其保留4个字节的内存空间。

java的数组是一种引用型的变量,数组变量并不是数组本身。他只是指向堆内存中的数组对象。
对数组变量来说,他们并不需要进行所谓的初始化,只要让数组变量指向一个有效的数组对象,程序即可正常使用该数组变量。
需要初始化的永远只是该引用变量所引用的对象,而不是引用变量本身。
对基本类型数组而言,数组元素的值直接存储在对应的数组元素上。
因此基本类型数组的初始化比较简单:程序直接先为数组分配内存空间,再将数组元素的值存入对应的内存中。
引用类型数组的初始化
引用类型数组的数组元素依然是引用类型的,因此数组元素里存储的还是引用。他指向另一块内存,这块内存里存储了该变量所引用的对象(包括数组和java对象)。
对于引用类型的数组而言,他的数组元素其实是一个引用类型的变量,因此可以指向任何有效的内存——此处”有效“的意思是指强类型的约束。比如Person[]类型的数组,它的每个数组元素都相当于Person类型的变量,因此他的数组元素只能指向Person对象。
String[] names = { "Michael", "Orson", "Andrew" };
        // 动态初始化数组
        String[] animal = new String[4];
        // 让animal 指向 namens 数组所引用的数组
        names = animal;

问题:引用变量何时只是栈内存中的变量本身,何时又变为引用实际的java对象?
答:其实规则很简单,引用变量本质上只是一个指针,只要程序通过引用变量访问属性或方法,该引用变量将会由他所引用的对象代替。

三、将数组变成字符串(Arrays类toString)
int[] intArray = { 1, 2, 3, 4, 5 };
String intArrayString = Arrays.toString(intArray);
System.out.println(intArrayString);
// [1, 2, 3, 4, 5]
    
    
四、将数组变成ArrayList(Arrays类toString)

    
    
int[] intArray = { 1, 2, 3, 4, 5 };
ArrayList<Integer> arrayList = new ArrayList<Integer>(Arrays.asList(intArray));
System.out.println(arrayList);
// [1, 2, 3, 4, 5]
  
  
    
    

    
    
为什么要将Array转换成ArrayList呢?可能是因为ArrayList是动态链表,我们可以更方便地对ArrayList进行增删改,我们并不需要循环Array将每一个元素加入到ArrayList中,用以上的代码即可简单实现转换。
     
     
         
         
            
            
、将数组变成Set集合(Arrays类toString)
String[] stringArray = { "a", "b", "b", "d", "e" };
ArrayList<Integer> arrayList = new ArrayList<Integer>(Arrays.asList(intArray));
Set<String> set = new HashSet<String>(Arrays.asList(stringArray));
System.out.println(set);
//[d, e, b, a]
      
      
          
          
            
            
                
                
、比较两个数组是否相等(Arrays类equals)
		Integer[] a1 = { 1, 2, 3, 4, 5 };
		Integer[] a2 = { 1, 2, 3 };
		System.out.println(Arrays.equals(a1, a2));
		//false
        
        
七、查询数组中是否包含某个值,不循环
String[] stringArray = { "a", "b", "c", "d", "e" };
boolean b = Arrays.asList(stringArray).contains("a");
System.out.println(b);
// true
      
      
先使用Arrays.asList()将Array转换成List<String>,这样就可以用动态链表的contains函数来判断元素是否包含在链表中。
       
       
八、连接两个数组(ArrayUtils类addAll)

        
        
int[] intArray = { 1, 2, 3, 4, 5 };
int[] intArray2 = { 6, 7, 8, 9, 10 };
// Apache Commons Lang library
int[] combinedIntArray = ArrayUtils.addAll(intArray, intArray2);
ArrayUtils是Apache提供的数组处理类库,其addAll方法可以很方便地将两个数组连接成一个数组。

        
        
         
         
九、
将数组中的元素以字符串的形式输出
   
   
         
         
  
  
StringUtils
  
  
类join)
  
  

     
     
String j = StringUtils.join(new String[] { "a", "b", "c" }, ", ");
System.out.println(j);
// a, b, c

同样利用StringUtils中的join方法,可以将数组中的元素以一个字符串的形式输出。

       
       
         
         
十、数组翻转(ArrayUtils类reverse)
      
      

      
      
      
      

         
         
int[] intArray = { 1, 2, 3, 4, 5 };
ArrayUtils.reverse(intArray);
System.out.println(Arrays.toString(intArray));
//[5, 4, 3, 2, 1]

          
          
十一、从数组中移除一个元素(ArrayUtils类reverse)
       
       
int[] intArray = { 1, 2, 3, 4, 5 };
int[] removed = ArrayUtils.removeElement(intArray, 3);//create a new array
System.out.println(Arrays.toString(removed));
参考 http://www.codeceo.com/article/10-java-array-method.html
十二、数组排序(Arrays类sort)
Arrays类可以实现数组的排序,不管数组的元素是引用类型还是值类型。 下面的代码实现数组的正序、倒序排序:
String[] stringArray = { "a", "c", "b", "d", "e" };
Arrays.sort(stringArray);
for (String i : stringArray) {
System.out.print(i);
}
// abcde
Arrays.sort(stringArray, Collections.reverseOrder());
for (String i : stringArray) {
System.out.print(i);
}
// edcba
  
  
十三、数组拷贝copyOf
System.out.println(Arrays.toString(Arrays.copyOf(stringArray, 6)));
//[e, d, c, b, a, null]
   
   


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值