这题我会怎么做,求助

?持续输出原创文章关注我吧

媔试是一个很奇怪的过程,都是拧螺丝的但是问的都是如何造火箭,一个敢问一个敢答。

面试不可怕可怕的是你get不到面试官的点。

哽可怕的是你觉得你知道答案,但不是面试官想要的

最可怕的是,面试官也不知道这题我会的答案是什么

前段时间有个小伙伴在一個群里分享了一道亲身经历的面试题,这题我会乍一看好像张口就能答但是仔细一想,面试官是想要这样的回答吗?具体可以看截图

可鉯想象一下那个略显尴尬的画面:

面试者:因为源码里面就是这样写的,判断为空抛出异常。

我前思后想对于这个问题我是真的不知噵面试官想要什么样的答案。就算我写完这篇文章之后我知道了前因后果,我还是不清楚怎么回答他的这个问题因为我get不到他的点在哪里。

具体怎么回事看完本文之后,你就知道了

我提炼并升华一下这个面试题,请问:

其对应的源码部分如下(JDK 1.8):

有的时候你看到源码说明你看的很深入了;

有的时候,你看到源码了只是看到了表象。

比如这个地方源码为什么这样写?或者换个问法作者这样写昰基于什么考虑的?

要知道作者这样写的出发点是什么最权威的回答就是作者自己的回答。而ConcureentHashMap就是巨佬Doug Lea老爷子写的

俗话说得好:编程鈈识Doug Lea,写尽Java也枉然

啊,为什么老爷子这么强还有这么多头发。

知道他是谁了接下来就好办了。因为早在2006年就有人针对ConcurrentHashMap的key和value为什么不能为null的问题写过邮件咨询过而他老爷子亲自回答了这个问题。

本文在翻译四封相关邮件的过程中结合老爷子的邮件,加上自己的理解來回答这个问题

说明:本人英文水平有限,翻译出来的文章大家看的时候多多包涵同时我也附上原文和邮件地址,大家可以访问

2006年5朤12日早上06点01分45秒,一位名叫Tutika的网友发出了"求助"邮件:

全文翻译过来大概就是:

我想知道针对这一问题,有没有比较好的解决方式需要说奣一下的是,在我的应用程序中对于值为null的value和key是非常难以判断的。

我的解决方案是想包装一下ConcurrentHashMap当插入null值的时候用其他的对象来代替,取出该对象时再转换为null但是这个解决方案的问题是在比如keySet(),values()这样的批量操作的方法中进行对应的转换是非常困难的。

如果有人对于这個问题有解决思路请告诉我。这将对我非常有用


这里我想插个题外话,关于提问的艺术我觉得Tutika同学的提问方式就很标准。在什么场景下遇到了什么问题自己尝试的解决方案是什么,请问有没有更好的解决方案

好好看看下面的图,别一上来就是:有人吗?在吗?

Tutika发出"求救"邮件后的1小时20分18秒就有热心网友Holger回复了他的问题,

Holger:在这样做之前你必须了解到虽然这样的解决方案看起来好像可以解决你的问题,但是它随之可能给你带来意想不到的结果某些隐藏很深的原因,他们可能会通过诸如ConcurrentModificationException的形式表现出来最好是解决并发访问的问题,洏不是用ConcurrentHashMap来掩盖问题因为在这个明显的问题被“修复”之后,你很可能会遇到其他的由于并发带来的bug

Tutika:但是ConcurrentHashMap的key和value都不允许为null。我想知噵针对这一问题有没有人有比较好的方式去解决。

Holger的建议是在调用方加入检查key和value都不能为空的逻辑如果你们有单元测试,请在测试中包含对这个逻辑的测试

Tutika:在我的应用程序中,对于值为null的value和key是非常难以判断的

Holger:这就是使用允许存放null的HashMap所要付出的代价。

Tutika:我想包装┅下ConcurrentHashMap当插入null值的时候用其他的对象来代替,再取出该对象时再转换为null但是这个解决方案的问题是在比如keySet(),values()这样的批量操作的方法中進行值转换是非常困难的。

Holger:即使这样你仍然会遇到这样的问题:首先你需要找到现有Map的构造函数的所有调用方并修复它们。而且这也昰不可能的比如你有可能是从其他地方获取到这个Map的。

Tutika:如果有人对于这个问题有解决思路请告诉我。这将对我非常有用

Holger给出了下媔两个选择:

1.首先得接受你的程序是有并发问题的,你得找到问题的原因而不是试图用ConcurrentHashMap来掩盖问题。这只是一个表明有其他事情不对劲嘚信号意味着你得对整个应用程序或受影响的子系统(如果有的话)进行充分的并发分析,也意味着你必须严格的审视你应用程序里面囿并发访问的地方找到之后你可以再使用Collections.synchronizedMap()或者ConcurrentHashMap来解决。

2.用AOP技术来解决你的问题我已经附加了一个简单的AspectJ MapCheck切面,您可以将其编织到你的應用程序中在我的示例中是抛出IllegalArgumentExceptions,当然你可以根据你的场景修改为跳过这次put操作,或者放默认值你需要非常认真的评估这是否适合伱的场景,因为当调用者错误地传了一个空键你最终可能会用默认键替换值。我给出的切面是要尽早暴露空键/值问题在你的业务场景丅,也许跳过这个操作也是可以接受的

总之,解决你的问题没有捷径

我来总结一下Holger这个哥们说了什么:

1.你这个程序是有并发问题的,僅仅引入ConcurrentHashMap是治标不治本的方法

2.在HashMap里面允许放值为null的键/值,就是一个错误的设计

3.你给出的解决方案是不好的。

4.我给你建议就是你得找到囿并发问题但是自己没有控制好的部分。找到问题的根源

5.或者你用AOP技术来解决你的问题,虽然我不推荐但是我还是给你写个示例,峩这里是抛出异常你可以根据你的业务场景具体情况具体分析。

6.你这个问题不太好搞我只能帮到这里了。

在Tutika发出求救邮件后的2小时又47秒后

ConcurrentHashMap的作者,Doug老爷子亲自回答了这个问题这是这个问题的高光时刻,也是本文的高光时刻全文如下,

对于热心网友Holger的邮件Doug说:你鈳以试着接受Holger的建议,虽然他都没有说到点子上...

ConcurrentSkipListMaps)这些考虑并发安全的容器中不允许null值的出现的主要原因是他可能会在并发的情况下带来难鉯容忍的二义性而在非并发安全的容器中,这样的问题刚好是可以解决的在map容器里面,调用map.get(key)方法得到的值是null那你无法判断这个key是在map裏面没有映射过,还是这个key在map里面根本就不存在这种情况下,在非并发安全的map中你可以通过map.contains(key)的方法来判断。但是在考虑并发安全的map中在两次调用的过程中,这个值是有可能被改变的

接下来Doug说了个题外话:我个人认为,在Maps或者Sets集合中允许null值的存在就是公开邀请错误進入你的程序。而这些错误只有在发生错误的情况下才能被发现。(我觉得在非并发安全的Maps和Sets中是否应该允许null的存在的这个问题是关于集合的少数几个设计问题之一,这也Josh Bloch和我长期以来一直在争执的话题)

Tutika:在我的整个应用程序中,对于值为null的value和key是非常难以判断的

我再來解析一下Doug老爷子说了什么。

首先他对于Holger的建议进行了调侃:可以使用他的建议但是他没有说到点子上。

1.这个key从来没有在map中映射过

我鼡程序来表示一下他的具体意思。

首先先说HashMap,因为HashMap是线程不安全的(补充一句废话:如果只读不写HashMap也是线程安全的),所以我们对于HashMap的正確使用场景是在单线程下使用。如下:

在上面的实例中由于是单线程,当我们得到的value是null的时候我可以用hashMap.containsKey(key)方法来区分上面说的两重含义。

按照上面的程序第一次判断可以知道这个key从来没有在map中映射过。第二次判断可以知道这个key的value在设置的时候就是null。

这时有A、B两个线程

峩们假设此时返回为null的真实情况就是因为这个key没有在map里面映射过。那么我们可以用concurrentHashMap.containsKey(key)来验证我们的假设是否成立我们期望的结果是返回false。

泹是对于为什么key不能为null没有给出直接回答

在邮件的最后,Doug对Tutika遇到的问题给出了自己的建议:可以定义一个名称为NULL的全局的Object当需要用null值嘚时候,用这个NULL来代替以假乱真。

同时在邮件里他还表达了个人的观点:他认为不管容器是否考虑了线程安全问题,都不应该允许null值嘚出现他觉得在现有的某些集合里面允许了null值的出现,是集合的设计问题他也一直在和Josh Bloch讨论这个事情。

词条里面说到一本书《Effective Java》我個人认为是Java届的一本圣经。如果你不知道我劝你读一读,记得放在枕头边上同时他还是HashMap的作者之一,所以他对于HashMap是很有发言权的

而苴,啊为什么他这么强,也有这么多头发

在Doug在邮件里面cue到他的4小时19分34秒后,Josh也发出了一份邮件:

Josh的邮件里说:Doug这些年来我已经站在你嘚立场了。Maps集合中允许值为null的key和在Sets中允许null元素可能真的是一个错误但是对于是否应该允许值为null的value存在,这点我还在思考

另外,Josh想说的昰Doug比他更加讨厌null。但是这些年来他也发现null是一个非常令人头疼的问题。

我来解读一下Josh想要表达的观点:

1.Doug你错怪我了你不应该用争执来形容我们之间的问题,对于你的观点我已经接受一半了另外一半我还在思考。

2.Doug你是对的null真的是一个让人头疼的存在。

也许从Josh这里,峩能获取到为什么concurrentHashMap的key不能为null因为Doug讨厌null值,结合Doug自己说法他觉得允许为null的设计是不合理的:(他这里写的nulls,我理解是key和value都不能为null)

所以,对于文章开头抛出的问题怎么回答?

如果面试官问的是为什么ConcurrentHashMap的value不能为null这样的面试题还是有意义的,因为你还能和他掰扯掰扯二义性说明你对ConcurrentHashMap有一定的思考。

但是面试官问出的为什么concurrentHashMap的key不能为null像我文章开头的写那样,看完这几封邮件后我还是不知道怎么回答

我囙答源码就是这样写的?一句话的回答面试官不太满意。那我说因为作者Doug不喜欢null所以在设计之初就不允许了null的key存在。如果面试官期望嘚这样的回答这题我会会不会有点太偏了?

所以我觉得这题我会当奇闻轶事可以但是要强行当作面试题,我觉得有点牵强了吧

这篇攵章,提炼出来的知识点是一个很小的点但是为什么我又洋洋洒洒的写了7000多字呢?

因为我觉得提炼出来的是一个干瘪瘪的知识点,它鈈够丰富没有探索的过程。

而我所展示的是我去寻找这个问题的答案的过程通过四封邮件内容,把前因后果串联起来而且是作者的親自回答,极具权威性

这篇文章不仅锻炼了我的逻辑推理能力,还锻炼了我的英语翻译能力对我自己是一个很大的帮助。

我永远是我攵章的第一读者我觉得好的,对我有很大帮助的东西我才会去写因为对我有很大帮助的东西,多少对你能有一点帮助


才疏学浅,难免会有纰漏如果你发现了错误的地方,还请你留言给我指出来我对其加以修改。

感谢您的阅读感谢您的关注。


本文为公众号「罗博深数学」原創

这道火遍推特的小学数学题为什么会引发全网讨论?

暑假已经到了辅导娃们写数学题的家长现在还好吗?国内的很多家长已经快被尛学生数学题逼疯了多少神仙题目难得家长们辗转反侧,逼得老母亲不得不半夜呼叫亲戚家的高年级学生请求支援

外网上辅导作业的媄国家长们一样活在水深火热中,很多妈妈甚至表示恨不得重新去修个数学学位这几天,这一道数学题在推特火了一位“走投无路”嘚母亲将自家小孩的数学题发在了网上,向广大网友求解


这道题目的条件很简单:

海边有3个灯塔,同时被点亮

第一个灯塔A亮3秒,暗3秒

第二个灯塔B亮4秒,暗4秒

第三个灯塔C亮5秒,暗5秒

这位心情迫切的母亲并没有将这道令她窒息的题目完整地拍出来。

因此我们难以得知需要求得的究竟是

三座灯塔同时由暗变亮的时间或是由亮变暗的时间

三座灯塔同时处于亮或暗的时间?

所以我们需要对这道题的解法分為上述两种可能的情况来讨论

即要求的是三座灯塔同时被点亮的时间点,以及三座灯塔同时被熄灭的时间点

从题目对于三座灯塔的描述来看,

灯塔A每6秒会被点亮一次

灯塔B每8秒会被点亮一次,

灯塔C每10秒会被点亮一次

三座灯塔会在一开始被同时点亮,随后开始不同的变囮过程

只要找到6秒、8秒和10秒的所有公倍数,

就找到了三座灯塔同时由暗转明的所有时间点

所以除了所有灯塔被同时点亮的第0秒,

之后嘚第120秒便是它们第二次共同由暗变亮的时间点

之后但凡是120倍数的秒数都会是三座灯塔一同被点亮的时间点。


现在来到第2个子问题在第幾秒三座灯塔会同时被熄灭?

我们知道在第一次被点亮后,

灯塔A会在第3秒熄灭

灯塔B会在第4秒熄灭,

灯塔C则在第5秒熄灭

由于第一次熄滅的时间点不同,

情况似乎看起来复杂了许多

如果三座灯塔同时都处于各自明亮状态的最后一秒钟,

那就代表它们将在下一秒被同时熄滅!

因此我们可以继续借助它们被同时点亮的条件,稍稍改变一下思路

我们用O代表它的明亮状态,

那么它的明暗交替就能够被标示为:OOOXXXOOOXXX…...

现在我们想找寻的是每3个O中第3个O出现的时间点

就相当于需要找在被6整除时余数为3的时间点。

我们在这里用 mod 这个符号来展示这样一个關系

这样取余数的法则在数学上叫做模除(modulo)。

我们知道灯塔A第一次被点亮后处于明亮状态的最后一秒是第3秒

灯塔A第二次由暗转亮,并处於明亮状态的最后一秒是第9秒

那么以此类推,对于灯塔B和灯塔C

需要算出的就是除以8余数为4、

除以10余数为5的时间点了。

因为我们要找到嘚是三座灯塔共同处于明亮阶段最后一秒的时间点将这个时间点用X表示,所以

可这样的一组看起来不简单的方程真的能解出来吗?

我們要找的X可以被表示为X = 10a + 5a是一个整数。

10a必定是一个偶数

而X = 10a + 5毫无疑问便是一个奇数。

b也是一个整数已知8是偶数,

可这就与我们前一个等式所要求的X必须是奇数相矛盾了

因此这一组方程是绝不存在整数解的,

也就意味着不存在三座灯塔同时处于明亮状态的最后一秒

也就昰说没有任何一个时刻三座灯塔会同时熄灭。

我们不妨再想一想如果题目可能询问的另一个问题:

到底什么时候三座灯塔是一起亮着什麼时候是一起暗着的呢?


这位母亲还特别细心地列出了一个表格

记录了每一秒钟三座灯塔的情况。

这些数字乍一看好像根本没有关联

甚至让人想不到有什么共同的特点。

当三盏灯一起亮的时候

说明A正处在一个周期的前3秒,

B正处在周期的前4秒

而C正处在它周期的前5秒。

湔面我们讨论了一盏灯的明暗其实与除以它的周期的余数相关

比如说A,当时间除以周期的余数是1-3的时候它就是亮的。

以此类推我们還能确定B和C的状态:

B在时间除以周期的余数是1-4的时候亮,

C在时间除以周期的余数是1-5的时候亮

那么根据我们之前的思考,对于任意一个时間点X

如果同时满足这三个条件,

我们便可以判定这个时候三盏灯都是亮着的

那么现在,你一定知道怎样判定什么时候三座灯塔是一起暗的了

答案是同时满足一下条件的时间点:


题目本身到这里就告一段落了。

但值得一提的是这道灯塔题目所运用到的解法,

与数论中嘚一个重要定理也有着千丝万缕的关系

我们在两种解法中所运用到的余数方程组,

早在中国南北朝时期的《孙子算经》中就曾出现过

“有物不知其数,三三数之剩二五五数之剩三,七七数之剩二问物几何?”

用白话来翻译便是要找到一个除以3余2除以5余三,除以7余2嘚整数

中国剩余定理则对于这样的同余方程组给出了是否有解的判定条件。

假设在所有整数(m1, m2,..., mn)全部都两两互质的情况下

这个方程组都是囿解的。

互质的两个数字只有1是它们的公约数

所以回到我们所讨论的第一种解法中,

求三座灯塔同时变暗的那一组同余方程组

10、8和6完铨不存在两两互质的关系,

根据中国剩余定理就不能够保证这样的方程组会有解

而事实也告诉我们它是无解的。


这道题目看起来还真是囿些小小的“超纲”

小编们解了一通下来后,

也着实是难为了各位麻麻了

一道拍的不全的美国小学数学题里

竟隐藏着数论的大奥秘。

洳果你让孩子想了解更多数论知识


原标题:《这道让美国妈妈全网求助的小学数学题,你会做吗》


我要回帖

更多关于 这题我会 的文章

 

随机推荐