热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

关于JAVA数组的使用介绍

本篇文章小编将为大家介绍,关于JAVA数组的使用介绍,有需要的朋友可以参考一下

JAVA数组与容器类主要有三方面的区别:效率、类型和保存基本类型的能力。在JAVA中,数组是一种效率最高的存储和随机访问对象引用序列的方式。数组就是一个简单的线性数列,这使得元素访问非常快速。但是为此付出的代价却是数组的大小被固定,并且在其生命周期中不可改变。

由于范型和自动包装机制的出现,容器已经可以与数组几乎一样方便地用于基本类型中了。数组和容器都可以一定程度上防止你滥用他们,如果越界,就会得到RuntimeException异常。数组硕果仅存的优势便是效率,然而,如果要解决更一般化的问题,那数组可能会受到过多的限制,因此这种情况下大部分还是会选择容器。

因此,如果使用最近的JAVA版本,应该优先选择容器而不是数组。只有在已证明性能已成为问题,并且切换到数组可以提高性能时,才应该重构程序为数组。

【初始化】
JAVA对数组初始化有很严格的规定,这样可以有效地防止滥用数组。如果初始化错误,会直接得到CompileException而不是RuntimeException。在未对数组正确初始化之前,无法用此数组引用做任何事情。
数组定义有int[] array 和int array[],一般采用第一种风格,可以将类型与变量名分开。
数组的初始化有两种方式,静态初始化和动态初始化。初始化的时候必须指定长度,多维数组第一维的长度必须指出,同时必须由高维向低维定义。初始化动作可以在代码的任何地方,而用{}方式只能在创建数组的地方出现。具体初始化方式见程序:

代码如下:

public class javaArrayInit{
    public static void main(String args[]){
        int[] arrayA; //未初始化
        int[] arrayB = new int[5]; //静态初始化
        //System.out.println(arrayA.length);  //CompileException
        System.out.println("arrayB length: " + arrayB.length); //无法得到实际保存的元素个数

        arrayA = new int[10]; //动态初始化
        System.out.println("arrayA length: " + arrayA.length);

        int[] arrayC = new int[]{1,2,3,4};
        System.out.println("arrayC length: " + arrayC.length);

        //int[] arrayD = new int[1]{1}; //错误的初始化,不能同时定义维和初始化值

        int[][] arrayE = new int[1][];
        System.out.println("arrayE length: " + arrayE.length);

        //int[][] arrayF = new int[][2]; //应先指定高维的长度

        int[][] arrayG = new int[][]{{1,2,3,4},{5,6,7},{7,24,23,24}};
        System.out.println("arrayG length: " + arrayG.length);

        int[][][] arrayH = new int[][][]{{{1,2,3},{4,5,6},{7,8,9},{10,11,12}}};
        System.out.println("arrayH length: " + arrayH.length);

        dummyArray[] arrayI = {new dummyArray(),new dummyArray()}; //自定义数组类型
        System.out.println("arrayI length: " + arrayI.length);
        System.out.println("arrayI[1]: " + arrayI[1].getValue());

        dummyArray[] arrayK = new dummyArray[5];
        System.out.println("arrayK[0]: " + arrayK[0]); //null
        for(int i = 0; i             arrayK[i] = new dummyArray();
        }
        System.out.println("arrayK[0]: " + arrayK[0].getValue()); //2
    }
}
class dummyArray{
    private static int temp;
    private final int arrayValue = temp++;
    public int getValue(){
        return arrayValue;
    }
}

输出:

arrayB length: 5
arrayA length: 10
arrayC length: 4
arrayE length: 1
arrayG length: 3
arrayH length: 1
arrayI length: 2
arrayI[1]: 1
arrayK[0]: null
arrayK[0]: 2


【length】
只读成员length是数组对象的一部分(虽然实际上API里面并没有声明这个变量,是运行时动态生成),这是唯一一个可以访问的字段或方法。而[]语法是访问数组对象的唯一方式,容器是通过get()方法访问。可以使用Array.length来得到数组的大小,注意与String类型的String.length()区分。Array使用的是成员变量的方式,而String使用的是成员方法的方式。同时,Array.length只能得到数组的大小,而无法得到数组实际有多少元素。多维数组的length只计算第一维的长度。
代码如下:

public class javaArrayLength{
    public static void main(String args[]){
        int[] arrayA = new int[15];
        arrayA[1] = 1;
        arrayA[2] = 2;
        arrayA[3] = 3;
        System.out.println("arrayA length: " + arrayA.length);

        int[][] arrayB = new int[10][];
        System.out.println("arrayB length: " + arrayB.length);

        int[][] arrayC = new int[][]{{1,1,1,2,},{1,1,2,3,4,5},{4,5,6,7,7},};//注意后面的逗号
        System.out.println("arrayC length: " + arrayC.length);

        int[][] arrayD = new int[][]{{1,1,1,2,},{1,1,2,3,4,5},{4,5,6,7,7},{}};
        System.out.println("arrayD length: " + arrayD.length);
    }
}
输出:

arrayA length: 15
arrayB length: 10
arrayC length: 3
arrayD length: 4


【Arrays.fill】
Arrays.fill是一个作用十分有限的方法,因为它只能用同一个值填充各个位置(如果是对象,则复制同一个引用进行填充)。使用Arrays.fill可以填充整个数组或者数组的某一个区域,但是由于只能用单一的数值来调用Arrays.fill,因此作用并不是很大。

【赋值与引用】
JAVA数组初始化的时候拥有的只是对数组的引用,并没有给数组分配存储空间。因此,数组之间的复制不能简单地用“=”赋值,因为操作的是同一对象。如下程序:
代码如下:

public class javaArrayQuote{
    public static void main(String args[]){
        String testA = "testA";
        String testB = "testB";
        String[] arrayA = new String[]{"arrayA"};
        String[] arrayB = new String[]{"arrayB"};
        testB = testA;
        testB = "testB change";
        System.out.println("I'm testA,I have no changed: " + testA);
        arrayB = arrayA;
        arrayB[0] = "arrayB have changed";
        System.out.println("I'm arrayA, I have no changed: " + arrayA[0]);

    }
}
输出:

I'm testA,I have no changed:testA
I'm arrayA, I have no changed:arrayB have changed


可以看出,我们改变arrayB[0]的值,改变的是引用的数组,因此我们输出arrayA[0],其实和arrayB[0]一样。

【数组复制】
        JAVA中复制数组的方法:

        1.使用FOR循环复制全部或指定元素,效率较低
        2.使用clone方法,得到数组的值,而不是引用。然而clone不能复制指定元素,灵活性较低
        3.使用System.arraycopy(src, srcPos, dest, destPos, length)方法,java标准类库提供有static方法 System.arraycopy(),用它复制数组要比for循环快很多,System.arraycopy()针对所有类型做了重载,基本类型数组和对象数组都可以用System.arraycopy()复制,但是对象数组只是复制引用,不会出现两份对象的拷贝。这被称作浅复制(shallowcopy)。
               src:源数组;
                srcPos:源数组要复制的起始位置;
                dest:目的数组;
                destPos:目的数组放置的起始位置;
                length:复制的长度.
        注意:System.arraycopy()不会进行自动包装和自动拆包,因此两个数组必须是同类型或者可以转换为同类型的数组。同时,这个方法也可以用于复制数组本身。
        int[] test ={0,1,2,3,4,5,6};
        System.arraycopy(test,0,test,3,3);
        则结果为:{0,1,2,0,1,2,6};
        测试程序如下:
代码如下:

public class javaArrayCopy{
    public static void main(String args[]){
        int[] array = {1,2,3,4,5,6,7,8,9};
        //for循环方法
        int[] arrayA = new int[9];
        for(int i = 0; i             arrayA[i] = array[i];
            System.out.print(arrayA[i] + ",");
        }
        //测试
        System.out.println("");
        arrayA[1] = 19;
        for(int i = 0; i             System.out.print(arrayA[i] + ",");
        }
        System.out.println("");
        for(int i = 0; i             System.out.print(array[i] + ",");
        }
        System.out.println("");

        //clone方法
        int[] arrayB = new int[9];
        arrayB = array.clone();
        //测试
        arrayB[1] = 19;
        for(int i = 0; i             System.out.print(arrayB[i] + ",");
        }
        System.out.println("");
        for(int i = 0; i             System.out.print(array[i] + ",");
        }
        System.out.println("");

        //System.arrayCopy 方法
        int[] arrayC = new int[9];
        System.arraycopy(array, 0, arrayC, 0, arrayC.length);
        //测试
        arrayC[1] = 19;
        for(int i = 0; i             System.out.print(arrayC[i] + ",");
        }
        System.out.println("");
        for(int i = 0; i             System.out.print(array[i] + ",");
        }
    }
}

【数组比较】
Arrays提供了重载后的equals()方法,针对所有类型和Object类型都做了重载,用来比较整个数组。数组相等的条件是元素个数必须相等,并且对应位置的元素也相等。而多维数组的比较用deepEquals()方法。Array.equals()方法比较的两个数组必须是同类型的数组。
代码如下:

import java.util.Arrays;
public class javaArrayEquals{
    public static void main(String args[]){
        int[] arrayA = {1,2,3};
        int[] arrayB = {1,2,3,};
        int[] arrayC = new int[4]; //if int[] arrayC = new int[3],return true
        arrayC[0] = 1;
        arrayC[1] = 2;
        arrayC[2] = 3;
        System.out.println(Arrays.equals(arrayA, arrayB));
        System.out.println(Arrays.equals(arrayA, arrayC));

        String[][] arrayD = {{"a","b"},{"c","d"}};
        String[][] arrayE = {{"a","b"},{"c","d"}};
        System.out.println(Arrays.deepEquals(arrayD, arrayE));
    }
}

【数组排序与查找】
数组提供了内置的排序方法sort(),可以对任意基本类型数组或者对象数组进行排序(该对象必须实现Comparable接口或者具有相关联的Comparator)。JAVA对不同的类型提供了不同的排序方法----针对基本类型设计的快速排序,以及针对对象设计的“稳定归并排序”,所以无需担心数组排序的效率问题。
 binarySearch()用于在以排好序的数组中快速查找元素,如果对未排序的数组使用binarySearch(),那么将产生难以预料的结果。

【返回数组】
C和C++不能返回一个数组,只能返回指向数组的指针,因为返回数组使得控制数组的生命周期变得困难,并且容易造成内存泄漏。java允许直接返回一个数组,并且可以由垃圾回收机制回收。

【数组与容器转换】【无法转换基本类型数组】

数组转为List:
代码如下:

import java.util.*;
public class arrayToList{
    public static void main(String args[]){
        String[] arrayA = {"a","b","c"};
        List listA = java.util.Arrays.asList(arrayA);
        System.out.println("listA: " + listA);

        int[] arrayB = {1,2,3};
        List listB = java.util.Arrays.asList(arrayB);
        System.out.println("listB: " + listB);

        Integer[] arrayC = {1,2,3};
        List listC = java.util.Arrays.asList(arrayC);
        System.out.println("listC: " + listC);
    }
}
输出:


listA: [a, b, c]
listB: [[I@de6ced]
listC: [1, 2, 3]


为什么int和Integer输出会不同呢?

List转为数组
代码如下:

import java.util.*;
public class listToArray{
    public static void main(String args[]){
        List list = new ArrayList();
        String[] array;
        list.add("testA");
        list.add("testB");
        list.add("testC");
        System.out.println("list: " + list);

        String[] strings = new String[list.size()];
        array = list.toArray(strings);
        for(int i = 0, j = array.length; i             System.out.print(array[i] + ",");
        }
    }
}
输出为:

list: [testA, testB, testC]
testA,testB,testC


【去除重复数据】
利用数组和容器转换可以方便地去除数组重复数据,不过如果数组过大,效率是一个问题。
代码如下:

import java.util.*;
public class javaArrayUnique{
    public static void main(String args[]){
        String[] array = {"a","b","a","a","c","b"};
        arrayUnique(array);
        //test
        for(int i = 0, j = arrayUnique(array).length; i             System.out.print(arrayUnique(array)[i] + ",");
        }
    }

    public static String[] arrayUnique(String[] array){
        List list = new ArrayList();
        for(int i = 0, j = array.length; i             if(!list.contains(array[i])){
                list.add(array[i]);
            }
        }
        String[] strings = new String[list.size()];
        String[] arrayUnique = list.toArray(strings);
        return arrayUnique;
    }
}

 关于效率问题,我做了一个对比,在我电脑上运行十万数据的数组大概是577ms,而运行一百万数据的数据大约要5663ms。这还跟计算机的运行能力有关,但是明显是随着数组大小递增的。
代码如下:

import java.util.*;
public class javaArrayUnique{
    public static void main(String args[]){
        Double[] array = new Double[100000];
        for(int i = 0, j = array.length; i             array[i] = Math.ceil(Math.random()*1000);
        }

        Double[] arrayB = new Double[1000000];
        for(int i = 0, j = arrayB.length; i             arrayB[i] = Math.ceil(Math.random()*1000);
        }

        System.out.println("start");
        long startTime = System.currentTimeMillis();
        arrayUnique(array);
        long endTime = System.currentTimeMillis();
        System.out.println("array unique run time: " +(endTime - startTime) +"ms");

        long startTimeB = System.currentTimeMillis();
        arrayUnique(arrayB);
        long endTimeB = System.currentTimeMillis();
        System.out.println("arrayB unique run time: " +(endTimeB - startTimeB) +"ms");
    }

    public static Double[] arrayUnique(Double[] array){
        List list = new ArrayList();
        for(int i = 0, j = array.length; i             if(!list.contains(array[i])){
                list.add(array[i]);
            }
        }
        Double[] doubles = new Double[list.size()];
        Double[] arrayUnique = list.toArray(doubles);
        return arrayUnique;
    }
}
输出:

start
array unique run time: 577ms
arrayB unique run time: 5663ms



推荐阅读
  • 深入解析Spring Cloud Ribbon负载均衡机制
    本文详细介绍了Spring Cloud中的Ribbon组件如何实现服务调用的负载均衡。通过分析其工作原理、源码结构及配置方式,帮助读者理解Ribbon在分布式系统中的重要作用。 ... [详细]
  • 本文详细介绍了如何使用Spring Boot进行高效开发,涵盖了配置、实例化容器以及核心注解的使用方法。 ... [详细]
  • 本文详细探讨了Java中StringBuffer类在不同情况下的扩容规则,包括空参构造、带初始字符串和指定初始容量的构造方法。通过实例代码和理论分析,帮助读者更好地理解StringBuffer的内部工作原理。 ... [详细]
  • 本文探讨了领域驱动设计(DDD)的核心概念、应用场景及其实现方式,详细介绍了其在企业级软件开发中的优势和挑战。通过对比事务脚本与领域模型,展示了DDD如何提升系统的可维护性和扩展性。 ... [详细]
  • 深入了解 Windows 窗体中的 SplitContainer 控件
    SplitContainer 控件是 Windows 窗体中的一种复合控件,由两个可调整大小的面板和一个可移动的拆分条组成。本文将详细介绍其功能、属性以及如何通过编程方式创建复杂的用户界面。 ... [详细]
  • 实体映射最强工具类:MapStruct真香 ... [详细]
  • 深入解析 Apache Shiro 安全框架架构
    本文详细介绍了 Apache Shiro,一个强大且灵活的开源安全框架。Shiro 专注于简化身份验证、授权、会话管理和加密等复杂的安全操作,使开发者能够更轻松地保护应用程序。其核心目标是提供易于使用和理解的API,同时确保高度的安全性和灵活性。 ... [详细]
  • 本文探讨了在Linux系统上使用Docker时,通过volume将主机上的HTML5文件挂载到容器内部指定目录时遇到的403错误,并提供了解决方案和详细的操作步骤。 ... [详细]
  • 探讨如何真正掌握Java EE,包括所需技能、工具和实践经验。资深软件教学总监李刚分享了对毕业生简历中常见问题的看法,并提供了详尽的标准。 ... [详细]
  • 作为一名专业的Web前端工程师,掌握HTML和CSS的命名规范是至关重要的。良好的命名习惯不仅有助于提高代码的可读性和维护性,还能促进团队协作。本文将详细介绍Web前端开发中常用的HTML和CSS命名规范,并提供实用的建议。 ... [详细]
  • 本文探讨了在 ASP.NET MVC 5 中实现松耦合组件的方法。通过分离关注点,应用程序的各个组件可以更加独立且易于维护和测试。文中详细介绍了依赖项注入(DI)及其在实现松耦合中的作用。 ... [详细]
  • Startup 类配置服务和应用的请求管道。Startup类ASP.NETCore应用使用 Startup 类,按照约定命名为 Startup。 Startup 类:可选择性地包括 ... [详细]
  • 网易严选Java开发面试:MySQL索引深度解析
    本文详细记录了网易严选Java开发岗位的面试经验,特别针对MySQL索引相关的技术问题进行了深入探讨。通过本文,读者可以了解面试官常问的索引问题及其背后的原理。 ... [详细]
  • 自己用过的一些比较有用的css3新属性【HTML】
    web前端|html教程自己用过的一些比较用的css3新属性web前端-html教程css3刚推出不久,虽然大多数的css3属性在很多流行的浏览器中不支持,但我个人觉得还是要尽量开 ... [详细]
  • 本文将深入探讨如何在不依赖第三方库的情况下,使用 React 处理表单输入和验证。我们将介绍一种高效且灵活的方法,涵盖表单提交、输入验证及错误处理等关键功能。 ... [详细]
author-avatar
果子露强逼_604
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有