面向对象的编程-Application 18

Previously on OOP:

In the last article, we have entered the Java Generics chapter. Generics is divided into two main categories: group and associative containers. And two examples were made regarding group containers. Specifically, TreeSet and LinkedList.

现在我们从group containers转移到associative containers,他们共同的父类是Map类,所以使用Map做为object reference的指针是非常合适的。下面,本黄鸭来举一个HashMap的例子:

不同于group containers中使用add()函数来添加数据,向associative containers中加入数据的时候,调用的是put()函数,而且需要两个参数:

(1)Key field的值。这个值必须是唯一的,比如每个中国公民具有唯一的身份证号码,那么身份证号码就能作为数据库的主键,或者是Map类的key field值。

(2)Value field的值,即存放的数据。还是用中国公民的例子,需要存放的数据是每个公民的所有信息,比如叫什么名字,找了什么工作,有没有结婚,等等。这些数据里面必然还会包括一项,就是身份证号码,虽然这里和key field产生了重复,但是这种重复是有意义的,能显著提高搜索的效率。

在本段代码中,我们的数据结构是HashMap,里面存放的数据类型是String类型。于此同时,还需要在声明语句中指明key field的数据的类型是Integer。尖括号中的Integer是一个wrapper class,那么能不能改成int呢?答案是不行,这是因为定义在库类中的Map就是这么规定的。

这里有一个值得记住的结论:

以某一个key值(不是key position)为参数,调用get()函数,能飞快地取得这个key值对应的value值,即存放在value field中的字符串类型的数据。在“m.get(1);”执行之后,取得的字符串应该是:Duck。

相对的,在LinkedList中调用get()函数,能够得到指定的位置的元素的值。

确定HashMap中有没有key的值是10,有两种方案:

(1)调用containsKey()函数。如果返回值是true,说明有key的值是10;反之,则没有。

(2)调用get()。如果返回值不是null,那么说明有key的值是10。这里还说明了一点,就是get()函数的返回值可能是空。最好在调用之后判定一下是不是为空,否则容易出现Exceptions。举一个例子:

在没有key的值是100的情况下,程序运行会中断,理由是出现了Exception,而且没有handler。

Map的遍历仍然可以使用for each statement,只是必须指定是遍历key field还是value field,是不能两个fields一起遍历的。本段代码中的“m.values()”遍历的是HashMap中的value field,里面存放的数据类型都是String类型的,所以临时变量v的类型也是String。

在HashMap中,数据的存放顺序是怎样的?答案是按照order of hash code来存放,即随机。要是换成TreeMap或者SortedMap,就会按照key的值从小到大存放。

下面,本黄鸭要再举一个例子来巩固一下group containers的学习成果。

print()函数比较特殊,首先因为它是一个static的函数。这种定义方式不是很推荐,但是不是不可以。其次,是因为“Collection”的写法。

如果把diamond brackets里面的问号换成“Object”,那么Objectis not agreeable with type Integer,所以cast在所难免。而问号表示的含义是:

使用问号的好处是可以避免cast,局限在于we are forbidden to modify the object。

If thebelow line of codewere possible,we can add any type of Object into objects, for example String, Integer, etc.

但是,这种编码方式is no more safeand barely possible。为什么基本不能实现呢?答案是Generics的性质type invariant,比如Collection and Collection是不同的,前者是后者子类这层关系,而且不能简单地前面加一个“(Collection)”来做类型转换。

Type invariant性质也同样解释了为什么print()中,“Collection”is not agreeable with typeCollection。总之,在本课程中要100%避开“Collection”。

欢迎使用本黄鸭编写的小程序~

微信公众号二维码:

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181018G1J9D100?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券