文档章节

《Java编程思想》第四版读书笔记 第十六章 数组

一万
 一万
发布于 2016/07/05 15:40
字数 1753
阅读 201
收藏 3

16.1 数组为什么特殊

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

泛型的出现使得容器也具备了类型检查的能力,而自动装箱机制使容器可以与数组几乎一模一样的用于基本类型,数组的硕果仅存的优点就是效率。

16.2 数组是第一级对象

在声明数组时可采用“聚集初始化”方法:

int[] integers = {0, 1, 2, 3, 4};

但是如果不在声明时初始化则必须采用“动态聚集初始化”方法:

int[] integers;

integers = new int[] {0, 1, 2, 3, 4};

16.4 多维数组

Java 1.5新增的Arrays.deepToString()方法可以将多维数组转换为可读的String。

数组中构造矩阵的每个向量都可以具有任意的长度,这被称为粗糙数组。

自动包装机制对数组初始化器也起作用。

练习5证明基本类型...写错了,应该是非基本类型

16.5 数组与泛型

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

Peel<Banana>[] peels = new Peel<Banana>[10]; //不合法

但是可以创建非泛型的数组,然后将其转型为泛型数组,一旦拥有了泛型数组的引用,就会得到编译器检查。但是数组是协变的,因此List<String>也是Object[],并且可以利用这一点把ArrayList<Integer>赋值到数组中而不会有编译期或运行时错误:

List<String>[] ls;
List[] la = new List[20];
ls = (List<String>[])la;
ls[0] = new ArrayList<String>();
//编译错误
//ls[1] = new ArrayList<Integer>();

Object[] objects = ls;
objects[1] = new ArrayList<Integer>();

如果确定将来不会向上转型,并且需求相对简单,那么可以创建泛型数组。但是泛型容器总是比泛型数组更好的选择。

16.6 创建测试数据

Java标准类库Arrays有一个作用十分有限的fill()方法,只能用同一个值填充各个位置,针对对象而言,就是复制同一个引用进行填充,还可以只填充数组的某个区域:

Arrays.fill(a9, "Hello");
Arrays.fill(a9, 3, 5, "World");

例子中有一段小数保留两位小数的代码可以借鉴:

int trimmed = Math.round(r.nextFloat() * 100);
return ((float)trimmed) / 100;

16.7 Arrays实用功能

Java标准类库提供static方法System.arraycopy(),用它复制数组比用for循环复制快很多。

System.arraycopy(Object src, int srcPosition, Object dest, int destPosition, int length);

基本类型数组与对象数组都可以复制。如果复制对象数组,只是复制了对象的引用——而不是对象本身的拷贝,这被称为浅复制。System.arraycopy()不会执行自动包装盒自动拆包,两个数组必须具有相同的确切类型。

Arrays类提供了静态equals()方法,用来比较整个数组。数组相等的条件是元素个数必须相等,并且对应位置的元素也相等,通过对每一个元素使用equals()方法来作比较。

使用Arrays.deepEquals()可以比较多维数组。

使用静态方法Arrays.sort()用语对数组进行排序。Java有两种方式来提供比较功能:

  1. 第一种是实现java.lang.Comparable借口,使类具有天生的比较能力。此接口只有一个compareTo()方法,此方法接收另一个Object为参数,如果当前对象小于参数则返回负值,如果相等则返回零,如果当前对象大于参数则返回正值。如果对没有实现Comparable接口的类的数组进行排序,会抛出ClassCastException。因为sort()需要把参数的类型转换为Comparable。
  2. 假设使用别人定义好的类并没有实现Comparable接口,或者类实现了Comparable接口但是需要另外一种比较方式。就需要创建一个实现了Comparator接口的单独的类。这是策略设计模式的一个应用实例。这个类有两个方法compare()和equals()方法。不一定要实现equals()方法,因为它间接的继承自Object的equals()方法。

Collections类包含一个reverseOrder()静态方法可以产生一个Comparator,它可以翻转自然的排序顺序。

String的排序算法依据词典编排顺序排序,所以大写字母开头的词都放在前面,然后是小写字母。如果想忽略大小写可以使用String.CASE_INSENSITIVE_ORDER比较器。

Java标准类库的排序算法对各种类型的正排序都进行了优化——针对基本类型设计的快速排序和针对对象设计的稳定归并排序。所以无需单行排序的性能。

如果数组已经排好顺序就可以使用Arrays.binarySearch()执行快速查找。如果要对未排序的数组使用binarySearch()将产生不可预料的结果(可能指没找到元素的返回情况)。如果找到了目标,Arrays.binarySearch()产生的返回值大于或等于0.否则产生负返回值,表示若要保持数组的排序状态此目标元素应该插入的位置。这个负值的计算方式的: -(插入点)-1。插入点指第一个大于查找对象的元素在数组中的位置,如果数组中所有的元素都小于查找的对象,插入点就等于数组的长度。如果数组包含重复的元素,则无法保证找到的是这些副本中的哪一个。

如果需要对没有重复元素的数组排序可以使用TreeSet(保持排序顺序),或者LinkedHashSet(保持插入顺序)。这些类会自动处理所有细节。除非他们成为程序性能的瓶颈,否则不需要自己维护数组。

如果使用Comparator排序了某个对象数组,在使用binarySearch()时必须提供同样的Comparator。

在编写练习25时我犯了一个错误,直接使用了Arrays.asList()方法得到的List并向其添加元素。这个方法得到的List是长度固定的,所以当调用它的add()方法时会抛出UnsupportOperateException。

作者在本章的总结中建议,当使用新版本的Java时,优选容器而不是数组。只有在已证明性能成为问题(并且切换到数组对性能提高有所帮助)时,才应该将程序重构为使用数组。

我手敲的本章例子代码和练习题代码在https://git.oschina.net/ivanjz93/ThinkingInJava-.git 的com.ctbri.arrays和com.ctbri.util包中。

© 著作权归作者所有

一万
粉丝 30
博文 102
码字总数 173386
作品 0
朝阳
程序员
私信 提问
加载中

评论(0)

Android--面试中遇到的问题总结(三)

《Android 开发工程师面试指南 LearningNotes 》,作者是陶程,由梁观全贡献部分。大家可以去知乎关注这两位用心的少年。这份指南包含了大部分Android开发的基础、进阶知识,不仅可以帮助准备...

sealin
2017/02/22
0
0
读书笔记之《Java并发编程的艺术》-并发编程容器和框架(重要)

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
805
1
《On Java 8》中文版,又名《Java 编程思想》中文第五版

来源:LingCoder/OnJava8 主译: LingCoder 参译: LortSir 校对:nickChenyx E-mail: lingcoder@gmail.com 本书原作者为 [美] Bruce Eckel,即(Thinking in Java 4th Edition,2006)的作者。......

ApacheCN_飞龙
2019/04/04
0
0
读书笔记之《Java并发编程的艺术》-并发编程基础

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
4.1K
8
读书笔记之《Java并发编程的艺术》-线程池和Executor的子孙们

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
815
1

没有更多内容

加载失败,请刷新页面

加载更多

0228 我的潘多拉

我的潘多拉 从一个故事说起。<br />从前,有个Java程序员非常喜欢写程序,喜欢研究源码,读英文文档。但是它在一家小公司里工作,公司的技术栈很陈旧。<br /> <br />单个系统代码中含有很多的...

李福春carter
今天
18
0
OSChina 周六乱弹 —— 屁会不会传染病毒

Osc乱弹歌单(2020)请戳(这里) 【今日歌曲】 @薛定谔的兄弟 :分享洛神有语创建的歌单「我喜欢的音乐」: 《ハレハレヤ(朗朗晴天)》- 猫瑾 手机党少年们想听歌,请使劲儿戳(这里) @空格...

小小编辑
今天
63
1
两个值得注意的问题

对成员变量的操作只能放在方法中,方法可以对成员变量和方法体中自己定义的局部 变量进行操作.在定义类的成员变量时可以同时赋予初值,如 class A { int a=12; float b=12.56f; } 但是不可以这...

咔啡
今天
27
0
第三章 分布式服务框架的选择

1.大项目工程且多人维护的弊端 (1)项目团队协同成本高,业务响应越来越慢 (2)应用复杂度已超出人的认知负载(向杂乱的电线一样) (3)错误难于隔离(一个模块出错,整个系统挂掉) (4...

zxx901221
今天
68
0
eclipse 上传jar到远程仓库

使用maven的项目中,有时需要把本地的项目打成jar包上传到mevan仓库。 操作如下: 前提:pom文件中配置好远程库的地址,否则会报错 一、将maven 中的settings文件配置好用户名和密码,如下:...

文文1
昨天
63
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部