• 关于

    编码变换工作原理

    的搜索结果

回答

研究密码变化的客观规律,应用于编制密码以保守通信秘密的,称为编码学;应用于破译密码以获取通信情报的,称为破译学,密码学是研究编制密码和破译密码的技术科学。 密码是通信双方按约定的法则进行信息特殊变换的一种重要保密手段。密码学是在编码与破译的斗争实践中逐步发展起来的,并随着先进科学技术的应用,已成为一门综合性的尖端技术科学。它与语言学、数学、电子学、声学、信息论、计算机科学等有着广泛而密切的联系。 在西欧语文中之源於希腊语kryptós,“隐藏的”,和gráphein,“书写”)是研究如何隐密的传递信息的学科。在现代特别指对信息以及其传输的数学性研究,常被认为是数学和计算机科学的分支,和信息论也密切相关。著名的密码学者Ron Rivest解释道:「密码学是关於如何在敌人存在的环境中通讯」,自工程学的角度,这相当于密码学与纯数学的异同。密码学是 信息安全等相关议题,如认证、访问控制的核心。密码学的首要目是隐藏信息的涵义,并不是将隐藏信息的存在。密码学也促进了计算机科学,特别是在於电脑与网路安全所使用的技术,如访问控制与信息的机密性。密码学已被应用在日常生活:包括自动柜员机的芯片卡、电脑使用者存取密码、电子商务等等。 非对称加密算法的核心就是加密密钥不等于解密密钥,且无法从任意一个密钥推导出另一个密钥,这样就大大加强了信息保护的力度,而且基于密钥对的原理很容易的实现数字签名和电子信封。 比较典型的非对称加密算法是RSA算法,它的数学原理是大素数的分解,密钥是成对出现的,一个为公钥,一个是私钥。公钥是公开的,可以用私钥去解公钥加密过的信息,也可以用公钥去解私钥加密过的信息。 比如A向B发送信息,由于B的公钥是公开的,那么A用B的公钥对信息进行加密,发送出去,因为只有B有对应的私钥,所以信息只能为B所读取。 牢固的RSA算法需要其密钥长度为1024位,加解密的速度比较慢是它的弱点。 另外一种比较典型的非对称加密算法是ECC算法,基于的数学原理是椭圆曲线离散对数系统,这种算法的标准我国尚未确定,但是其只需要192 bit 就可以实现牢固的加密。所以,应该是优于RSA算法的。 对于加密,基本上不存在一个完全不可以被破解的加密算法,因为只要你有足够的时间,完全可以用穷举法来进行试探,如果说一个加密算法是牢固的,一般就是指在现有的计算条件下,需要花费相当长的时间才能够穷举成功(比如100年) RSA加密演算法是一种非对称加密演算法。在公钥加密标准和电子商业中RSA被广泛使用。RSA是1977年由罗纳德·李维斯特(Ron Rivest)、阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的。当时他们三人都在麻省理工学院工作。RSA就是他们三人姓氏开头字母拼在一起组成的。 1973年,在英国政府通讯总部工作的数学家克利福德·柯克斯(Clifford Cocks)在一个内部文件中提出了一个相应的算法,但他的发现被列入机密,一直到1997年未被发表。 RSA算法的可靠性基于分解极大的整数是很困难的。假如有人找到一种很快的分解因子的算法的话,那么用RSA加密的信息的可靠性就肯定会极度下降。但找到这样的算法的可能性是非常小的。今天只有短的RSA钥匙才可能被强力方式解破。到2004年为止,世界上还没有任何可靠的攻击RSA算法的方式。只要其钥匙的长度足够长,用RSA加密的信息实际上是不能被解破的。 更详细信息请进入维克百科快照http://203.208.33.101/search?q=cache:RSrtDijnQFcJ:zh.wikipedia.org/wiki/%E5%AF%86%E7%A0%81%E5%AD%A6+%E5%AF%86%E7%A0%81%E5%AD%A6&hl=zh-CN&ct=clnk&cd=3&gl=cn&client=aff-os-worldbrowser&st_usg=ALhdy2-pgUZXjYl-Mz_pl5gft4w9MJ94TQ 还有http://203.208.33.101/search?q=cache:LLAmzT7XnnYJ:zh.wikipedia.org/wiki/RSA%E5%8A%A0%E5%AF%86%E6%BC%94%E7%AE%97%E6%B3%95+RSA+1024%E4%BD%8D%E9%9D%9E%E5%AF%B9%E7%A7%B0%E5%AF%86%E9%92%A5&hl=zh-CN&newwindow=1&client=aff-os-worldbrowser&gl=cn&st_usg=ALhdy2-4cB1VU2Dtq1bXILD_m6EvFw9e5g&strip=1 后面这个链接断开了,要全部复制上去才打得开,直接点击打不开,BS CHN gov

晚来风急 2019-12-02 01:27:04 0 浏览量 回答数 0

回答

如果能时光倒流,回到过去,作为一个开发人员,你可以告诉自己在职业生涯初期应该读一本, 你会选择哪本书呢。我希望这个书单列表内容丰富,可以涵盖很多东西。” 1、《代码大全》 史蒂夫·迈克康奈尔 推荐数:1684 “优秀的编程实践的百科全书,《代码大全》注重个人技术,其中所有东西加起来, 就是我们本能所说的“编写整洁的代码”。这本书有50页在谈论代码布局。” —— Joel Spolsky 对于新手来说,这本书中的观念有点高阶了。到你准备阅读此书时,你应该已经知道并实践过书中99%的观念。– esac Steve McConnell的原作《代码大全》(第1版)是公认的关于编程的最佳实践指南之一, 在过去的十多年间,本书一直在帮助开发人员编写更好的软件。 现在,作者将这本经典著作全新演绎,融入了最前沿的实践技术,加入了上百个崭新的代码示例, 充分展示了软件构建的艺术性和科学性。 McConnell汇集了来自研究机构、学术界以及业界日常实践的主要知识, 把最高效的技术和最重要的原理交织融会为这本既清晰又实用的指南。 无论您的经验水平如何,也不管您在怎样的开发环境中工作,也无论项目是大是小, 本书都将激发您的思维并帮助您构建高品质的代码。 《代码大全(第2版))》做了全面的更新,增加了很多与时俱进的内容,包括对新语言、新的开发过程与方法论的讨论等等。 2、《程序员修炼之道》 推荐数:1504 对于那些已经学习过编程机制的程序员来说,这是一本卓越的书。 或许他们还是在校生,但对要自己做什么,还感觉不是很安全。 就像草图和架构之间的差别。虽然你在学校课堂上学到的是画图,你也可以画的很漂亮, 但如果你觉得你不太知道从哪儿下手,如果某人要你独自画一个P2P的音乐交换网络图,那这本书就适合你了。—— Joel 《程序员修炼之道:从小工到专家》内容简介:《程序员修炼之道》由一系列独立的部分组成, 涵盖的主题从个人责任、职业发展,知道用于使代码保持灵活、并且易于改编和复用的各种架构技术, 利用许多富有娱乐性的奇闻轶事、有思想性的例子及有趣的类比, 全面阐释了软件开发的许多不同方面的最佳实践和重大陷阱。 无论你是初学者,是有经验的程序员,还是软件项目经理,《程序员修炼之道:从小工到专家》都适合你阅读。 3、《计算机程序的构造和解释》 推荐数:916 就个人而言,这本书目前为止对我影响醉倒的一本编程书。 《代码大全》、《重构》和《设计模式》这些经典书会教给你高效的工作习惯和交易细节。 其他像《人件集》、《计算机编程心理学》和《人月神话》这些书会深入软件开发的心理层面。 其他书籍则处理算法。这些书都有自己所属的位置。 然而《计算机程序的构造和解释》与这些不同。 这是一本会启发你的书,它会燃起你编写出色程序的热情; 它还将教会你认识并欣赏美; 它会让你有种敬畏,让你难以抑制地渴望学习更多的东西。 其他书或许会让你成为一位更出色的程序员,但此书将一定会让你成为一名程序员。 同时,你将会学到其他东西,函数式编程(第三章)、惰性计算、元编程、虚拟机、解释器和编译器。 一些人认为此书不适合新手。 个人认为,虽然我并不完全认同要有一些编程经验才能读此书,但我还是一定推荐给初学者。 毕竟这本书是写给著名的6.001,是麻省理工学院的入门编程课程。 此书或许需要多做努力(尤其你在做练习的时候,你也应当如此),但这个价是对得起这本书的。 4、《C程序设计语言》 推荐数:774 这本书简洁易读,会教给你三件事:C 编程语言;如何像程序员一样思考;底层计算模型。 (这对理解“底层”非常重要)—— Nathan 《C程序设计语言》(第2版新版)讲述深入浅出,配合典型例证,通俗易懂,实用性强, 适合作为大专院校计算机专业或非计算机专业的C语言教材,也可以作为从事计算机相关软硬件开发的技术人员的参考书。 《C程序设计语言》(第2版新版)原著即为C语言的设计者之一Dennis M.Ritchie和著名的计算机科学家Brian W.Kernighan合著的 一本介绍C语言的权威经典著作。 我们现在见到的大量论述C语言程序设计的教材和专著均以此书为蓝本。 原著第1版中介绍的C语言成为后来广泛使用的C语言版本——标准C的基础。 人们熟知的“hello,world”程序就是由本书首次引入的,现在,这一程序已经成为所有程序设计语言入门的第一课。 5、《算法导论》 推荐数:671 《代码大全》教你如何正确编程; 《人月神话》教你如何正确管理; 《设计模式》教你如何正确设计…… 在我看来,代码只是一个工具,并非精髓。 开发软件的主要部分是创建新算法或重新实现现有算法。 其他部分则像重新组装乐高砖块或创建“管理”层。 我依然梦想这样的工作,我的大部分时间(>50%)是在写算法,其他“管理”细节则留给其他人…… —— Ran Biron 经典的算法书,被亚马逊网,《程序员》等评选为2006年最受读者喜爱的十大IT图书之一。 算法领域的标准教材,全球多所知名大学选用 MIT名师联手铸就,被誉为“计算机算法的圣经” 编写上采用了“五个一”,即一章介绍一个算法、一种设计技术、一个应用领域和一个相关话题。 6、《重构:改善既有代码的设计》 推荐数:617 《重构:改善既有代码的设计》清晰地揭示了重构的过程,解释了重构的原理和最佳实践方式, 并给出了何时以及何地应该开始挖掘代码以求改善。 书中给出了70多个可行的重构,每个重构都介绍了一种经过验证的代码变换手法的动机和技术。 《重构:改善既有代码的设计》提出的重构准则将帮助你一次一小步地修改你的代码,从而减少了开发过程中的风险。 《重构:改善既有代码的设计》适合软件开发人员、项目管理人员等阅读, 也可作为高等院校计算机及相关专业师生的参考读物。 我想我不得不推荐《重构》:改进现有代码的设计。—— Martin 我必须承认,我最喜欢的编程语录是出自这本书:任何一个傻瓜都能写出计算机能理解的程序, 而优秀的程序员却能写出别人能读得懂的程序。—— Martin Fowler 7、《设计模式》 推荐数:617 自1995年出版以来,本书一直名列Amazon和各大书店销售榜前列。 近10年后,本书仍是Addison-Wesley公司2003年最畅销的图书之一。 中文版销售逾4万册。 就我而言,我认为四人帮编著的《设计模式》是一本极为有用的书。 虽然此书并不像其他建议一样有关“元”编程,但它强调封装诸如模式一类的优秀编程技术, 因而鼓励其他人提出新模式和反模式(antipatterns),并运用于编程对话中。—— Chris Jester-Young 8、《人月神话》 推荐数:588 在软件领域,很少能有像《人月神话》一样具有深远影响力并且畅销不衰的著作。 Brooks博士为人们管理复杂项目提供了最具洞察力的见解。 既有很多发人深省的观点,又有大量软件工程的实践。 本书内容来自Brooks博士在IBM公司System/360家族和OS/360中的项目管理经验。 该书英文原版一经面世,即引起业内人士的强烈反响,后又译为德、法、日、俄中等多种语言,全球销量数百万册。 确立了其在行业内的经典地位。 9、《计算机程序设计艺术》 推荐数:542 《计算机程序设计艺术》系列著作对计算机领域产生了深远的影响。 这一系列堪称一项浩大的工程,自1962年开始编写,计划出版7卷,目前已经出版了4卷。 《美国科学家》杂志曾将这套书与爱因斯坦的《相对论》等书并列称为20世纪最重要的12本物理学著作。 目前Knuth正将毕生精力投入到这部史诗性著作的撰写中。 这是高德纳倾注心血写的一本书。—— Peter Coulton 10、《编译原理》(龙书) 推荐数:462 我很奇怪,居然没人提到龙书。(或许已有推荐,我没有看到)。 我从没忘过此书的第一版封面。 此书让我知道了编译器是多么地神奇绝妙。- DB 11、《深入浅出设计模式》 推荐数:445 强大的写作阵容。 《Head First设计模式》(中文版) 作者Eric Freeman; ElElisabeth Freeman是作家、讲师和技术顾问。 Eric拥有耶鲁大学的计算机科学博士学位,E1isabath拥有耶鲁大学的计算机科学硕士学位。 Kathy Sierra(javaranch.com的创始人)FHBert Bates是畅销的HeadFirst系列书籍的创立者,也是Sun公司Java开发员认证考试的开发者。 本书的产品设计应用神经生物学、认知科学,以及学习理论,这使得这本书能够将这些知识深深地印在你的脑海里, 不容易被遗忘。 本书的编写方式采用引导式教学,不直接告诉你该怎么做,而是利用故事当作引子,带领读者思考并想办法解决问题。 解决问题的过程中又会产生一些新的问题,再继续思考、继续解决问题,这样可以加深体会。 作者以大量的生活化故事当背景,例如第1章是鸭子,第2章是气象站,第3章是咖啡店, 书中搭配大量的插图(几乎每一页都有图),所以阅读起来生动有趣,不会感觉到昏昏欲睡。 作者还利用歪歪斜斜的手写字体,增加“现场感”。 精心设计许多爆笑的对白,让学习过程不会太枯燥。 还有模式告白节目,将设计模式拟人化成节目来宾,畅谈其内在的一切。 每一章都有数目不等的测验题。 每章最后有一页要点整理,这也是精华所在,我都是利用这一页做复习。 我知道四人帮的《设计模式》是一本标准书,但倒不如先看看这部大部头,此书更为简易。 一旦你了解了解了基本原则,可以去看四人帮的那本圣经了。- Calanus 12、《哥德尔、艾舍尔、巴赫书:集异璧之大成》 推荐数:437 如果下昂真正深入阅读,我推荐道格拉斯·侯世达(Douglas Hofstadter)的《哥德尔、艾舍尔、巴赫书》。 他极为深入研究了程序员每日都要面对的问题:递归、验证、证明和布尔代数。 这是一本很出色的读物,难度不大,偶尔有挑战,一旦你要鏖战到底,将是非常值得的。 – Jonik 13、《代码整洁之道》 推荐数:329 细节之中自有天地,整洁成就卓越代码 尽管糟糕的代码也能运行,但如果代码不整洁,会使整个开发团队泥足深陷, 写得不好的代码每年都要耗费难以计数的时间和资源。 然而这种情况并非无法避免。 著名软件专家RoberfC.Marlin在《代码整洁之道》中为你呈现出了革命性的视野。 Martin携同ObjectMetltor公司的同事,从他们有关整洁代码的最佳敏捷实践中提炼出软件技艺的价值观, 以飨读者,让你成为更优秀的程序员——只要你着手研读《代码整洁之道》。 阅读《代码整洁之道》需要你做些什么呢。你将阅读代码——大量代码。 《代码整洁之道》促使你思考代码中何谓正确,何谓错误。 更重要的是,《代码整洁之道》将促使你重新评估自己的专业价值观,以及对自己技艺的承诺。 从《代码整洁之道》中可以学到: 好代码和糟糕的代码之间的区别; 如何编写好代码,如何将糟糕的代码转化为好代码; 如何创建好名称、好函数、好对象和好类; 如何格式化代码以实现其可读性的最大化; 如何在不妨碍代码逻辑的前提下充分实现错误处理; 如何进行单元测试和测试驱动开发。 虽然《代码整洁之道》和《代码大全》有很多共同之处,但它有更为简洁更为实际的清晰例子。 – Craig P. Motlin 14、《Effective C++》和《More Effective C++》 推荐数:297 在我职业生涯早期,Scott Meyer的《Effective C++》和后续的《More Effective C++》都对我的编程能力有着直接影响。 正如当时的一位朋友所说,这些书缩短你培养编程技能的过程,而其他人可能要花费数年。 去年对我影响最大的一本书是《大教堂与市集》,该书教会我很有关开源开发过程如何运作,和如何处理我代码中的Bug。 – John Channing 15、《编程珠玑》 推荐数:282 多年以来,当程序员们推选出最心爱的计算机图书时,《编程珠玑》总是位列前列。 正如自然界里珍珠出自细沙对牡蛎的磨砺,计算机科学大师Jon Bentley以其独有的洞察力和创造力, 从磨砺程序员的实际问题中凝结出一篇篇不朽的编程“珠玑”, 成为世界计算机界名刊《ACM通讯》历史上最受欢迎的专栏, 最终结集为两部不朽的计算机科学经典名著,影响和激励着一代又一代程序员和计算机科学工作者。 本书为第一卷,主要讨论计算机科学中最本质的问题:如何正确选择和高效地实现算法。 尽管我不得不羞愧地承认,书中一半的东西我都没有理解,但我真的推荐《编程珠玑》,书中有些令人惊奇的东西。 – Matt Warren 16、《修改代码的艺术》by Michael Feathers 本书是继《重构》和《重构与模式》之后探讨修改代码技术的又一里程碑式的著作, 而且从涵盖面和深度上都超过了前两部经典。 书中不仅讲述面向对象语言(Java、C#和C++)代码,也有专章讨论C这样的过程式语言。 作者将理解、测试和修改代码的原理、技术和最新工具(自动化重构工具、单元测试框架、仿对象、集成测试框架等), 与解依赖技术和大量开发和设计优秀代码的原则、最佳实践相结合,许多内容非常深入,而且常常发前人所未发。 书中处处体现出作者独到的洞察力,以及多年开发和指导软件项目所积累的丰富经验和深厚功力。 通过这部集大成之作,你不仅能掌握最顶尖的修改代码技术,还可以大大提高对代码和软件开发的领悟力。 我认为没有任何一本书能向这本书一样影响了我的编程观点。 它明确地告诉你如何处理其他人的代码,含蓄地教会你避免哪些(以及为什么要避免)。- Wolfbyte 同意。很多开发人员讨论用干净的石板来编写软件。 但我想几乎所有开发人员的某些时候是在吃其他开发人员的狗食。– Bernard Dy 17、《编码:隐匿在计算机软硬件背后的语言》 这是一本讲述计算机工作原理的书。 不过,你千万不要因为“工作原理”之类的字眼就武断地认为,它是晦涩而难懂的。 作者用丰富的想象和清晰的笔墨将看似繁杂的理论阐述得通俗易懂,你丝毫不会感到枯燥和生硬。 更重要的是,你会因此而获得对计算机工作原理较深刻的理解。 这种理解不是抽象层面上的,而是具有一定深度的,这种深度甚至不逊于“电气工程师”和“程序员”的理解。 不管你是计算机高手,还是对这个神奇的机器充满敬畏之心的菜鸟, 都不妨翻阅一下《编码:隐匿在计算机软硬件背后的语言》,读一读大师的经典作品,必然会有收获。 我推荐Charles Petzold的《编码》。 在这个充满工具和IDE的年代,很多复杂度已经从程序员那“抽取”走了,这本书一本开眼之作。 – hemil 18、《禅与摩托车维修艺术 / Zen and the Art of Motorcycle Maintenance》 对我影响最大的那本书是 Robert Pirsig 的《禅与摩托车维修艺术》。 不管你做什么事,总是要力求完美,彻底了解你手中的工具和任务,更为重要的是, 要有乐趣(因为如果你做事有乐趣,一切将自发引向更好的结果)。 – akr 19、《Peopleware / 人件集:人性化的软件开发》 Demarco 和 Lister 表明,软件开发中的首要问题是人,并非技术。 他们的答案并不简单,只是令人难以置信的成功。 第二版新增加了八章内容。 – Eduardo Molteni 20、《Coders at Work / 编程人生》 这是一本访谈笔录,记录了当今最具个人魅力的15位软件先驱的编程生涯。 包括DonaldKnuth、Jamie Zawinski、Joshua Bloch、Ken Thompson等在内的业界传奇人物,为我们讲述了 他们是怎么学习编程的,在编程过程中发现了什么以及他们对未来的看法, 并对诸如应该如何设计软件等长久以来一直困扰很多程序员的问题谈了自己的观点。 一本非常有影响力的书,可以从中学到一些业界顶级人士的经验,了解他们如何思考并工作。 – Jahanzeb Farooq 21、《Surely You’re Joking, Mr. Feynman! / 别闹了,费曼先生。》 虽然这本书可能有点偏题,但不管你信不信,这本书曾在计算机科学专业课程的阅读列表之上。 一个优秀的角色模型,一本有关好奇心的优秀书籍。 – mike511 22、《Effective Java 中文版》 此书第二版教你如何编写漂亮并高效的代码,虽然这是一本Java书,但其中有很多跨语言的理念。 – Marcio Aguiar 23、《Patterns of Enterprise Application Architecture / 企业应用架构模式》 很奇怪,还没人推荐 Martin Fowler 的《企业应用架构模式》- levi rosol 24、《The Little Schemer》和《The Seasoned Schemer》 nmiranda 这两本是LISP的英文书,尚无中文版。 美国东北大学网站上也有电子版。 25、《交互设计之路》英文名:《The Inmates Are Running The Asylum: Why High Tech Products Drive Us Crazy and How to Restore the Sanity》该书作者:Alan Cooper,人称Visual Basic之父,交互设计之父。 本书是基于众多商务案例,讲述如何创建更好的、高客户忠诚度的软件产品和基于软件的高科技产品的书。 本书列举了很多真实可信的实际例子,说明目前在软件产品和基于软件的高科技产品中,普遍存在着“难用”的问题。 作者认为,“难用”问题是由这些产品中存在着的高度“认知摩擦”引起的, 而产生这个问题的根源在于现今软件开发过程中欠缺了一个为用户利益着想的前期“交互设计”阶段。 “难用”的产品不仅损害了用户的利益,最终也将导致企业的失败。 本书通过一些生动的实例,让人信服地讲述了由作者倡导的“目标导向”交互设计方法在解决“难用”问题方面的有效性, 证实了只有改变现有观念,才能有效地在开发过程中引入交互设计,将产品的设计引向成功。 本书虽然是一本面向商务人员而编写的书,但也适合于所有参与软件产品和基于软件的高科技产品开发的专业人士, 以及关心软件行业和高科技行业现状与发展的人士阅读。 他还有另一本中文版著作:《About Face 3 交互设计精髓》 26、《Why’s (Poignant) Guide to Ruby 》 如果你不是程序员,阅读此书可能会很有趣,但如果你已经是个程序员,可能会有点乏味。 27、《Unix编程艺术》 It is useful regardless operating system you use. – J.F. Sebastian 不管你使用什么操作系统,这本书都很有用。 – J.F. Sebastian 28、《高效程序员的45个习惯:敏捷开发修炼之道》 45个习惯,分为7个方面:工作态度、学习、软件交付、反馈、编码、调试和协作。 每一个具体的习惯里,一开始提出一个谬论,然后展开分析,之后有正队性地提出正确的做法,并设身处地地讲出了正确做法给你个人的“切身感受”,最后列出几条注意事项,帮助你修正自己的做法(“平衡的艺术”)。 29、《测试驱动开发》 前面已经提到的很多书都启发了我,并影响了我,但这本书每位程序员都应该读。 它向我展示了单元测试和TDD的重要性,并让我很快上手。 – Curro 我不关心你的代码有多好或优雅。 如果你没有测试,你或许就如同没有编写代码。 这本书得到的推荐数应该更高些。 人们讨论编写用户喜欢的软件,或既设计出色并健壮的高效代码,但如果你的软件有一堆bug,谈论那些东西毫无意义。– Adam Gent 30、《点石成金:访客至上的网页设计秘笈》 可用性设计是Web设计中最重要也是难度最大的一项任务。 《点石成金-访客至上的网页设计秘笈(原书第二版)》作者根据多年从业的经验,剖析用户的心理, 在用户使用的模式、为扫描进行设计、导航设计、主页布局、可用性测试等方面提出了许多独特的观点, 并给出了大量简单、易行的可用性设计的建议。 本书短小精炼,语言轻松诙谐,书中穿插大量色彩丰富的屏幕截图、趣味丛生的卡通插图以及包含大量信息的图表, 使枯燥的设计原理变得平易近人。 本书适合从事Web设计和Web开发的技术人员阅读,特别适合为如何留住访问者而苦恼的网站/网页设计人员阅读。 这是一本关于Web设计原则而不是Web设计技术的书。 本书作者是Web设计专家,具有丰富的实践经验。 他用幽默的语言为你揭示Web设计中重要但却容易被忽视的问题,只需几个小时, 你便能对照书中讲授的设计原则找到网站设计的症结所在,令你的网站焕然一新。

青衫无名 2019-12-02 01:20:04 0 浏览量 回答数 0

回答

一、算法工程师简介 (通常是月薪15k以上,年薪18万以上,只是一个概数,具体薪资可以到招聘网站如拉钩,猎聘网上看看) 算法工程师目前是一个高端也是相对紧缺的职位; 算法工程师包括 音/视频算法工程师(通常统称为语音/视频/图形开发工程师)、图像处理算法工程师、计算机视觉算法工程师、通信基带算法工程师、信号算法工程师、射频/通信算法工程师、自然语言算法工程师、数据挖掘算法工程师、搜索算法工程师、控制算法工程师(云台算法工程师,飞控算法工程师,机器人控制算法)、导航算法工程师( @之介 感谢补充)、其他【其他一切需要复杂算法的行业】 专业要求:计算机、电子、通信、数学等相关专业; 学历要求:本科及其以上的学历,大多数是硕士学历及其以上; 语言要求:英语要求是熟练,基本上能阅读国外专业书刊,做这一行经常要读论文; 必须掌握计算机相关知识,熟练使用仿真工具MATLAB等,必须会一门编程语言。 算法工程师的技能树(不同方向差异较大,此处仅供参考) 1 机器学习 2 大数据处理:熟悉至少一个分布式计算框架Hadoop/Spark/Storm/ map-reduce/MPI 3 数据挖掘 4 扎实的数学功底 5 至少熟悉C/C++或者Java,熟悉至少一门编程语言例如java/python/R 加分项:具有较为丰富的项目实践经验(不是水论文的哪种) 二、算法工程师大致分类与技术要求 (一)图像算法/计算机视觉工程师类 包括 图像算法工程师,图像处理工程师,音/视频处理算法工程师,计算机视觉工程师 要求 l 专业:计算机、数学、统计学相关专业; l 技术领域:机器学习,模式识别 l 技术要求: (1) 精通DirectX HLSL和OpenGL GLSL等shader语言,熟悉常见图像处理算法GPU实现及优化; (2) 语言:精通C/C++; (3) 工具:Matlab数学软件,CUDA运算平台,VTK图像图形开源软件【医学领域:ITK,医学图像处理软件包】 (4) 熟悉OpenCV/OpenGL/Caffe等常用开源库; (5) 有人脸识别,行人检测,视频分析,三维建模,动态跟踪,车识别,目标检测跟踪识别经历的人优先考虑; (6) 熟悉基于GPU的算法设计与优化和并行优化经验者优先; (7) 【音/视频领域】熟悉H.264等视频编解码标准和FFMPEG,熟悉rtmp等流媒体传输协议,熟悉视频和音频解码算法,研究各种多媒体文件格式,GPU加速; 应用领域: (1) 互联网:如美颜app (2) 医学领域:如临床医学图像 (3) 汽车领域 (4) 人工智能 相关术语: (1) OCR:OCR (Optical Character Recognition,光学字符识别)是指电子设备(例如扫描仪或数码相机)检查纸上打印的字符,通过检测暗、亮的模式确定其形状,然后用字符识别方法将形状翻译成计算机文字的过程 (2) Matlab:商业数学软件; (3) CUDA: (Compute Unified Device Architecture),是显卡厂商NVIDIA推出的运算平台(由ISA和GPU构成)。 CUDA™是一种由NVIDIA推出的通用并行计算架构,该架构使GPU能够解决复杂的计算问题 (4) OpenCL: OpenCL是一个为异构平台编写程序的框架,此异构平台可由CPU,GPU或其他类型的处理器组成。 (5) OpenCV:开源计算机视觉库;OpenGL:开源图形库;Caffe:是一个清晰,可读性高,快速的深度学习框架。 (6) CNN:(深度学习)卷积神经网络(Convolutional Neural Network)CNN主要用来识别位移、缩放及其他形式扭曲不变性的二维图形。 (7) 开源库:指的是计算机行业中对所有人开发的代码库,所有人均可以使用并改进代码算法。 (二)机器学习工程师 包括 机器学习工程师 要求 l 专业:计算机、数学、统计学相关专业; l 技术领域:人工智能,机器学习 l 技术要求: (1) 熟悉Hadoop/Hive以及Map-Reduce计算模式,熟悉Spark、Shark等尤佳; (2) 大数据挖掘; (3) 高性能、高并发的机器学习、数据挖掘方法及架构的研发; 应用领域: (1)人工智能,比如各类仿真、拟人应用,如机器人 (2)医疗用于各类拟合预测 (3)金融高频交易 (4)互联网数据挖掘、关联推荐 (5)无人汽车,无人机 相关术语: (1) Map-Reduce:MapReduce是一种编程模型,用于大规模数据集(大于1TB)的并行运算。概念"Map(映射)"和"Reduce(归约)",是它们的主要思想,都是从函数式编程语言里借来的,还有从矢量编程语言里借来的特性。 (三)自然语言处理工程师 包括 自然语言处理工程师 要求 l 专业:计算机相关专业; l 技术领域:文本数据库 l 技术要求: (1) 熟悉中文分词标注、文本分类、语言模型、实体识别、知识图谱抽取和推理、问答系统设计、深度问答等NLP 相关算法; (2) 应用NLP、机器学习等技术解决海量UGC的文本相关性; (3) 分词、词性分析、实体识别、新词发现、语义关联等NLP基础性研究与开发; (4) 人工智能,分布式处理Hadoop; (5) 数据结构和算法; 应用领域: 口语输入、书面语输入 、语言分析和理解、语言生成、口语输出技术、话语分析与对话、文献自动处理、多语问题的计算机处理、多模态的计算机处理、信息传输与信息存储 、自然语言处理中的数学方法、语言资源、自然语言处理系统的评测。 相关术语: (2) NLP:人工智能的自然语言处理,NLP (Natural Language Processing) 是人工智能(AI)的一个子领域。NLP涉及领域很多,最令我感兴趣的是“中文自动分词”(Chinese word segmentation):结婚的和尚未结婚的【计算机中却有可能理解为结婚的“和尚“】 (四)射频/通信/信号算法工程师类 包括 3G/4G无线通信算法工程师, 通信基带算法工程师,DSP开发工程师(数字信号处理),射频通信工程师,信号算法工程师 要求 l 专业:计算机、通信相关专业; l 技术领域:2G、3G、4G,BlueTooth(蓝牙),WLAN,无线移动通信, 网络通信基带信号处理 l 技术要求: (1) 了解2G,3G,4G,BlueTooth,WLAN等无线通信相关知识,熟悉现有的通信系统和标准协议,熟悉常用的无线测试设备; (2) 信号处理技术,通信算法; (3) 熟悉同步、均衡、信道译码等算法的基本原理; (4) 【射频部分】熟悉射频前端芯片,扎实的射频微波理论和测试经验,熟练使用射频电路仿真工具(如ADS或MW或Ansoft);熟练使用cadence、altium designer PCB电路设计软件; (5) 有扎实的数学基础,如复变函数、随机过程、数值计算、矩阵论、离散数学 应用领域: 通信 VR【用于快速传输视频图像,例如乐客灵境VR公司招募的通信工程师(数据编码、流数据)】 物联网,车联网 导航,军事,卫星,雷达 相关术语: (1) 基带信号:指的是没有经过调制(进行频谱搬移和变换)的原始电信号。 (2) 基带通信(又称基带传输):指传输基带信号。进行基带传输的系统称为基带传输系统。传输介质的整个信道被一个基带信号占用.基带传输不需要调制解调器,设备化费小,具有速率高和误码率低等优点,.适合短距离的数据传输,传输距离在100米内,在音频市话、计算机网络通信中被广泛采用。如从计算机到监视器、打印机等外设的信号就是基带传输的。大多数的局域网使用基带传输,如以太网、令牌环网。 (3) 射频:射频(RF)是Radio Frequency的缩写,表示可以辐射到空间的电磁频率(电磁波),频率范围从300KHz~300GHz之间(因为其较高的频率使其具有远距离传输能力)。射频简称RF射频就是射频电流,它是一种高频交流变化电磁波的简称。每秒变化小于1000次的交流电称为低频电流,大于10000次的称为高频电流,而射频就是这样一种高频电流。高频(大于10K);射频(300K-300G)是高频的较高频段;微波频段(300M-300G)又是射频的较高频段。【有线电视就是用射频传输方式】 (4) DSP:数字信号处理,也指数字信号处理芯片 (五)数据挖掘算法工程师类 包括 推荐算法工程师,数据挖掘算法工程师 要求 l 专业:计算机、通信、应用数学、金融数学、模式识别、人工智能; l 技术领域:机器学习,数据挖掘 l 技术要求: (1) 熟悉常用机器学习和数据挖掘算法,包括但不限于决策树、Kmeans、SVM、线性回归、逻辑回归以及神经网络等算法; (2) 熟练使用SQL、Matlab、Python等工具优先; (3) 对Hadoop、Spark、Storm等大规模数据存储与运算平台有实践经验【均为分布式计算框架】 (4) 数学基础要好,如高数,统计学,数据结构 l 加分项:数据挖掘建模大赛; 应用领域 (1) 个性化推荐 (2) 广告投放 (3) 大数据分析 相关术语 Map-Reduce:MapReduce是一种编程模型,用于大规模数据集(大于1TB)的并行运算。概念"Map(映射)"和"Reduce(归约)",是它们的主要思想,都是从函数式编程语言里借来的,还有从矢量编程语言里借来的特性。 (六)搜索算法工程师 要求 l 技术领域:自然语言 l 技术要求: (1) 数据结构,海量数据处理、高性能计算、大规模分布式系统开发 (2) hadoop、lucene (3) 精通Lucene/Solr/Elastic Search等技术,并有二次开发经验 (4) 精通Lucene/Solr/Elastic Search等技术,并有二次开发经验; (5) 精通倒排索引、全文检索、分词、排序等相关技术; (6) 熟悉Java,熟悉Spring、MyBatis、Netty等主流框架; (7) 优秀的数据库设计和优化能力,精通MySQL数据库应用 ; (8) 了解推荐引擎和数据挖掘和机器学习的理论知识,有大型搜索应用的开发经验者优先。 (七)控制算法工程师类 包括了云台控制算法,飞控控制算法,机器人控制算法 要求 l 专业:计算机,电子信息工程,航天航空,自动化 l 技术要求: (1) 精通自动控制原理(如PID)、现代控制理论,精通组合导航原理,姿态融合算法,电机驱动,电机驱动 (2) 卡尔曼滤波,熟悉状态空间分析法对控制系统进行数学模型建模、分析调试; l 加分项:有电子设计大赛,机器人比赛,robocon等比赛经验,有硬件设计的基础; 应用领域 (1)医疗/工业机械设备 (2)工业机器人 (3)机器人 (4)无人机飞控、云台控制等 (八)导航算法工程师 要求 l 专业:计算机,电子信息工程,航天航空,自动化 l 技术要求(以公司职位JD为例) 公司一(1)精通惯性导航、激光导航、雷达导航等工作原理; (2)精通组合导航算法设计、精通卡尔曼滤波算法、精通路径规划算法; (3)具备导航方案设计和实现的工程经验; (4)熟悉C/C++语言、熟悉至少一种嵌入式系统开发、熟悉Matlab工具; 公司二(1)熟悉基于视觉信息的SLAM、定位、导航算法,有1年以上相关的科研或项目经历; (2)熟悉惯性导航算法,熟悉IMU与视觉信息的融合; 应用领域 无人机、机器人等。

小哇 2019-12-02 01:21:12 0 浏览量 回答数 0

阿里云试用中心,为您提供0门槛上云实践机会!

0元试用32+款产品,最高免费12个月!拨打95187-1,咨询专业上云建议!

回答

一、算法工程师简介 (通常是月薪15k以上,年薪18万以上,只是一个概数,具体薪资可以到招聘网站如拉钩,猎聘网上看看) 算法工程师目前是一个高端也是相对紧缺的职位; 算法工程师包括 音/视频算法工程师(通常统称为语音/视频/图形开发工程师)、图像处理算法工程师、计算机视觉算法工程师、通信基带算法工程师、信号算法工程师、射频/通信算法工程师、自然语言算法工程师、数据挖掘算法工程师、搜索算法工程师、控制算法工程师(云台算法工程师,飞控算法工程师,机器人控制算法)、导航算法工程师( @之介 感谢补充)、其他【其他一切需要复杂算法的行业】 专业要求:计算机、电子、通信、数学等相关专业; 学历要求:本科及其以上的学历,大多数是硕士学历及其以上; 语言要求:英语要求是熟练,基本上能阅读国外专业书刊,做这一行经常要读论文; 必须掌握计算机相关知识,熟练使用仿真工具MATLAB等,必须会一门编程语言。 算法工程师的技能树(不同方向差异较大,此处仅供参考) 1 机器学习 2 大数据处理:熟悉至少一个分布式计算框架Hadoop/Spark/Storm/ map-reduce/MPI 3 数据挖掘 4 扎实的数学功底 5 至少熟悉C/C++或者Java,熟悉至少一门编程语言例如java/python/R 加分项:具有较为丰富的项目实践经验(不是水论文的哪种) 二、算法工程师大致分类与技术要求 (一)图像算法/计算机视觉工程师类 包括 图像算法工程师,图像处理工程师,音/视频处理算法工程师,计算机视觉工程师 要求 l 专业:计算机、数学、统计学相关专业; l 技术领域:机器学习,模式识别 l 技术要求: (1) 精通DirectX HLSL和OpenGL GLSL等shader语言,熟悉常见图像处理算法GPU实现及优化; (2) 语言:精通C/C++; (3) 工具:Matlab数学软件,CUDA运算平台,VTK图像图形开源软件【医学领域:ITK,医学图像处理软件包】 (4) 熟悉OpenCV/OpenGL/Caffe等常用开源库; (5) 有人脸识别,行人检测,视频分析,三维建模,动态跟踪,车识别,目标检测跟踪识别经历的人优先考虑; (6) 熟悉基于GPU的算法设计与优化和并行优化经验者优先; (7) 【音/视频领域】熟悉H.264等视频编解码标准和FFMPEG,熟悉rtmp等流媒体传输协议,熟悉视频和音频解码算法,研究各种多媒体文件格式,GPU加速; 应用领域: (1) 互联网:如美颜app (2) 医学领域:如临床医学图像 (3) 汽车领域 (4) 人工智能 相关术语: (1) OCR:OCR (Optical Character Recognition,光学字符识别)是指电子设备(例如扫描仪或数码相机)检查纸上打印的字符,通过检测暗、亮的模式确定其形状,然后用字符识别方法将形状翻译成计算机文字的过程 (2) Matlab:商业数学软件; (3) CUDA: (Compute Unified Device Architecture),是显卡厂商NVIDIA推出的运算平台(由ISA和GPU构成)。 CUDA™是一种由NVIDIA推出的通用并行计算架构,该架构使GPU能够解决复杂的计算问题 (4) OpenCL: OpenCL是一个为异构平台编写程序的框架,此异构平台可由CPU,GPU或其他类型的处理器组成。 (5) OpenCV:开源计算机视觉库;OpenGL:开源图形库;Caffe:是一个清晰,可读性高,快速的深度学习框架。 (6) CNN:(深度学习)卷积神经网络(Convolutional Neural Network)CNN主要用来识别位移、缩放及其他形式扭曲不变性的二维图形。 (7) 开源库:指的是计算机行业中对所有人开发的代码库,所有人均可以使用并改进代码算法。 (二)机器学习工程师 包括 机器学习工程师 要求 l 专业:计算机、数学、统计学相关专业; l 技术领域:人工智能,机器学习 l 技术要求: (1) 熟悉Hadoop/Hive以及Map-Reduce计算模式,熟悉Spark、Shark等尤佳; (2) 大数据挖掘; (3) 高性能、高并发的机器学习、数据挖掘方法及架构的研发; 应用领域: (1)人工智能,比如各类仿真、拟人应用,如机器人 (2)医疗用于各类拟合预测 (3)金融高频交易 (4)互联网数据挖掘、关联推荐 (5)无人汽车,无人机 相关术语: (1) Map-Reduce:MapReduce是一种编程模型,用于大规模数据集(大于1TB)的并行运算。概念"Map(映射)"和"Reduce(归约)",是它们的主要思想,都是从函数式编程语言里借来的,还有从矢量编程语言里借来的特性。 (三)自然语言处理工程师 包括 自然语言处理工程师 要求 l 专业:计算机相关专业; l 技术领域:文本数据库 l 技术要求: (1) 熟悉中文分词标注、文本分类、语言模型、实体识别、知识图谱抽取和推理、问答系统设计、深度问答等NLP 相关算法; (2) 应用NLP、机器学习等技术解决海量UGC的文本相关性; (3) 分词、词性分析、实体识别、新词发现、语义关联等NLP基础性研究与开发; (4) 人工智能,分布式处理Hadoop; (5) 数据结构和算法; 应用领域: 口语输入、书面语输入 、语言分析和理解、语言生成、口语输出技术、话语分析与对话、文献自动处理、多语问题的计算机处理、多模态的计算机处理、信息传输与信息存储 、自然语言处理中的数学方法、语言资源、自然语言处理系统的评测。 相关术语: (2) NLP:人工智能的自然语言处理,NLP (Natural Language Processing) 是人工智能(AI)的一个子领域。NLP涉及领域很多,最令我感兴趣的是“中文自动分词”(Chinese word segmentation):结婚的和尚未结婚的【计算机中却有可能理解为结婚的“和尚“】 (四)射频/通信/信号算法工程师类 包括 3G/4G无线通信算法工程师, 通信基带算法工程师,DSP开发工程师(数字信号处理),射频通信工程师,信号算法工程师 要求 l 专业:计算机、通信相关专业; l 技术领域:2G、3G、4G,BlueTooth(蓝牙),WLAN,无线移动通信, 网络通信基带信号处理 l 技术要求: (1) 了解2G,3G,4G,BlueTooth,WLAN等无线通信相关知识,熟悉现有的通信系统和标准协议,熟悉常用的无线测试设备; (2) 信号处理技术,通信算法; (3) 熟悉同步、均衡、信道译码等算法的基本原理; (4) 【射频部分】熟悉射频前端芯片,扎实的射频微波理论和测试经验,熟练使用射频电路仿真工具(如ADS或MW或Ansoft);熟练使用cadence、altium designer PCB电路设计软件; (5) 有扎实的数学基础,如复变函数、随机过程、数值计算、矩阵论、离散数学 应用领域: 通信 VR【用于快速传输视频图像,例如乐客灵境VR公司招募的通信工程师(数据编码、流数据)】 物联网,车联网 导航,军事,卫星,雷达 相关术语: (1) 基带信号:指的是没有经过调制(进行频谱搬移和变换)的原始电信号。 (2) 基带通信(又称基带传输):指传输基带信号。进行基带传输的系统称为基带传输系统。传输介质的整个信道被一个基带信号占用.基带传输不需要调制解调器,设备化费小,具有速率高和误码率低等优点,.适合短距离的数据传输,传输距离在100米内,在音频市话、计算机网络通信中被广泛采用。如从计算机到监视器、打印机等外设的信号就是基带传输的。大多数的局域网使用基带传输,如以太网、令牌环网。 (3) 射频:射频(RF)是Radio Frequency的缩写,表示可以辐射到空间的电磁频率(电磁波),频率范围从300KHz~300GHz之间(因为其较高的频率使其具有远距离传输能力)。射频简称RF射频就是射频电流,它是一种高频交流变化电磁波的简称。每秒变化小于1000次的交流电称为低频电流,大于10000次的称为高频电流,而射频就是这样一种高频电流。高频(大于10K);射频(300K-300G)是高频的较高频段;微波频段(300M-300G)又是射频的较高频段。【有线电视就是用射频传输方式】 (4) DSP:数字信号处理,也指数字信号处理芯片 (五)数据挖掘算法工程师类 包括 推荐算法工程师,数据挖掘算法工程师 要求 l 专业:计算机、通信、应用数学、金融数学、模式识别、人工智能; l 技术领域:机器学习,数据挖掘 l 技术要求: (1) 熟悉常用机器学习和数据挖掘算法,包括但不限于决策树、Kmeans、SVM、线性回归、逻辑回归以及神经网络等算法; (2) 熟练使用SQL、Matlab、Python等工具优先; (3) 对Hadoop、Spark、Storm等大规模数据存储与运算平台有实践经验【均为分布式计算框架】 (4) 数学基础要好,如高数,统计学,数据结构 l 加分项:数据挖掘建模大赛; 应用领域 (1) 个性化推荐 (2) 广告投放 (3) 大数据分析 相关术语 Map-Reduce:MapReduce是一种编程模型,用于大规模数据集(大于1TB)的并行运算。概念"Map(映射)"和"Reduce(归约)",是它们的主要思想,都是从函数式编程语言里借来的,还有从矢量编程语言里借来的特性。 (六)搜索算法工程师 要求 l 技术领域:自然语言 l 技术要求: (1) 数据结构,海量数据处理、高性能计算、大规模分布式系统开发 (2) hadoop、lucene (3) 精通Lucene/Solr/Elastic Search等技术,并有二次开发经验 (4) 精通Lucene/Solr/Elastic Search等技术,并有二次开发经验; (5) 精通倒排索引、全文检索、分词、排序等相关技术; (6) 熟悉Java,熟悉Spring、MyBatis、Netty等主流框架; (7) 优秀的数据库设计和优化能力,精通MySQL数据库应用 ; (8) 了解推荐引擎和数据挖掘和机器学习的理论知识,有大型搜索应用的开发经验者优先。 (七)控制算法工程师类 包括了云台控制算法,飞控控制算法,机器人控制算法 要求 l 专业:计算机,电子信息工程,航天航空,自动化 l 技术要求: (1) 精通自动控制原理(如PID)、现代控制理论,精通组合导航原理,姿态融合算法,电机驱动,电机驱动 (2) 卡尔曼滤波,熟悉状态空间分析法对控制系统进行数学模型建模、分析调试; l 加分项:有电子设计大赛,机器人比赛,robocon等比赛经验,有硬件设计的基础; 应用领域 (1)医疗/工业机械设备 (2)工业机器人 (3)机器人 (4)无人机飞控、云台控制等 (八)导航算法工程师 要求 l 专业:计算机,电子信息工程,航天航空,自动化 l 技术要求(以公司职位JD为例) 公司一(1)精通惯性导航、激光导航、雷达导航等工作原理; (2)精通组合导航算法设计、精通卡尔曼滤波算法、精通路径规划算法; (3)具备导航方案设计和实现的工程经验; (4)熟悉C/C++语言、熟悉至少一种嵌入式系统开发、熟悉Matlab工具; 公司二(1)熟悉基于视觉信息的SLAM、定位、导航算法,有1年以上相关的科研或项目经历; (2)熟悉惯性导航算法,熟悉IMU与视觉信息的融合; 应用领域 无人机、机器人等。

琴瑟 2019-12-02 01:21:11 0 浏览量 回答数 0

回答

K-Means聚类 首先,我们在一个简单的二维数据集上实现并应用k-means,以了解它如何工作。k-means是一种迭代的、无监督的聚类算法,它将类似的实例组合成集群。该算法通过猜测每个集群的初始centroid,反复向最近的集群分配实例,并重新计算该集群的centroid。首先我们要实现一个函数,它为数据中的每个实例找到最接近的centroid。 import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sb from scipy.io import loadmat %matplotlib inline def find_closest_centroids(X, centroids): m = X.shape[0] k = centroids.shape[0] idx = np.zeros(m) for i in range(m): min_dist = 1000000 for j in range(k): dist = np.sum((X[i,:] - centroids[j,:]) ** 2) if dist < min_dist: min_dist = dist idx[i] = j return idx 测试函数确保它像预期的那样工作,我们使用练习中的测试案例。 data = loadmat('data/ex7data2.mat') X = data['X'] initial_centroids = initial_centroids = np.array([[3, 3], [6, 2], [8, 5]]) idx = find_closest_centroids(X, initial_centroids) idx[0:3] array([0., 2., 1.]) 输出与文本中的预期值相匹配(我们的数组是zero-indexed而不是one-indexed,所以值比练习中的值要低1)。接下来,我们需要一个函数来计算集群的centroid。centroid是当前分配给集群的所有例子的平均值。 def compute_centroids(X, idx, k): m, n = X.shape centroids = np.zeros((k, n)) for i in range(k): indices = np.where(idx == i) centroids[i,:] = (np.sum(X[indices,:], axis=1) / len(indices[0])).ravel() return centroids compute_centroids(X, idx, 3) array([[ 2.42830111, 3.15792418], [ 5.81350331, 2.63365645], [ 7.11938687, 3.6166844 ]]) 此输出也与该练习的预期值相匹配。目前为止一切都很顺利。下一部分涉及到实际运行算法的迭代次数和可视化结果。我们在练习中实现了这一步骤,它没有那么复杂,我将从头开始构建它。为了运行这个算法,我们只需要在分配到最近集群的示例和重新计算集群的centroids之间进行交替操作。 def run_k_means(X, initial_centroids, max_iters): m, n = X.shape k = initial_centroids.shape[0] idx = np.zeros(m) centroids = initial_centroids for i in range(max_iters): idx = find_closest_centroids(X, centroids) centroids = compute_centroids(X, idx, k) return idx, centroids idx, centroids = run_k_means(X, initial_centroids, 10) 我们现在可以使用颜色编码表示集群成员。 cluster1 = X[np.where(idx == 0)[0],:] cluster2 = X[np.where(idx == 1)[0],:] cluster3 = X[np.where(idx == 2)[0],:] fig, ax = plt.subplots(figsize=(12,8)) ax.scatter(cluster1[:,0], cluster1[:,1], s=30, color='r', label='Cluster 1') ax.scatter(cluster2[:,0], cluster2[:,1], s=30, color='g', label='Cluster 2') ax.scatter(cluster3[:,0], cluster3[:,1], s=30, color='b', label='Cluster 3') ax.legend() 我们跳过了初始化centroid的过程。这可能会影响算法的收敛性。 接下来创建一个可以选择随机例子的函数,并将这些例子作为初始的centroid。 def init_centroids(X, k): m, n = X.shape centroids = np.zeros((k, n)) idx = np.random.randint(0, m, k) for i in range(k): centroids[i,:] = X[idx[i],:] return centroids init_centroids(X, 3) array([[ 1.15354031, 4.67866717], [ 6.27376271, 2.24256036], [ 2.20960296, 4.91469264]]) 我们的下一任务是应用K-means实现图像压缩。我们可以使用集群来查找图像中最具有代表性的少量的颜色,并使用集群分配将原来的24位颜色映射到一个低维度的颜色空间。这是我们要压缩的图像。 原始像素数据已经预加载了,把它输入进来。 image_data= loadmat('data/bird_small.mat') image_data {'A': array([[[219, 180, 103], [230, 185, 116], [226, 186, 110], ..., [ 14, 15, 13], [ 13, 15, 12], [ 12, 14, 12]], ..., [[ 15, 19, 19], [ 20, 20, 18], [ 18, 19, 17], ..., [ 65, 43, 39], [ 58, 37, 38], [ 52, 39, 34]]], dtype=uint8), '__globals__': [], '__header__': 'MATLAB 5.0 MAT-file, Platform: GLNXA64, Created on: Tue Jun 5 04:06:24 2012', '__version__': '1.0'} 我们可以快速查看数据的形状,以验证它是否像我们预期的图像。 A= image_data['A'] A.shape (128L,128L,3L) 现在我们需要对数据进行预处理,并将它输入到k-means算法中。 # normalize value ranges A = A / 255. # reshape the array X = np.reshape(A, (A.shape[0] * A.shape[1], A.shape[2])) # randomly initialize the centroids initial_centroids = init_centroids(X, 16) # run the algorithm idx, centroids = run_k_means(X, initial_centroids, 10) # get the closest centroids one last time idx = find_closest_centroids(X, centroids) # map each pixel to the centroid value X_recovered = centroids[idx.astype(int),:] # reshape to the original dimensions X_recovered = np.reshape(X_recovered, (A.shape[0], A.shape[1], A.shape[2])) plt.imshow(X_recovered) 我们在压缩中创建了一些artifact,尽管将原始图像映射到仅16种颜色,但图像的主要特征仍然存在。 这是关于k-means的部分,接下来我们来看关于主成分分析的部分。 主成分分析 PCA是一个可以在数据集中找到“主成分”或者最大方差方向的线性变换。它可以用于其他事物的维度减少。在这个练习中,我们需要实现PCA,并将其应用于一个简单的二维数据集,观察它是如何工作的。从加载和可视化数据集开始。 data = loadmat('data/ex7data1.mat') X = data['X'] fig, ax = plt.subplots(figsize=(12,8)) ax.scatter(X[:, 0], X[:, 1]) PCA的算法相当简单。在保证数据正规化后,输出只是原始数据协方差矩阵的单值分解。由于numpy已经有内置函数来计算矩阵协方差和SVD,我们将利用这些函数而不是从头开始。 def pca(X): # normalize the features X = (X - X.mean()) / X.std() # compute the covariance matrix X = np.matrix(X) cov = (X.T * X) / X.shape[0] # perform SVD U, S, V = np.linalg.svd(cov) return U, S, V U, S, V = pca(X) U, S, V (matrix([[-0.79241747, -0.60997914], [-0.60997914, 0.79241747]]), array([ 1.43584536, 0.56415464]), matrix([[-0.79241747, -0.60997914], [-0.60997914, 0.79241747]])) 现在我们已经有了主成分(矩阵U),我们可以利用它把原始数据投入到一个更低维度的空间,对于这个任务,我们将实现一个函数,它计算投影并只选择顶部K成分,有效地减少了维度的数量。 def project_data(X, U, k): U_reduced = U[:,:k] return np.dot(X, U_reduced) Z = project_data(X, U, 1) Z matrix([[-4.74689738], [-7.15889408], [-4.79563345], [-4.45754509], [-4.80263579], ..., [-6.44590096], [-2.69118076], [-4.61386195], [-5.88236227], [-7.76732508]]) 我们也可以通过改变采取的步骤来恢复原始数据。 def recover_data(Z, U, k): U_reduced = U[:,:k] return np.dot(Z, U_reduced.T) X_recovered = recover_data(Z, U, 1) X_recovered matrix([[ 3.76152442, 2.89550838], [ 5.67283275, 4.36677606], [ 3.80014373, 2.92523637], [ 3.53223661, 2.71900952], [ 3.80569251, 2.92950765], ..., [ 5.10784454, 3.93186513], [ 2.13253865, 1.64156413], [ 3.65610482, 2.81435955], [ 4.66128664, 3.58811828], [ 6.1549641 , 4.73790627]]) 如果我们尝试去可视化恢复的数据,会很容易的发现算法的工作原理。 fig, ax= plt.subplots(figsize=(12,8)) ax.scatter(X_recovered[:,0], X_recovered[:,1]) 注意这些点如何被压缩成一条虚线。虚线本质上是第一个主成分。当我们将数据减少到一个维度时,我们切断的第二个主成分可以被认为是与这条虚线的正交变化。由于我们失去了这些信息,我们的重建只能将这些点与第一个主成分相关联。 我们这次练习的最后一项任务是将PCA应用于脸部图像。通过使用相同降维技术,我们可以使用比原始图像少得多的数据来捕捉图像的“本质”。 faces= loadmat('data/ex7faces.mat') X= faces['X'] X.shape (5000L,1024L) 该练习代码包含一个函数,它将在网格中的数据集中渲染前100个脸部图像。你可以在练习文本中找到它们,不需要重新生成。 face= np.reshape(X[3,:], (32,32)) plt.imshow(face) 只有32 x 32灰度图像。下一步我们要在脸部图像数据集上运行PCA,并取得前100个主成分。 U, S, V= pca(X) Z= project_data(X, U,100) 现在尝试恢复原来的结构并重新渲染它。 X_recovered= recover_data(Z, U,100) face= np.reshape(X_recovered[3,:], (32,32)) plt.imshow(face) 结果并没有像预期的维度数量减少10倍,可能是因为我们丢失了一些细节部分。

珍宝珠 2019-12-02 03:22:40 0 浏览量 回答数 0

问题

【精品问答】python技术1000问(2)

问问小秘 2019-12-01 22:03:02 68 浏览量 回答数 0

回答

遍历一个 List 有哪些不同的方式?每种方法的实现原理是什么?Java 中 List 遍历的最佳实践是什么? 遍历方式有以下几种: for 循环遍历,基于计数器。在集合外部维护一个计数器,然后依次读取每一个位置的元素,当读取到最后一个元素后停止。 迭代器遍历,Iterator。Iterator 是面向对象的一个设计模式,目的是屏蔽不同数据集合的特点,统一遍历集合的接口。Java 在 Collections 中支持了 Iterator 模式。 foreach 循环遍历。foreach 内部也是采用了 Iterator 的方式实现,使用时不需要显式声明 Iterator 或计数器。优点是代码简洁,不易出错;缺点是只能做简单的遍历,不能在遍历过程中操作数据集合,例如删除、替换。 最佳实践:Java Collections 框架中提供了一个 RandomAccess 接口,用来标记 List 实现是否支持 Random Access。 如果一个数据集合实现了该接口,就意味着它支持 Random Access,按位置读取元素的平均时间复杂度为 O(1),如ArrayList。如果没有实现该接口,表示不支持 Random Access,如LinkedList。 推荐的做法就是,支持 Random Access 的列表可用 for 循环遍历,否则建议用 Iterator 或 foreach 遍历。 说一下 ArrayList 的优缺点 ArrayList的优点如下: ArrayList 底层以数组实现,是一种随机访问模式。ArrayList 实现了 RandomAccess 接口,因此查找的时候非常快。ArrayList 在顺序添加一个元素的时候非常方便。 ArrayList 的缺点如下: 删除元素的时候,需要做一次元素复制操作。如果要复制的元素很多,那么就会比较耗费性能。插入元素的时候,也需要做一次元素复制操作,缺点同上。 ArrayList 比较适合顺序添加、随机访问的场景。 如何实现数组和 List 之间的转换? 数组转 List:使用 Arrays. asList(array) 进行转换。List 转数组:使用 List 自带的 toArray() 方法。 代码示例: ArrayList 和 LinkedList 的区别是什么? 数据结构实现:ArrayList 是动态数组的数据结构实现,而 LinkedList 是双向链表的数据结构实现。随机访问效率:ArrayList 比 LinkedList 在随机访问的时候效率要高,因为 LinkedList 是线性的数据存储方式,所以需要移动指针从前往后依次查找。增加和删除效率:在非首尾的增加和删除操作,LinkedList 要比 ArrayList 效率要高,因为 ArrayList 增删操作要影响数组内的其他数据的下标。内存空间占用:LinkedList 比 ArrayList 更占内存,因为 LinkedList 的节点除了存储数据,还存储了两个引用,一个指向前一个元素,一个指向后一个元素。线程安全:ArrayList 和 LinkedList 都是不同步的,也就是不保证线程安全; 综合来说,在需要频繁读取集合中的元素时,更推荐使用 ArrayList,而在插入和删除操作较多时,更推荐使用 LinkedList。 补充:数据结构基础之双向链表 双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。 ArrayList 和 Vector 的区别是什么? 这两个类都实现了 List 接口(List 接口继承了 Collection 接口),他们都是有序集合 线程安全:Vector 使用了 Synchronized 来实现线程同步,是线程安全的,而 ArrayList 是非线程安全的。性能:ArrayList 在性能方面要优于 Vector。扩容:ArrayList 和 Vector 都会根据实际的需要动态的调整容量,只不过在 Vector 扩容每次会增加 1 倍,而 ArrayList 只会增加 50%。 Vector类的所有方法都是同步的。可以由两个线程安全地访问一个Vector对象、但是一个线程访问Vector的话代码要在同步操作上耗费大量的时间。 Arraylist不是同步的,所以在不需要保证线程安全时时建议使用Arraylist。 插入数据时,ArrayList、LinkedList、Vector谁速度较快?阐述 ArrayList、Vector、LinkedList 的存储性能和特性? ArrayList、LinkedList、Vector 底层的实现都是使用数组方式存储数据。数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢。 Vector 中的方法由于加了 synchronized 修饰,因此 Vector 是线程安全容器,但性能上较ArrayList差。 LinkedList 使用双向链表实现存储,按序号索引数据需要进行前向或后向遍历,但插入数据时只需要记录当前项的前后项即可,所以 LinkedList 插入速度较快。 多线程场景下如何使用 ArrayList? ArrayList 不是线程安全的,如果遇到多线程场景,可以通过 Collections 的 synchronizedList 方法将其转换成线程安全的容器后再使用。例如像下面这样: 为什么 ArrayList 的 elementData 加上 transient 修饰? ArrayList 中的数组定义如下: private transient Object[] elementData; 再看一下 ArrayList 的定义: public class ArrayList extends AbstractList implements List<E>, RandomAccess, Cloneable, java.io.Serializable 可以看到 ArrayList 实现了 Serializable 接口,这意味着 ArrayList 支持序列化。transient 的作用是说不希望 elementData 数组被序列化,重写了 writeObject 实现: 每次序列化时,先调用 defaultWriteObject() 方法序列化 ArrayList 中的非 transient 元素,然后遍历 elementData,只序列化已存入的元素,这样既加快了序列化的速度,又减小了序列化之后的文件大小。 List 和 Set 的区别 List , Set 都是继承自Collection 接口 List 特点:一个有序(元素存入集合的顺序和取出的顺序一致)容器,元素可以重复,可以插入多个null元素,元素都有索引。常用的实现类有 ArrayList、LinkedList 和 Vector。 Set 特点:一个无序(存入和取出顺序有可能不一致)容器,不可以存储重复元素,只允许存入一个null元素,必须保证元素唯一性。Set 接口常用实现类是 HashSet、LinkedHashSet 以及 TreeSet。 另外 List 支持for循环,也就是通过下标来遍历,也可以用迭代器,但是set只能用迭代,因为他无序,无法用下标来取得想要的值。 Set和List对比 Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。 List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变 Set接口 说一下 HashSet 的实现原理? HashSet 是基于 HashMap 实现的,HashSet的值存放于HashMap的key上,HashMap的value统一为PRESENT,因此 HashSet 的实现比较简单,相关 HashSet 的操作,基本上都是直接调用底层 HashMap 的相关方法来完成,HashSet 不允许重复的值。 HashSet如何检查重复?HashSet是如何保证数据不可重复的? 向HashSet 中add ()元素时,判断元素是否存在的依据,不仅要比较hash值,同时还要结合equles 方法比较。 HashSet 中的add ()方法会使用HashMap 的put()方法。 HashMap 的 key 是唯一的,由源码可以看出 HashSet 添加进去的值就是作为HashMap 的key,并且在HashMap中如果K/V相同时,会用新的V覆盖掉旧的V,然后返回旧的V。所以不会重复( HashMap 比较key是否相等是先比较hashcode 再比较equals )。 以下是HashSet 部分源码: hashCode()与equals()的相关规定: 如果两个对象相等,则hashcode一定也是相同的 两个对象相等,对两个equals方法返回true 两个对象有相同的hashcode值,它们也不一定是相等的 综上,equals方法被覆盖过,则hashCode方法也必须被覆盖 hashCode()的默认行为是对堆上的对象产生独特值。如果没有重写hashCode(),则该class的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)。 ** ==与equals的区别** ==是判断两个变量或实例是不是指向同一个内存空间 equals是判断两个变量或实例所指向的内存空间的值是不是相同 ==是指对内存地址进行比较 equals()是对字符串的内容进行比较3.==指引用是否相同 equals()指的是值是否相同 HashSet与HashMap的区别 Queue BlockingQueue是什么? Java.util.concurrent.BlockingQueue是一个队列,在进行检索或移除一个元素的时候,它会等待队列变为非空;当在添加一个元素时,它会等待队列中的可用空间。BlockingQueue接口是Java集合框架的一部分,主要用于实现生产者-消费者模式。我们不需要担心等待生产者有可用的空间,或消费者有可用的对象,因为它都在BlockingQueue的实现类中被处理了。Java提供了集中BlockingQueue的实现,比如ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue,、SynchronousQueue等。 在 Queue 中 poll()和 remove()有什么区别? 相同点:都是返回第一个元素,并在队列中删除返回的对象。 不同点:如果没有元素 poll()会返回 null,而 remove()会直接抛出 NoSuchElementException 异常。 代码示例: Queue queue = new LinkedList (); queue. offer("string"); // add System. out. println(queue. poll()); System. out. println(queue. remove()); System. out. println(queue. size()); Map接口 说一下 HashMap 的实现原理? HashMap概述: HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。 HashMap的数据结构: 在Java编程语言中,最基本的结构就是两种,一个是数组,另外一个是模拟指针(引用),所有的数据结构都可以用这两个基本结构来构造的,HashMap也不例外。HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体。 HashMap 基于 Hash 算法实现的 当我们往Hashmap中put元素时,利用key的hashCode重新hash计算出当前对象的元素在数组中的下标存储时,如果出现hash值相同的key,此时有两种情况。(1)如果key相同,则覆盖原始值;(2)如果key不同(出现冲突),则将当前的key-value放入链表中获取时,直接找到hash值对应的下标,在进一步判断key是否相同,从而找到对应值。理解了以上过程就不难明白HashMap是如何解决hash冲突的问题,核心就是使用了数组的存储方式,然后将冲突的key的对象放入链表中,一旦发现冲突就在链表中做进一步的对比。 需要注意Jdk 1.8中对HashMap的实现做了优化,当链表中的节点数据超过八个之后,该链表会转为红黑树来提高查询效率,从原来的O(n)到O(logn) HashMap在JDK1.7和JDK1.8中有哪些不同?HashMap的底层实现 在Java中,保存数据有两种比较简单的数据结构:数组和链表。数组的特点是:寻址容易,插入和删除困难;链表的特点是:寻址困难,但插入和删除容易;所以我们将数组和链表结合在一起,发挥两者各自的优势,使用一种叫做拉链法的方式可以解决哈希冲突。 JDK1.8之前 JDK1.8之前采用的是拉链法。拉链法:将链表和数组相结合。也就是说创建一个链表数组,数组中每一格就是一个链表。若遇到哈希冲突,则将冲突的值加到链表中即可。 JDK1.8之后 相比于之前的版本,jdk1.8在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间。 JDK1.7 VS JDK1.8 比较 JDK1.8主要解决或优化了一下问题: resize 扩容优化引入了红黑树,目的是避免单条链表过长而影响查询效率,红黑树算法请参考解决了多线程死循环问题,但仍是非线程安全的,多线程时可能会造成数据丢失问题。 HashMap的put方法的具体流程? 当我们put的时候,首先计算 key的hash值,这里调用了 hash方法,hash方法实际是让key.hashCode()与key.hashCode()>>>16进行异或操作,高16bit补0,一个数和0异或不变,所以 hash 函数大概的作用就是:高16bit不变,低16bit和高16bit做了一个异或,目的是减少碰撞。按照函数注释,因为bucket数组大小是2的幂,计算下标index = (table.length - 1) & hash,如果不做 hash 处理,相当于散列生效的只有几个低 bit 位,为了减少散列的碰撞,设计者综合考虑了速度、作用、质量之后,使用高16bit和低16bit异或来简单处理减少碰撞,而且JDK8中用了复杂度 O(logn)的树结构来提升碰撞下的性能。 putVal方法执行流程图 ①.判断键值对数组table[i]是否为空或为null,否则执行resize()进行扩容; ②.根据键值key计算hash值得到插入的数组索引i,如果table[i]==null,直接新建节点添加,转向⑥,如果table[i]不为空,转向③; ③.判断table[i]的首个元素是否和key一样,如果相同直接覆盖value,否则转向④,这里的相同指的是hashCode以及equals; ④.判断table[i] 是否为treeNode,即table[i] 是否是红黑树,如果是红黑树,则直接在树中插入键值对,否则转向⑤; ⑤.遍历table[i],判断链表长度是否大于8,大于8的话把链表转换为红黑树,在红黑树中执行插入操作,否则进行链表的插入操作;遍历过程中若发现key已经存在直接覆盖value即可; ⑥.插入成功后,判断实际存在的键值对数量size是否超多了最大容量threshold,如果超过,进行扩容。 HashMap的扩容操作是怎么实现的? ①.在jdk1.8中,resize方法是在hashmap中的键值对大于阀值时或者初始化时,就调用resize方法进行扩容; ②.每次扩展的时候,都是扩展2倍; ③.扩展后Node对象的位置要么在原位置,要么移动到原偏移量两倍的位置。 在putVal()中,我们看到在这个函数里面使用到了2次resize()方法,resize()方法表示的在进行第一次初始化时会对其进行扩容,或者当该数组的实际大小大于其临界值值(第一次为12),这个时候在扩容的同时也会伴随的桶上面的元素进行重新分发,这也是JDK1.8版本的一个优化的地方,在1.7中,扩容之后需要重新去计算其Hash值,根据Hash值对其进行分发,但在1.8版本中,则是根据在同一个桶的位置中进行判断(e.hash & oldCap)是否为0,重新进行hash分配后,该元素的位置要么停留在原始位置,要么移动到原始位置+增加的数组大小这个位置上 HashMap是怎么解决哈希冲突的? 答:在解决这个问题之前,我们首先需要知道什么是哈希冲突,而在了解哈希冲突之前我们还要知道什么是哈希才行; 什么是哈希? Hash,一般翻译为“散列”,也有直接音译为“哈希”的,这就是把任意长度的输入通过散列算法,变换成固定长度的输出,该输出就是散列值(哈希值);这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。 所有散列函数都有如下一个基本特性**:根据同一散列函数计算出的散列值如果不同,那么输入值肯定也不同。但是,根据同一散列函数计算出的散列值如果相同,输入值不一定相同**。 什么是哈希冲突? 当两个不同的输入值,根据同一散列函数计算出相同的散列值的现象,我们就把它叫做碰撞(哈希碰撞)。 HashMap的数据结构 在Java中,保存数据有两种比较简单的数据结构:数组和链表。数组的特点是:寻址容易,插入和删除困难;链表的特点是:寻址困难,但插入和删除容易;所以我们将数组和链表结合在一起,发挥两者各自的优势,使用一种叫做链地址法的方式可以解决哈希冲突: 这样我们就可以将拥有相同哈希值的对象组织成一个链表放在hash值所对应的bucket下,但相比于hashCode返回的int类型,我们HashMap初始的容量大小DEFAULT_INITIAL_CAPACITY = 1 << 4(即2的四次方16)要远小于int类型的范围,所以我们如果只是单纯的用hashCode取余来获取对应的bucket这将会大大增加哈希碰撞的概率,并且最坏情况下还会将HashMap变成一个单链表,所以我们还需要对hashCode作一定的优化 hash()函数 上面提到的问题,主要是因为如果使用hashCode取余,那么相当于参与运算的只有hashCode的低位,高位是没有起到任何作用的,所以我们的思路就是让hashCode取值出的高位也参与运算,进一步降低hash碰撞的概率,使得数据分布更平均,我们把这样的操作称为扰动,在JDK 1.8中的hash()函数如下: static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);// 与自己右移16位进行异或运算(高低位异或) } 这比在JDK 1.7中,更为简洁,相比在1.7中的4次位运算,5次异或运算(9次扰动),在1.8中,只进行了1次位运算和1次异或运算(2次扰动); JDK1.8新增红黑树 通过上面的链地址法(使用散列表)和扰动函数我们成功让我们的数据分布更平均,哈希碰撞减少,但是当我们的HashMap中存在大量数据时,加入我们某个bucket下对应的链表有n个元素,那么遍历时间复杂度就为O(n),为了针对这个问题,JDK1.8在HashMap中新增了红黑树的数据结构,进一步使得遍历复杂度降低至O(logn); 总结 简单总结一下HashMap是使用了哪些方法来有效解决哈希冲突的: 使用链地址法(使用散列表)来链接拥有相同hash值的数据;使用2次扰动函数(hash函数)来降低哈希冲突的概率,使得数据分布更平均;引入红黑树进一步降低遍历的时间复杂度,使得遍历更快; **能否使用任何类作为 Map 的 key? **可以使用任何类作为 Map 的 key,然而在使用之前,需要考虑以下几点: 如果类重写了 equals() 方法,也应该重写 hashCode() 方法。 类的所有实例需要遵循与 equals() 和 hashCode() 相关的规则。 如果一个类没有使用 equals(),不应该在 hashCode() 中使用它。 用户自定义 Key 类最佳实践是使之为不可变的,这样 hashCode() 值可以被缓存起来,拥有更好的性能。不可变的类也可以确保 hashCode() 和 equals() 在未来不会改变,这样就会解决与可变相关的问题了。 为什么HashMap中String、Integer这样的包装类适合作为K? 答:String、Integer等包装类的特性能够保证Hash值的不可更改性和计算准确性,能够有效的减少Hash碰撞的几率 都是final类型,即不可变性,保证key的不可更改性,不会存在获取hash值不同的情况 内部已重写了equals()、hashCode()等方法,遵守了HashMap内部的规范(不清楚可以去上面看看putValue的过程),不容易出现Hash值计算错误的情况; 如果使用Object作为HashMap的Key,应该怎么办呢? 答:重写hashCode()和equals()方法 重写hashCode()是因为需要计算存储数据的存储位置,需要注意不要试图从散列码计算中排除掉一个对象的关键部分来提高性能,这样虽然能更快但可能会导致更多的Hash碰撞; 重写equals()方法,需要遵守自反性、对称性、传递性、一致性以及对于任何非null的引用值x,x.equals(null)必须返回false的这几个特性,目的是为了保证key在哈希表中的唯一性; HashMap为什么不直接使用hashCode()处理后的哈希值直接作为table的下标 答:hashCode()方法返回的是int整数类型,其范围为-(2 ^ 31)~(2 ^ 31 - 1),约有40亿个映射空间,而HashMap的容量范围是在16(初始化默认值)~2 ^ 30,HashMap通常情况下是取不到最大值的,并且设备上也难以提供这么多的存储空间,从而导致通过hashCode()计算出的哈希值可能不在数组大小范围内,进而无法匹配存储位置; 那怎么解决呢? HashMap自己实现了自己的hash()方法,通过两次扰动使得它自己的哈希值高低位自行进行异或运算,降低哈希碰撞概率也使得数据分布更平均; 在保证数组长度为2的幂次方的时候,使用hash()运算之后的值与运算(&)(数组长度 - 1)来获取数组下标的方式进行存储,这样一来是比取余操作更加有效率,二来也是因为只有当数组长度为2的幂次方时,h&(length-1)才等价于h%length,三来解决了“哈希值与数组大小范围不匹配”的问题; HashMap 的长度为什么是2的幂次方 为了能让 HashMap 存取高效,尽量较少碰撞,也就是要尽量把数据分配均匀,每个链表/红黑树长度大致相同。这个实现就是把数据存到哪个链表/红黑树中的算法。 这个算法应该如何设计呢? 我们首先可能会想到采用%取余的操作来实现。但是,重点来了:“取余(%)操作中如果除数是2的幂次则等价于与其除数减一的与(&)操作(也就是说 hash%length==hash&(length-1)的前提是 length 是2的 n 次方;)。” 并且 采用二进制位操作 &,相对于%能够提高运算效率,这就解释了 HashMap 的长度为什么是2的幂次方。 那为什么是两次扰动呢? 答:这样就是加大哈希值低位的随机性,使得分布更均匀,从而提高对应数组存储下标位置的随机性&均匀性,最终减少Hash冲突,两次就够了,已经达到了高位低位同时参与运算的目的; HashMap 与 HashTable 有什么区别? 线程安全: HashMap 是非线程安全的,HashTable 是线程安全的;HashTable 内部的方法基本都经过 synchronized 修饰。(如果你要保证线程安全的话就使用 ConcurrentHashMap 吧!); 效率: 因为线程安全的问题,HashMap 要比 HashTable 效率高一点。另外,HashTable 基本被淘汰,不要在代码中使用它; 对Null key 和Null value的支持: HashMap 中,null 可以作为键,这样的键只有一个,可以有一个或多个键所对应的值为 null。但是在 HashTable 中 put 进的键值只要有一个 null,直接抛NullPointerException。 **初始容量大小和每次扩充容量大小的不同 **: ①创建时如果不指定容量初始值,Hashtable 默认的初始大小为11,之后每次扩充,容量变为原来的2n+1。HashMap 默认的初始化大小为16。之后每次扩充,容量变为原来的2倍。②创建时如果给定了容量初始值,那么 Hashtable 会直接使用你给定的大小,而 HashMap 会将其扩充为2的幂次方大小。也就是说 HashMap 总是使用2的幂作为哈希表的大小,后面会介绍到为什么是2的幂次方。 底层数据结构: JDK1.8 以后的 HashMap 在解决哈希冲突时有了较大的变化,当链表长度大于阈值(默认为8)时,将链表转化为红黑树,以减少搜索时间。Hashtable 没有这样的机制。 推荐使用:在 Hashtable 的类注释可以看到,Hashtable 是保留类不建议使用,推荐在单线程环境下使用 HashMap 替代,如果需要多线程使用则用 ConcurrentHashMap 替代。 如何决定使用 HashMap 还是 TreeMap? 对于在Map中插入、删除和定位元素这类操作,HashMap是最好的选择。然而,假如你需要对一个有序的key集合进行遍历,TreeMap是更好的选择。基于你的collection的大小,也许向HashMap中添加元素会更快,将map换为TreeMap进行有序key的遍历。 HashMap 和 ConcurrentHashMap 的区别 ConcurrentHashMap对整个桶数组进行了分割分段(Segment),然后在每一个分段上都用lock锁进行保护,相对于HashTable的synchronized锁的粒度更精细了一些,并发性能更好,而HashMap没有锁机制,不是线程安全的。(JDK1.8之后ConcurrentHashMap启用了一种全新的方式实现,利用CAS算法。) HashMap的键值对允许有null,但是ConCurrentHashMap都不允许。 ConcurrentHashMap 和 Hashtable 的区别? ConcurrentHashMap 和 Hashtable 的区别主要体现在实现线程安全的方式上不同。 底层数据结构: JDK1.7的 ConcurrentHashMap 底层采用 分段的数组+链表 实现,JDK1.8 采用的数据结构跟HashMap1.8的结构一样,数组+链表/红黑二叉树。Hashtable 和 JDK1.8 之前的 HashMap 的底层数据结构类似都是采用 数组+链表 的形式,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的; 实现线程安全的方式(重要): ① 在JDK1.7的时候,ConcurrentHashMap(分段锁) 对整个桶数组进行了分割分段(Segment),每一把锁只锁容器其中一部分数据,多线程访问容器里不同数据段的数据,就不会存在锁竞争,提高并发访问率。(默认分配16个Segment,比Hashtable效率提高16倍。) 到了 JDK1.8 的时候已经摒弃了Segment的概念,而是直接用 Node 数组+链表+红黑树的数据结构来实现,并发控制使用 synchronized 和 CAS 来操作。(JDK1.6以后 对 synchronized锁做了很多优化) 整个看起来就像是优化过且线程安全的 HashMap,虽然在JDK1.8中还能看到 Segment 的数据结构,但是已经简化了属性,只是为了兼容旧版本;② Hashtable(同一把锁) :使用 synchronized 来保证线程安全,效率非常低下。当一个线程访问同步方法时,其他线程也访问同步方法,可能会进入阻塞或轮询状态,如使用 put 添加元素,另一个线程不能使用 put 添加元素,也不能使用 get,竞争会越来越激烈效率越低。 两者的对比图: HashTable: JDK1.7的ConcurrentHashMap: JDK1.8的ConcurrentHashMap(TreeBin: 红黑二叉树节点 Node: 链表节点): 答:ConcurrentHashMap 结合了 HashMap 和 HashTable 二者的优势。HashMap 没有考虑同步,HashTable 考虑了同步的问题。但是 HashTable 在每次同步执行时都要锁住整个结构。 ConcurrentHashMap 锁的方式是稍微细粒度的。 ConcurrentHashMap 底层具体实现知道吗?实现原理是什么? JDK1.7 首先将数据分为一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据时,其他段的数据也能被其他线程访问。 在JDK1.7中,ConcurrentHashMap采用Segment + HashEntry的方式进行实现,结构如下: 一个 ConcurrentHashMap 里包含一个 Segment 数组。Segment 的结构和HashMap类似,是一种数组和链表结构,一个 Segment 包含一个 HashEntry 数组,每个 HashEntry 是一个链表结构的元素,每个 Segment 守护着一个HashEntry数组里的元素,当对 HashEntry 数组的数据进行修改时,必须首先获得对应的 Segment的锁。 该类包含两个静态内部类 HashEntry 和 Segment ;前者用来封装映射表的键值对,后者用来充当锁的角色;Segment 是一种可重入的锁 ReentrantLock,每个 Segment 守护一个HashEntry 数组里得元素,当对 HashEntry 数组的数据进行修改时,必须首先获得对应的 Segment 锁。 JDK1.8 在JDK1.8中,放弃了Segment臃肿的设计,取而代之的是采用Node + CAS + Synchronized来保证并发安全进行实现,synchronized只锁定当前链表或红黑二叉树的首节点,这样只要hash不冲突,就不会产生并发,效率又提升N倍。 结构如下: 如果该节点是TreeBin类型的节点,说明是红黑树结构,则通过putTreeVal方法往红黑树中插入节点;如果binCount不为0,说明put操作对数据产生了影响,如果当前链表的个数达到8个,则通过treeifyBin方法转化为红黑树,如果oldVal不为空,说明是一次更新操作,没有对元素个数产生影响,则直接返回旧值;如果插入的是一个新节点,则执行addCount()方法尝试更新元素个数baseCount; 辅助工具类 Array 和 ArrayList 有何区别? Array 可以存储基本数据类型和对象,ArrayList 只能存储对象。Array 是指定固定大小的,而 ArrayList 大小是自动扩展的。Array 内置方法没有 ArrayList 多,比如 addAll、removeAll、iteration 等方法只有 ArrayList 有。 对于基本类型数据,集合使用自动装箱来减少编码工作量。但是,当处理固定大小的基本数据类型的时候,这种方式相对比较慢。 如何实现 Array 和 List 之间的转换? Array 转 List: Arrays. asList(array) ;List 转 Array:List 的 toArray() 方法。 comparable 和 comparator的区别? comparable接口实际上是出自java.lang包,它有一个 compareTo(Object obj)方法用来排序comparator接口实际上是出自 java.util 包,它有一个compare(Object obj1, Object obj2)方法用来排序 一般我们需要对一个集合使用自定义排序时,我们就要重写compareTo方法或compare方法,当我们需要对某一个集合实现两种排序方式,比如一个song对象中的歌名和歌手名分别采用一种排序方法的话,我们可以重写compareTo方法和使用自制的Comparator方法或者以两个Comparator来实现歌名排序和歌星名排序,第二种代表我们只能使用两个参数版的Collections.sort(). 方法如何比较元素? TreeSet 要求存放的对象所属的类必须实现 Comparable 接口,该接口提供了比较元素的 compareTo()方法,当插入元素时会回调该方法比较元素的大小。TreeMap 要求存放的键值对映射的键必须实现 Comparable 接口从而根据键对元素进 行排 序。 Collections 工具类的 sort 方法有两种重载的形式, 第一种要求传入的待排序容器中存放的对象比较实现 Comparable 接口以实现元素的比较; 第二种不强制性的要求容器中的元素必须可比较,但是要求传入第二个参数,参数是Comparator 接口的子类型(需要重写 compare 方法实现元素的比较),相当于一个临时定义的排序规则,其实就是通过接口注入比较元素大小的算法,也是对回调模式的应用(Java 中对函数式编程的支持)。

剑曼红尘 2020-03-24 14:41:57 0 浏览量 回答数 0
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 企业信息查询 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 2020阿里巴巴研发效能峰会 企业建站模板 云效成长地图 高端建站