Java 之路 (十七) -- 数组(基本概念与使用、数组与泛型、数组操作、Arrays 类)

学完复杂的泛型,来学点简单的。本文介绍 Java 数组的相关知识。


1. 基本概念

数组是一个容器对象,它包含固定数量的单个类型的值。 创建数组时,将建立数组的长度。 创建后,其长度是固定的。

10 个元素的数组

数组中的每个项成为元素,每个元素由其数组索引访问。

举个简单例子:

class ArrayDemo {
    public static void main(String[] args) {
        // 声明一个整数数组
        int[] anArray;
        // 为10个整数分配内存
        anArray = new int[10];
        // 初始化第一个元素
        anArray[0] = 100;
        // 初始化第2个元素
        anArray[1] = 200;
        // 以此类推
        anArray[2] = 300;
        anArray[3] = 400;
        anArray[4] = 500;
        anArray[5] = 600;
        anArray[6] = 700;
        anArray[7] = 800;
        anArray[8] = 900;
        anArray[9] = 1000;

        System.out.println("Element at index 0: " + anArray[0]);
        System.out.println("Element at index 1: " + anArray[1]);
        System.out.println("Element at index 2: " + anArray[2]);
        System.out.println("Element at index 3: " + anArray[3]);
        System.out.println("Element at index 4: " + anArray[4]);
        System.out.println("Element at index 5: " + anArray[5]);
        System.out.println("Element at index 6: " + anArray[6]);
        System.out.println("Element at index 7: " + anArray[7]);
        System.out.println("Element at index 8: " + anArray[8]);
        System.out.println("Element at index 9: " + anArray[9]);
    }
} 
/*输出
Element at index 0: 100
Element at index 1: 200
Element at index 2: 300
Element at index 3: 400
Element at index 4: 500
Element at index 5: 600
Element at index 6: 700
Element at index 7: 800
Element at index 8: 900
Element at index 9: 1000
*/

1.1 声明数组

通过以下代码声明一个数组:

int[] anArray;

可以看出,与其他类型的变量声明相似,数组声明有两个部分:数组类型和数组名称。数组类型写法为 "type[]",数组名称可以是任意合法名称。

同样的,声明实际上并不创建数组,只是告诉编译器该变量是指定类型的数组。

对于其他类型的数组,创建方式也是如此:

byte[] anArrayOfBytes;
short[] anArrayOfShorts;
long[] anArrayOfLongs;
float[] anArrayOfFloats;
double[] anArrayOfDoubles;
boolean[] anArrayOfBooleans;
char[] anArrayOfChars;
String[] anArrayOfStrings;

另外,还有另外一种不常用写法,将[]放在后面:

float anArrayOfFloats[];

1.2 创建、初始化以及访问

创建数组的一种方法是使用 new 操作符。

anArray = new int[10];

之后,通过索引访问数组元素,并初始化:

anArray[0] = 100;
anArray[1] = 200; 
anArray[2] = 300; 

System.out.println("Element 1 at index 0: " + anArray[0]);
System.out.println("Element 2 at index 1: " + anArray[1]);
System.out.println("Element 3 at index 2: " + anArray[2]);

或者,可以在创建的时候同时进行初始化:

int[] anArray = { 
    100, 200, 300,
    400, 500, 600, 
    700, 800, 900, 1000
};

另外,还可以使用两个或多个括号[] 如String[][] names 声明一个多维数组。同样的每个元素必须由相应的索引值访问。

class MultiDimArrayDemo {
    public static void main(String[] args) {
        String[][] names = {
            {"Mr. ", "Mrs. ", "Ms. "},
            {"Smith", "Jones"}
        };
        // Mr. Smith
        System.out.println(names[0][0] + names[1][0]);
        // Ms. Jones
        System.out.println(names[0][2] + names[1][1]);
    }
}
/*输出
Mr. Smith
Ms. Jones
*/

然后,可以通过数组的 length 属性来确定数组的大小。

未初始化时,引用类型为 null,基本数据类型为零:

基本类型 默认值
boolean false
char '\uoooo'(null)
byte (byte)0
short (short)0
int 0
long 0L
float 0.0f
double 0.0d

2. 数组为什么特殊

数组和其他种类的容器之间的区别:

  1. 效率
  2. 类型
  3. 保存基本类型的能力

补充一些特性:

  • 数组是一种效率最高的存储和随机访问对象引用序列的方式。

    数组本身就是一个简单的线性序列,这使得元素访问非常快。当然代价是数组对象的大小被固定,并且不可改变。

  • 数组之所以优于泛型之前的容器,就是因为可以创建一个数组去持有某种具体类型,这意味着可以通过编译器检查,来防止插入错误类型和抽取不当类型。

  • 数组可以持有基本类型,而泛型之前的容器则不能,有了泛型之后,通过自动包装机制,容器看起来能够持有基本类型。

3. 数组与泛型

能实例化具有参数化类型的数组

Peel<Banana>[] peels = new Peel<Banana>[10];// 编译错误

擦除会移除参数类型信息,而数组本身必须知道它们所持有的确切类型,以强制保证类型安全

但是,可以参数化数组本身的类型:

public  <T> T[] f(T[] arg) {
    return arg;
}

编译器虽然不允许实例化泛型数组,但是可以创建这种数组的引用:

List<String>[] ls; //合法
ls = new ArrayList<String>[10]; //编译错误

尽管不能黄建始及的持有泛型的数组对象,但是可以创建非泛型的数组,然后将其转型:

public class ArrayOfGenerics {
    @SupressWarning("unchecked")
    public static void main(String... args) {
        List<String> ls;
        List[] la = new List[10];
        ls = (List<String>[]) la; //unchecked warning
        ls[0] = new ArrayList<String>();
    }
}

数组是协变类型的, 因此 List<String>[] 也是一个 Object[],可以将一个 ArrayList<String> 赋值到数组中。

4. 数组操作

本小节介绍以下 Java 内置的一些对数组操作的方法

4.1 复制数组

System类有一个arraycopy方法,可以使用它来有效地将数据从一个数组复制到另一个数组:

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

两个Object参数指定要从中复制的数组和要复制的数组。 三个int参数指定源数组中的起始位置,目标数组中的起始位置以及要复制的数组元素的数量。

class ArrayCopyDemo {
    public static void main(String[] args) {
        char[] copyFrom = { 'd', 'e', 'c', 'a', 'f', 'f', 'e',
                'i', 'n', 'a', 't', 'e', 'd' };
        char[] copyTo = new char[7];

        System.arraycopy(copyFrom, 2, copyTo, 0, 7);
        System.out.println(new String(copyTo));
    }
}
/*输出
caffein
*/

4.2 Arrays 类

java.util.Arrays类中的方法提供的一些有用的操作是:

  • 在数组中搜索特定值以获取其所在的索引( binarySearch方法)。
  • 比较两个数组以确定它们是否相等( equals方法)。
  • 填充数组以在每个索引处放置特定值( fill方法)。
  • 按升序对数组进行排序。 这可以使用sort方法顺序完成,也可以使用Java SE 8中引入的parallelSort方法同时完成。在多处理器系统上对大型数组进行并行排序比顺序数组排序更快。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容

  • 136.泛型 泛型代码让你可以写出灵活,可重用的函数和类型,它们可以使用任何类型,受你定义的需求的约束。你可以写出...
    无沣阅读 1,456评论 0 4
  • 传奇宝兴生态好,熊猫牛羊深山跑。 汽笛声声耳边过,道中漫步任逍遥。 ——素生 道中漫步任逍遥
    杨共同学阅读 228评论 0 1
  • 每当压力袭来,工作不顺心时,希望自己能提醒自己:愿君砥砺前行,会有赏尽两岸花开的那一天~
    禧珍阅读 250评论 6 14
  • 摘要:这篇文章,抛开心理角度解读“如何成为一个有趣的人”,我们从有趣是什么,如何培养有趣来说一说。 见到拉着大罐的...
    长呀长阅读 397评论 0 0
  • 我第一次知道自杀,是看的翁美玲的传记,她那会演的《射雕英雄传》红遍大陆,但是她因为失恋心情不好喝了酒开了煤气,最后...
    快乐的嫣红阅读 842评论 15 8