<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/rss.xsl" type="text/xsl"?>
<rss version="2.0">
  <channel>
    <title>IT瘾经典推荐</title>
    <link>https://itindex.net/categories/经典</link>
    <description>IT社区推荐资讯 - ITIndex.net</description>
    <language>zh</language>
    <copyright>https://itindex.net/</copyright>
    <generator>https://itindex.net/</generator>
    <docs>http://backend.userland.com/rss</docs>
    <image>
      <url>https://itindex.net/images/logo.gif</url>
      <title>IT社区推荐资讯 - ITIndex.net</title>
      <link>https://itindex.net/categories/经典</link>
    </image>
    <item>
      <title>《老人与海》为什么成为经典？</title>
      <link>https://itindex.net/detail/63095-%E8%80%81%E4%BA%BA%E4%B8%8E%E6%B5%B7-%E7%BB%8F%E5%85%B8</link>
      <description>&lt;div&gt;问：&lt;/div&gt; &lt;div&gt;昨天晚上看了《老人与海》也觉得又臭又长（虽然是短篇小说），因为绝大部分老人都在自言自语、磨磨叽叽，也没干什么，这就给我了一个不太好的印象。讲真，我并不能理解这本书为什么可以如此著名，并流传至今还是经典。  &lt;br /&gt;  &lt;br /&gt;  &lt;div&gt;   &lt;div&gt;    &lt;div&gt;     &lt;p&gt;答：&lt;/p&gt;     &lt;p&gt;题主能这样想，说明是好事，说明题主人生没什么挫折，过的非常幸福。&lt;/p&gt;     &lt;p&gt;      &lt;a href="https://zhida.zhihu.com/search?content_id=61243273&amp;content_type=Answer&amp;match_order=1&amp;q=%E3%80%8A%E8%80%81%E4%BA%BA%E4%B8%8E%E6%B5%B7%E3%80%8B&amp;zhida_source=entity" target="_blank"&gt;《老人与海》&lt;/a&gt;这本书，作者用平铺直叙的手法来写作，语言上面没有高潮起伏，所以你会觉得它，       &lt;strong&gt;又臭又长、 自言自语 、 磨磨叽叽、也没干什么 、 啰嗦起来真的像紧箍咒 。&lt;/strong&gt;&lt;/p&gt;     &lt;p&gt;但越发是这样的写作手法，阅读它的时候就越要去发挥自己的思维联动，因为作者给的信息太少。这是      &lt;a href="https://zhida.zhihu.com/search?content_id=61243273&amp;content_type=Answer&amp;match_order=1&amp;q=%E6%B5%B7%E6%98%8E%E5%A8%81&amp;zhida_source=entity" target="_blank"&gt;海明威&lt;/a&gt;特有的      &lt;a href="https://zhida.zhihu.com/search?content_id=61243273&amp;content_type=Answer&amp;match_order=1&amp;q=%E6%9E%81%E7%AE%80%E4%B8%BB%E4%B9%89&amp;zhida_source=entity" target="_blank"&gt;极简主义&lt;/a&gt;的风格。&lt;/p&gt;     &lt;p&gt;举个例子，&lt;/p&gt;     &lt;p&gt;      &lt;strong&gt;最后，她还是提出了分手。他——。&lt;/strong&gt;&lt;/p&gt;     &lt;p&gt;一般作家都会写，      &lt;strong&gt;他无奈的笑了。&lt;/strong&gt;&lt;/p&gt;     &lt;p&gt;      &lt;strong&gt;他满脸苦笑。&lt;/strong&gt;&lt;/p&gt;     &lt;p&gt;诸如此类的等等修辞手法。      &lt;br /&gt;&lt;/p&gt;     &lt;p&gt;而海明威就不会赋予这个笑任何情绪，直接就写，      &lt;strong&gt;他笑了。&lt;/strong&gt;&lt;/p&gt;     &lt;p&gt;但我们都有过感情受挫的经验，所以，看到      &lt;strong&gt;他笑了。&lt;/strong&gt;我们就会联系当时的情景，我们知道感情破裂不好笑，所以就知道这个笑肯定不是正面的情绪表达。所以男主人公这时候肯定不是开心的状态。&lt;/p&gt;     &lt;p&gt;所以老人与海这种书，几乎从头到尾都是这样极简的写作手法，不同的人读它有不同的感受。&lt;/p&gt;     &lt;p&gt;因为里面叙事结构几乎没有高潮，就是很平静的给你娓娓道来，书中老人几乎也没表达情绪，就是不断自言自语，不断胡思乱想。&lt;/p&gt;     &lt;p&gt;各种情绪都要你结合自身的经验去体会。&lt;/p&gt;     &lt;p&gt;例如老人捕获了大鱼，并且与大鱼缠斗上了，时间瞬间过去了十几个小时，老人一直重复。&lt;/p&gt;     &lt;p&gt;“一定要记得吃沙丁鱼。”&lt;/p&gt;     &lt;p&gt;“不管你多么不想吃，天亮后一定要把沙丁鱼吃掉。”&lt;/p&gt;     &lt;p&gt;“必须在沙丁鱼腐化之前把它吃掉。”&lt;/p&gt;     &lt;br /&gt;     &lt;p&gt;因为老人抓了一条大鱼，抓住了大机会，&lt;/p&gt;     &lt;p&gt;但是对手太过于强大，又僵持了十几个小时。&lt;/p&gt;     &lt;p&gt;作者并没有写出来，当时老人的体力状况与心情，只是借老人的口不断说出要吃沙丁鱼这种话。&lt;/p&gt;     &lt;p&gt;你也许会想，这样想不是很正常吗，不吃就会饿，就没体力抓鱼了，有必要强调三四遍吗。&lt;/p&gt;     &lt;p&gt;因为你是抱着一种想看很精彩的故事的心态来看这个书的。&lt;/p&gt;     &lt;p&gt;这样写，并不精彩，在你眼里又臭又长。&lt;/p&gt;     &lt;p&gt;但如果你在生活中，有过      &lt;strong&gt;面临着巨大机会，但自知能力有限，紧张兮兮的心里状态。&lt;/strong&gt;&lt;/p&gt;     &lt;p&gt;你就能充分体会老人当时的心态。&lt;/p&gt;     &lt;p&gt;例如穷困潦倒，出去面试，老板审视着你，你却在心里不断念叨一定要注意自己的谈吐，不要说错话。&lt;/p&gt;     &lt;p&gt;例如面对很喜欢，但是自己觉得配不上的女孩子，在跟她说话的时候，你却在心里不断的想自己形象如何。&lt;/p&gt;     &lt;p&gt;例如面对客户，你本应向她推销，但心里却一直嘀嘀咕咕怎么样才能表现得体……&lt;/p&gt;     &lt;p&gt;你要是有任何这种经验，在看这段话就绝对不会觉得他又臭又长，而会觉得能完全理解老人当时的心态。&lt;/p&gt;     &lt;br /&gt;     &lt;p&gt;《老人与海》写于二战结束不久，世界一片狼藉，劳动人民生活日子艰苦，大家看到这种关怀人类存在的意义，描述与命运做斗争的故事，自然喜欢，奉为经典，一点也不奇怪。&lt;/p&gt;     &lt;p&gt;但是现如今我们生活太富足了，我认为题主人生没什么挫折，过的非常幸福。其实这并不是什么坏事呀。读书这个事情本来随性，大可找一点自己爱看的书去读。&lt;/p&gt;     &lt;p&gt;因为《老人与海》是不适合你看的，起码，现在暂时不适合。&lt;/p&gt;     &lt;p&gt;当你去做一些难事，&lt;/p&gt;     &lt;p&gt;例如，穷困潦倒出去创业。&lt;/p&gt;     &lt;p&gt;例如，一穷二白去追求自己喜欢的事情。&lt;/p&gt;     &lt;p&gt;例如，身体条件极差但拼命锻炼想改变自己。&lt;/p&gt;     &lt;p&gt;例如，碰到极度喜欢的女孩子然后拼命想改变自己的形象、气质、经济状况等等。&lt;/p&gt;     &lt;p&gt;你再来看这个书，想法一定会截然不同。&lt;/p&gt;     &lt;p&gt;我不想说我的人生过的有多艰苦，但我把这个书看完以后马上就泪目了，我看书从来没哭过，一本是这个，另一本是      &lt;a href="https://zhida.zhihu.com/search?content_id=61243273&amp;content_type=Answer&amp;match_order=1&amp;q=%E4%BD%99%E5%8D%8E&amp;zhida_source=entity" target="_blank"&gt;余华&lt;/a&gt;的      &lt;a href="https://zhida.zhihu.com/search?content_id=61243273&amp;content_type=Answer&amp;match_order=1&amp;q=%E3%80%8A%E6%B4%BB%E7%9D%80%E3%80%8B&amp;zhida_source=entity" target="_blank"&gt;《活着》&lt;/a&gt;，《活着》也被有些人称之为中国的老人与海。&lt;/p&gt;     &lt;p&gt;老人80多天没有抓到鱼，大家要么嘲笑他，要么同情他，没人理他，只有小孩与他为伍，酒吧老板救济他才能勉强吃顿饱饭，每天只能看看棒球新闻。&lt;/p&gt;     &lt;p&gt;这该有多失落啊，但是老人一点也没有沮丧。他出海，去了远海，他抓到一条大鱼，他是英雄，鱼也是英雄，搏斗几天几夜，惺惺相惜，鱼折磨老人，老人生吃恶心的鱼肉来充饥，睡不上觉，手上脸上血肉模糊，老人不恨鱼，敬佩鱼。&lt;/p&gt;     &lt;p&gt;如果把钓索切断，与鱼断开牵连，马上就能解脱。但那意味着失败！老人脑子里从没放弃过去斗争的念头。他所想的只是，我要吃生鱼肉，我要保存体力，鱼呀，你快死掉吧，我要为你念经。&lt;/p&gt;     &lt;p&gt;他胜利了，但是鲨鱼又来了，老人杀了一条又一条，枪没了，刀没了，船桨船舵都没了。&lt;/p&gt;     &lt;p&gt;最后老人回到岸边，只带回了一条鱼的白骨。&lt;/p&gt;     &lt;p&gt;但是他失败了吗？没有。&lt;/p&gt;     &lt;p&gt;      &lt;strong&gt; 什么叫失败？也许可以说，人去做一件事情，没有达到预期得目的，这就是失败。 &lt;/strong&gt;&lt;/p&gt;     &lt;p&gt;      &lt;strong&gt;但是，那些与命运斗争的人，那些做接近自己限度的斗争的人，却天生地接近这种失败。老人到海上去，不能期望天天有鱼来咬他的钩，于是他常常失败。一个常常在进行着接近自己限度的斗争的人总是会常常失败的，一个想探索自然奥秘的人也常常会失败，一个想改革社会的人更是会常常失败。只有那些安于自己限度之内的生活的人才总是“胜利”，这种“胜利者”之所以常胜不败，只是因为他的对手是早已降伏的，或者说，他根本没有投入斗争。 ——王小波&lt;/strong&gt;&lt;/p&gt;     &lt;p&gt;老人只带着一副鱼骨，疲惫不堪的回到了自己的破茅屋中，他起床后并没有懊悔，也没悲伤，他只对小孩说，要准备好刀枪、装备。风雨一停我们再去出海。颇有一副将生死置之度外，向命运宣战，向梦想扬帆的热血与悲壮。&lt;/p&gt;     &lt;p&gt;读到这里，我已肃然起敬，泪流满面。&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;   &lt;div&gt;    &lt;div&gt;     &lt;div&gt;      &lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;
     
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/63095-%E8%80%81%E4%BA%BA%E4%B8%8E%E6%B5%B7-%E7%BB%8F%E5%85%B8</guid>
      <pubDate>Fri, 28 Nov 2025 09:44:38 CST</pubDate>
    </item>
    <item>
      <title>6 大经典机器学习数据集，3w+ 用户票选得出，建议收藏</title>
      <link>https://itindex.net/detail/62669-%E7%BB%8F%E5%85%B8-%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0-%E6%95%B0%E6%8D%AE</link>
      <description>&lt;blockquote&gt;内容一览：本期汇总了超神经下载排名众多的 6 个数据集，涵盖图像识别、机器翻译、遥感影像等领域。这些数据集质量高、数据量大，经历人气认证值得收藏码住。  &lt;br /&gt;关键词：数据集   机器翻译   机器视觉&lt;/blockquote&gt; &lt;p&gt;数据集是机器学习模型训练的基础，优质的公开数据集对于模型训练效果、研究成果可靠度等具有重要意义。&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;HyperAI超神经自上线以来，为数据科学从业者提供了大量优质的公开数据集。&lt;/strong&gt; 本期内容分享，我们筛选出了 6 个热门数据集，  &lt;strong&gt;其总下载次数已达到 32,569 次。&lt;/strong&gt; 希望这些数据集能进一步为广大开发者服务~&lt;/p&gt; &lt;p&gt;注：本文梳理的数据集均来自为数据科学家服务的网站——超神经  &lt;br /&gt;  &lt;a href="https://hyper.ai/datasets" rel="nofollow noreferrer"&gt;https://hyper.ai/datasets&lt;/a&gt;&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;第 6 名：   &lt;a href="https://hyper.ai/datasets/4920" rel="nofollow noreferrer"&gt;Tanks Temple 3D 重建数据集&lt;/a&gt;&lt;/strong&gt;  &lt;br /&gt;  &lt;img alt="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="https://segmentfault.com/img/remote/1460000043474394" title="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="https://segmentfault.com/img/remote/1460000043474395" title="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;Tanks Temple 图像数据集提供高分辨率的视频，研究人员可以从视频中采集图像，  &lt;strong&gt;依据图像进行三维重建。&lt;/strong&gt; 该数据集包括训练数据和测试数据两类，其中测试数据分为中级组和高级组。&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;第 5 名：   &lt;a href="https://hyper.ai/datasets/4920" rel="nofollow noreferrer"&gt;DOTA 航拍图像数据集&lt;/a&gt;&lt;/strong&gt;   &lt;br /&gt;  &lt;img alt="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="https://segmentfault.com/img/remote/1460000043474396" title="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="https://segmentfault.com/img/remote/1460000043474397" title="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;DOTA 全称为 A Large-scale Dataset for Object DeTection in Aerial Images，是一个包含 2,806 张航拍图的图像数据集，  &lt;strong&gt;被用于在航拍图像中进行目标检测，发现和评估图像中的物体。&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;这些图像来源包含不同传感器和平台。每张图像的像素尺寸在 800  &lt;em&gt;800 到 4000&lt;/em&gt;4000 的范围内，其中包含不同尺度、方向和形状的物体。&lt;/p&gt; &lt;p&gt;往期推送请访问：  &lt;br /&gt;  &lt;a href="http://mp.weixin.qq.com/s?__biz=MzU3NTQ2NDIyOQ==&amp;mid=2247496885&amp;idx=1&amp;sn=add8058f38f5a39608d4915924c5e23b&amp;chksm=fd2002ffca578be91997c3dc38ff72aea8b818bae7be805072217220d9a71179776f71b7ec14&amp;scene=21#wechat_redirect" rel="nofollow noreferrer"&gt;DOTA 数据集：2806 张遥感图像，近 19 万个标注实例&lt;/a&gt;&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;第 4 名：   &lt;a href="https://hyper.ai/datasets/5711" rel="nofollow noreferrer"&gt;VGG-Face2 人脸识别数据集&lt;/a&gt;&lt;/strong&gt;  &lt;br /&gt;  &lt;img alt="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="https://segmentfault.com/img/remote/1460000043474398" title="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="https://segmentfault.com/img/remote/1460000043474399" title="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;VGG-Face2 是一个人脸图像数据集，包含共计 9131  个人的面部数据，图像均来自 Google 的图片搜索。  &lt;strong&gt;数据集中的人在姿势、年龄、种族和职业方面有很大差异。&lt;/strong&gt; 该数据集由牛津大学的工程科学系视觉几何组于 2015 年发布，相关论文有《Deep Face Recognition》。&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;第 3 名：   &lt;a href="https://hyper.ai/datasets/5419" rel="nofollow noreferrer"&gt;UCAS-AOD 遥感影像数据集&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="https://segmentfault.com/img/remote/1460000043474400" title="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="https://segmentfault.com/img/remote/1460000043474401" title="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;UCAS-AOD 是一个遥感影像数据集，  &lt;strong&gt;用于飞机和车辆检测。&lt;/strong&gt; 该数据集由国科大于 2014 年首次发布，并于 2015 年补充，相关论文有《Orientation Robust Object Detection in Aerial Images Using Deep Convolutional Neural Network》&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;第 2 名：   &lt;a href="https://hyper.ai/datasets/14137" rel="nofollow noreferrer"&gt;OpenMantra 漫画机器翻译数据集&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="https://segmentfault.com/img/remote/1460000043474402" title="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="https://segmentfault.com/img/remote/1460000043474403" title="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;OpenMantra 是一个针对日文漫画的机器翻译评估数据集，包含五种不同风格（fantacy、romance、battle、mystery、slice of life）的漫画。  &lt;strong&gt;数据集中共包含 1593 个句子，848 个场景画面和 214 页漫画，&lt;/strong&gt; 由东京大学 Mantra 团队发布。&lt;/p&gt; &lt;p&gt;往期推送请查看：  &lt;br /&gt;  &lt;a href="http://mp.weixin.qq.com/s?__biz=MzU3NTQ2NDIyOQ==&amp;mid=2247497461&amp;idx=1&amp;sn=3b7eede40073e65e0bd8bd73d15ede19&amp;chksm=fd2000bfca5789a92f1808b1e98464d31af07344bc98cae9f1fbad95de5e063dcd4659f77491&amp;scene=21#wechat_redirect" rel="nofollow noreferrer"&gt;漫画翻译、嵌字 AI，东京大学论文被 AAAI’21 收录&lt;/a&gt;&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;第 1 名：   &lt;a href="https://hyper.ai/datasets/4899" rel="nofollow noreferrer"&gt;ImageNet 10 图像识别数据集&lt;/a&gt;&lt;/strong&gt;  &lt;br /&gt;  &lt;img alt="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="https://segmentfault.com/img/remote/1460000043474404" title="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;  &lt;img alt="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="https://segmentfault.com/img/remote/1460000043474405" title="&amp;#22312;&amp;#36825;&amp;#37324;&amp;#25554;&amp;#20837;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;ImageNet 是目前世界上最大的图像识别数据库，由斯坦福大学教授李飞飞等人创建。&lt;/strong&gt; 主要用于机器视觉领域的图像分类和目标检测。&lt;/p&gt; &lt;p&gt;数据集根据 WordNet 层次结构组织，其中每个节点（也称为类别）由数百甚至数千张图像组成。该数据集共包含 2.2 万个图像类别，约 1500 万张图片。&lt;/p&gt; &lt;p&gt;往期推送请访问：  &lt;br /&gt;  &lt;a href="http://mp.weixin.qq.com/s?__biz=MzU3NTQ2NDIyOQ==&amp;mid=2247486955&amp;idx=1&amp;sn=622108b403f441fe71e8e4ddbe72529b&amp;chksm=fd23fba1ca5472b7a6f6129a8f064d2839fe68fbaef100734466a19f2f34fd22ca7e2d9d0f8e&amp;scene=21#wechat_redirect" rel="nofollow noreferrer"&gt;当年这个决定，让李飞飞奠定 AI 江湖的女王地位&lt;/a&gt;&lt;/p&gt; &lt;p&gt;以上就是本期推荐的 6 个 hyper.ai 高频下载数据集，更多数据科学优质公开数据集，可访问以下链接下载：  &lt;a href="https://hyper.ai/datasets" rel="nofollow noreferrer"&gt;https://hyper.ai/datasets&lt;/a&gt;&lt;/p&gt; &lt;p&gt;—— 完 ——&lt;/p&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>算法 机器学习 人工智能 深度学习 数据挖掘</category>
      <guid isPermaLink="true">https://itindex.net/detail/62669-%E7%BB%8F%E5%85%B8-%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0-%E6%95%B0%E6%8D%AE</guid>
      <pubDate>Mon, 20 Feb 2023 13:56:27 CST</pubDate>
    </item>
    <item>
      <title>常见 SQL 面试题：经典 50 例</title>
      <link>https://itindex.net/detail/61860-%E5%B8%B8%E8%A7%81-sql-%E9%9D%A2%E8%AF%95</link>
      <description>&lt;h2&gt;SQL基础知识整理&lt;/h2&gt; &lt;pre&gt;  &lt;code&gt;select 查询结果，如: [学号,平均成绩：组函数avg(成绩)]

from 从哪张表中查找数据，如:[涉及到成绩：成绩表score]

where 查询条件，如:[b.课程号=&amp;apos;0003&amp;apos; and b.成绩&amp;gt;80]

group by 分组，如:[每个学生的平均：按学号分组](oracle,SQL server中出现在select 子句后的非分组函数，必须出现在group by子句后出现),MySQL中可以不用

having 对分组结果指定条件，如:[大于60分]

order by 对查询结果排序，如:[增序: 成绩  ASC / 降序: 成绩 DESC];

limit 使用limt子句返回topN（对应这个问题返回的成绩前两名），如:[ limit  2 ==&amp;gt;从0索引开始读取2个]limit==&amp;gt;从0索引开始 [0,N-1]&lt;/code&gt;&lt;/pre&gt; &lt;pre&gt;  &lt;code&gt;select * from table limit 2,1;                
-- 含义是跳过2条取出1条数据，limit后面是从第2条开始读，读取1条信息，即读取第3条数据
 
select * from table limit 2 offset 1;     
-- 含义是从第1条（不包括）数据开始取出2条数据，limit后面跟的是2条数据，offset后面是从第1条开始读取，即读取第2,3条&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;  &lt;strong&gt;组函数&lt;/strong&gt;: 去重 distinct()  统计总数sum()   计算个数count()  平均数avg()  最大值max() 最小数min()&lt;/p&gt; &lt;p&gt;  &lt;strong&gt;多表连接&lt;/strong&gt;: 内连接(省略默认inner) join ...on..左连接left join tableName as b on a.key ==b.key右连接right join  连接union(无重复(过滤去重))和union all(有重复[不过滤去重])&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;union 并集&lt;/li&gt;  &lt;li&gt;union all(有重复)&lt;/li&gt;  &lt;li&gt;oracle(SQL server)数据库&lt;/li&gt;  &lt;li&gt;intersect 交集&lt;/li&gt;  &lt;li&gt;minus(except) 相减(差集)&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874556" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;h2&gt;oracle&lt;/h2&gt; &lt;h4&gt;一、数据库对象：表(table)  视图(view)  序列(sequence)  索引(index)  同义词(synonym)&lt;/h4&gt; &lt;h6&gt;1.视图: 存储起来的 select 语句&lt;/h6&gt; &lt;pre&gt;  &lt;code&gt;create view emp_vw
as
select employee_id, last_name, salary
from employees
where department_id = 90;

select * from emp_vw;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;可以对简单视图进行 DML 操作&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;update emp_vw
set last_name = &amp;apos;HelloKitty&amp;apos;
where employee_id = 100;

select * from employees
where employee_id = 100;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;1). 复杂视图&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;create view emp_vw2
as
select department_id, avg(salary) avg_sal
from employees
group by department_id;

select * from emp_vw2;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;复杂视图不能进行 DML 操作&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;update emp_vw2
set avg_sal = 10000
where department_id = 100;&lt;/code&gt;&lt;/pre&gt; &lt;h6&gt;2.序列：用于生成一组有规律的数值。（通常用于为主键设置值）&lt;/h6&gt; &lt;pre&gt;  &lt;code&gt;create sequence emp_seq1
start with 1
increment by 1
maxvalue 10000
minvalue 1
cycle
nocache;

select emp_seq1.currval from dual;

select emp_seq1.nextval from dual;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;  &lt;strong&gt;问题：裂缝，原因&lt;/strong&gt;：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;当多个表共用同一个序列时。&lt;/li&gt;  &lt;li&gt;rollback&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;发生异常&lt;/p&gt;   &lt;pre&gt;    &lt;code&gt;create table emp1(
     id number(10),
     name varchar2(30)
);

insert into emp1
values(emp_seq1.nextval, &amp;apos;张三&amp;apos;);

select * from emp1;&lt;/code&gt;&lt;/pre&gt;   &lt;h6&gt;3.索引：提高查询效率&lt;/h6&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;自动创建：Oracle 会为具有唯一约束(唯一约束，主键约束)的列，自动创建索引&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;create table emp2(
       id number(10) primary key,
       name varchar2(30)
)&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;手动创建&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;create index emp_idx
on emp2(name);

create index emp_idx2
on emp2(id, name);&lt;/code&gt;&lt;/pre&gt; &lt;h6&gt;4.同义词&lt;/h6&gt; &lt;pre&gt;  &lt;code&gt;create synonym d1 for departments;

select * from d1;&lt;/code&gt;&lt;/pre&gt; &lt;h6&gt;5.表：&lt;/h6&gt; &lt;p&gt;DDL ：数据定义语言 create table .../ drop table ... / rename ... to..../ truncate table.../alter table ...&lt;/p&gt; &lt;p&gt;DML : 数据操纵语言&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;insert into ... values ...
update ... set ... where ...
delete from ... where ...&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;【重要】&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;select ... 组函数(MIN()/MAX()/SUM()/AVG()/COUNT())
from ...join ... on ... 左外连接：left join ... on ... 右外连接: right join ... on ...
where ...
group by ... (oracle,SQL server中出现在select 子句后的非分组函数，必须出现在 group by子句后)
having ... 用于过滤 组函数
order by ... asc 升序， desc 降序
limit (0,4) 限制N条数据 如: topN数据
- union 并集
- union all(有重复)
- intersect 交集
- minus 相减
DCL : 数据控制语言  commit : 提交 / rollback : 回滚 / 授权grant...to...  /revoke&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874557" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;h2&gt;索引&lt;/h2&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874558" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874559" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874560" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;何时创建索引:&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874561" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874562" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874563" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874564" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;select employee_id, last_name, salary, department_id
from employees
where department_id in (70, 80) --&amp;gt; 70:1  80:34&lt;/code&gt;&lt;/pre&gt; &lt;ul&gt;  &lt;li&gt;union 并集&lt;/li&gt;  &lt;li&gt;union all(有重复部分)&lt;/li&gt;  &lt;li&gt;intersect 交集&lt;/li&gt;  &lt;li&gt;   &lt;p&gt;minus 相减&lt;/p&gt;   &lt;pre&gt;    &lt;code&gt;select employee_id, last_name, salary, department_id
from employees
where department_id in (80, 90)  --&amp;gt; 90:4  80:34&lt;/code&gt;&lt;/pre&gt;   &lt;p&gt;问题：查询工资大于149号员工工资的员工的信息&lt;/p&gt;   &lt;pre&gt;    &lt;code&gt;select * 
from employees
where salary &amp;gt; (
    select salary
    from employees
    where employee_id = 149
)&lt;/code&gt;&lt;/pre&gt;   &lt;p&gt;问题：查询与141号或174号员工的manager_id和department_id相同的其他员工的employee_id, manager_id, department_id&lt;/p&gt;   &lt;pre&gt;    &lt;code&gt;select employee_id, manager_id, department_id
from employees
where manager_id in (
    select manager_id
    from employees
    where employee_id in(141, 174)
) and department_id in (
    select department_id
    from employees
    where employee_id in(141, 174)
) and employee_id not in (141, 174);

select employee_id, manager_id, department_id
from employees
where (manager_id, department_id) in (
    select manager_id, department_id
    from employees
    where employee_id in (141, 174)
) and employee_id not in(141, 174);&lt;/code&gt;&lt;/pre&gt;   &lt;p&gt;from 子句中使用子查询&lt;/p&gt;   &lt;pre&gt;    &lt;code&gt;select max(avg(salary))
from employees
group by department_id;

select max(avg_sal)
from (
    select avg(salary) avg_sal
    from employees
    group by department_id
) &lt;/code&gt;&lt;/pre&gt;   &lt;p&gt;问题：返回比本部门平均工资高的员工的last_name, department_id, salary及平均工资&lt;/p&gt;   &lt;pre&gt;    &lt;code&gt;select last_name, department_id, salary, (select avg(salary) from employees where department_id = e1.department_id)
from employees e1
where salary &amp;gt; (
    select avg(salary)
    from employees e2
    where e1.department_id = e2.department_id
)

select last_name, e1.department_id, salary, avg_sal
from employees e1, (
   select department_id, avg(salary) avg_sal
   from employees
   group by department_id
) e2
where e1.department_id = e2.department_id
and e1.salary &amp;gt; e2.avg_sal;
case...when ... then... when ... then ... else ... end&lt;/code&gt;&lt;/pre&gt;   &lt;p&gt;查询：若部门为10 查看工资的 1.1 倍，部门号为 20 工资的1.2倍，其余 1.3 倍&lt;/p&gt;   &lt;pre&gt;    &lt;code&gt;SELECT
 employee_id,
 last_name,
 salary,
CASE
department_id 
WHEN 10 THEN
salary * 1.1                                                           
WHEN 20 THEN
salary * 1.2  ELSE salary * 1.3                                                           
 END &amp;quot;new_salary&amp;quot; 
FROM
 employees;
SELECT
 employee_id,
 last_name,
 salary,
 decode( department_id, 10, salary * 1.1, 20, salary * 1.2,  salary * 1.3 ) &amp;quot;new_salary&amp;quot; 
FROM
 employees;&lt;/code&gt;&lt;/pre&gt;   &lt;p&gt;问题：显式员工的employee_id,last_name和location。其中，若员工department_id与location_id为1800的department_id相同，则location为’Canada’,其余则为’USA’。&lt;/p&gt;   &lt;pre&gt;    &lt;code&gt;select employee_id, last_name, case department_id when (
                  select department_id
                  from departments
                  where location_id = 1800
) then &amp;apos;Canada&amp;apos; else &amp;apos;USA&amp;apos; end &amp;quot;location&amp;quot;
from employees;&lt;/code&gt;&lt;/pre&gt;   &lt;p&gt;问题：查询员工的employee_id,last_name,要求按照员工的department_name排序    &lt;br /&gt;select employee_id, last_name&lt;/p&gt;   &lt;pre&gt;    &lt;code&gt;from employees e1
order by (
    select department_name
    from departments d1
    where e1.department_id = d1.department_id
)&lt;/code&gt;&lt;/pre&gt;   &lt;h2&gt;SQL 优化：能使用 EXISTS 就不要使用 IN&lt;/h2&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;问题：查询公司管理者的employee_id,last_name,job_id,department_id信息&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;select employee_id, last_name, job_id, department_id
from employees
where employee_id in (
      select manager_id
      from employees
)&lt;/code&gt;&lt;/pre&gt; &lt;pre&gt;  &lt;code&gt;select employee_id, last_name, job_id, department_id
from employees e1
where exists (
      select &amp;apos;x&amp;apos;
      from employees e2
      where e1.employee_id = e2.manager_id
) &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;问题：查询departments表中，不存在于employees表中的部门的department_id和department_name&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;select department_id, department_name
from departments d1
where not exists (
      select &amp;apos;x&amp;apos;
      from employees e1
      where e1.department_id = d1.department_id
)&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;更改 108 员工的信息: 使其工资变为所在部门中的最高工资, job 变为公司中平均工资最低的 job&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;update employees e1
set salary = (
    select max(salary)
    from employees e2
    where e1.department_id = e2.department_id
), job_id = (
   select job_id
   from employees
   group by job_id
   having avg(salary) = (
         select min(avg(salary))
         from employees
         group by job_id
   )
)
where employee_id = 108;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;删除 108 号员工所在部门中工资最低的那个员工.&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;delete from employees e1
where salary = (
      select min(salary)
      from employees
      where department_id = (
            select department_id
            from employees
            where employee_id = 108
      )
)

select * from employees where employee_id = 108;
select * from employees where department_id = 100
order by salary;

rollback;&lt;/code&gt;&lt;/pre&gt; &lt;h2&gt;常见的SQL面试题：经典50题&lt;/h2&gt; &lt;p&gt;已知有如下4张表：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;学生表：student(学号,学生姓名,出生年月,性别)&lt;/li&gt;  &lt;li&gt;成绩表：score(学号,课程号,成绩)&lt;/li&gt;  &lt;li&gt;课程表：course(课程号,课程名称,教师号)&lt;/li&gt;  &lt;li&gt;教师表：teacher(教师号,教师姓名)&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;根据以上信息按照下面要求写出对应的SQL语句。（搜索公众号民工哥技术之路，回复“10241”，送你一份技术资源宝典）&lt;/p&gt; &lt;p&gt;ps：这些题考察SQL的编写能力，对于这类型的题目，需要你先把4张表之间的关联关系搞清楚了，最好的办法是自己在草稿纸上画出关联图，然后再编写对应的SQL语句就比较容易了。下图是我画的这4张表的关系图，可以看出它们之间是通过哪些外键关联起来的：&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874565" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;h3&gt;一、创建数据库和表&lt;/h3&gt; &lt;p&gt;为了演示题目的运行过程，我们先按下面语句在客户端navicat中创建数据库和表。&lt;/p&gt; &lt;p&gt;如何你还不懂什么是数据库，什么是客户端navicat，可以先学习这个：&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874566" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;h6&gt;1.创建表&lt;/h6&gt; &lt;p&gt;1）创建学生表（student）&lt;/p&gt; &lt;p&gt;按下图在客户端navicat里创建学生表。推荐：企业面试题汇总&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874567" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;学生表的“学号”列设置为主键约束，下图是每一列设置的数据类型和约束&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874568" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;创建完表，点击“保存”&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874569" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;2）创建成绩表（score）&lt;/p&gt; &lt;p&gt;同样的步骤，创建&amp;quot;成绩表“。“课程表的“学号”和“课程号”一起设置为主键约束（联合主键），“成绩”这一列设置为数值类型（float，浮点数值）&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874570" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;3）创建课程表（course）&lt;/p&gt; &lt;p&gt;课程表的“课程号”设置为主键约束&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874571" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;4）教师表（teacher）&lt;/p&gt; &lt;p&gt;教师表的“教师号”列设置为主键约束，教师姓名这一列设置约束为“null”（红框的地方不勾选），表示这一列允许包含空值（null）。推荐：企业面试题汇总&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874572" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;向表中添加数据&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874573" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;1）向学生表里添加数据&lt;/p&gt; &lt;p&gt;添加数据的sql&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;insert into student(学号,姓名,出生日期,性别) 
values(&amp;apos;0001&amp;apos; , &amp;apos;猴子&amp;apos; , &amp;apos;1989-01-01&amp;apos; , &amp;apos;男&amp;apos;);
 
insert into student(学号,姓名,出生日期,性别) 
values(&amp;apos;0002&amp;apos; , &amp;apos;猴子&amp;apos; , &amp;apos;1990-12-21&amp;apos; , &amp;apos;女&amp;apos;);
 
insert into student(学号,姓名,出生日期,性别) 
values(&amp;apos;0003&amp;apos; , &amp;apos;马云&amp;apos; , &amp;apos;1991-12-21&amp;apos; , &amp;apos;男&amp;apos;);
 
insert into student(学号,姓名,出生日期,性别) 
values(&amp;apos;0004&amp;apos; , &amp;apos;王思聪&amp;apos; , &amp;apos;1990-05-20&amp;apos; , &amp;apos;男&amp;apos;);&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;在客户端navicat里的操作&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874574" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874575" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874576" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;2）成绩表（score）&lt;/p&gt; &lt;p&gt;添加数据的sql&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;insert into score(学号,课程号,成绩) 
values(&amp;apos;0001&amp;apos; , &amp;apos;0001&amp;apos; , 80);
 
insert into score(学号,课程号,成绩) 
values(&amp;apos;0001&amp;apos; , &amp;apos;0002&amp;apos; , 90);
 
insert into score(学号,课程号,成绩) 
values(&amp;apos;0001&amp;apos; , &amp;apos;0003&amp;apos; , 99);
 
insert into score(学号,课程号,成绩) 
values(&amp;apos;0002&amp;apos; , &amp;apos;0002&amp;apos; , 60);
 
insert into score(学号,课程号,成绩) 
values(&amp;apos;0002&amp;apos; , &amp;apos;0003&amp;apos; , 80);
 
insert into score(学号,课程号,成绩) 
values(&amp;apos;0003&amp;apos; , &amp;apos;0001&amp;apos; , 80);
 
insert into score(学号,课程号,成绩) 
values(&amp;apos;0003&amp;apos; , &amp;apos;0002&amp;apos; , 80);
 
insert into score(学号,课程号,成绩) 
values(&amp;apos;0003&amp;apos; , &amp;apos;0003&amp;apos; , 80);&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;客户端navicat里的操作&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874577" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;3）课程表&lt;/p&gt; &lt;p&gt;添加数据的sql&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;insert into course(课程号,课程名称,教师号)
values(&amp;apos;0001&amp;apos; , &amp;apos;语文&amp;apos; , &amp;apos;0002&amp;apos;);
 
insert into course(课程号,课程名称,教师号)
values(&amp;apos;0002&amp;apos; , &amp;apos;数学&amp;apos; , &amp;apos;0001&amp;apos;);
 
insert into course(课程号,课程名称,教师号)
values(&amp;apos;0003&amp;apos; , &amp;apos;英语&amp;apos; , &amp;apos;0003&amp;apos;);&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;客户端navicat里的操作&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874578" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;4）教师表里添加数据&lt;/p&gt; &lt;p&gt;添加数据的sql&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;-- 教师表：添加数据
insert into teacher(教师号,教师姓名) 
values(&amp;apos;0001&amp;apos; , &amp;apos;孟扎扎&amp;apos;);
 
insert into teacher(教师号,教师姓名) 
values(&amp;apos;0002&amp;apos; , &amp;apos;马化腾&amp;apos;);
 
-- 这里的教师姓名是空值（null）
insert into teacher(教师号,教师姓名) 
values(&amp;apos;0003&amp;apos; , null);
 
-- 这里的教师姓名是空字符串（&amp;apos;&amp;apos;）
insert into teacher(教师号,教师姓名) 
values(&amp;apos;0004&amp;apos; , &amp;apos;&amp;apos;);&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;客户端navicat里操作&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874579" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;添加结果&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874580" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;h2&gt;三、50道面试题&lt;/h2&gt; &lt;p&gt;为了方便学习，我将50道面试题进行了分类&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874581" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;查询姓“猴”的学生名单&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874582" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;查询姓“孟”老师的个数&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;select count(教师号)
from teacher
where 教师姓名 like &amp;apos;孟%&amp;apos;;&lt;/code&gt;&lt;/pre&gt; &lt;h6&gt;2.汇总统计分组分析&lt;/h6&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874583" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;面试题：查询课程编号为“0002”的总成绩&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;--分析思路
--select 查询结果 [总成绩:汇总函数sum]
--from 从哪张表中查找数据[成绩表score]
--where 查询条件 [课程号是0002]
select sum(成绩)
from score
where 课程号 = &amp;apos;0002&amp;apos;;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;查询选了课程的学生人数&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;--这个题目翻译成大白话就是：查询有多少人选了课程
--select 学号，成绩表里学号有重复值需要去掉
--from 从课程表查找score;
select count(distinct 学号) as 学生人数 
from score;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874584" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;查询各科成绩最高和最低的分， 以如下的形式显示：课程号，最高分，最低分&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;/*
分析思路
select 查询结果 [课程ID：是课程号的别名,最高分：max(成绩) ,最低分：min(成绩)]
from 从哪张表中查找数据 [成绩表score]
where 查询条件 [没有]
group by 分组 [各科成绩：也就是每门课程的成绩，需要按课程号分组];
*/
select 课程号,max(成绩) as 最高分,min(成绩) as 最低分
from score
group by 课程号;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;查询每门课程被选修的学生数&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;/*
分析思路
select 查询结果 [课程号，选修该课程的学生数：汇总函数count]
from 从哪张表中查找数据 [成绩表score]
where 查询条件 [没有]
group by 分组 [每门课程：按课程号分组];
*/
select 课程号, count(学号)
from score
group by 课程号;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;查询男生、女生人数&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;/*
分析思路
select 查询结果 [性别，对应性别的人数：汇总函数count]
from 从哪张表中查找数据 [性别在学生表中，所以查找的是学生表student]
where 查询条件 [没有]
group by 分组 [男生、女生人数：按性别分组]
having 对分组结果指定条件 [没有]
order by 对查询结果排序[没有];
*/
select 性别,count(*)
from student
group by 性别;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874585" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;查询平均成绩大于60分学生的学号和平均成绩&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;/* 
题目翻译成大白话：
平均成绩：展开来说就是计算每个学生的平均成绩
这里涉及到“每个”就是要分组了
平均成绩大于60分，就是对分组结果指定条件
分析思路
select 查询结果 [学号，平均成绩：汇总函数avg(成绩)]
from 从哪张表中查找数据 [成绩在成绩表中，所以查找的是成绩表score]
where 查询条件 [没有]
group by 分组 [平均成绩：先按学号分组，再计算平均成绩]
having 对分组结果指定条件 [平均成绩大于60分]
*/
select 学号, avg(成绩)
from score
group by 学号
having avg(成绩)&amp;gt;60;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;查询至少选修两门课程的学生学号&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;/* 
翻译成大白话：
第1步，需要先计算出每个学生选修的课程数据，需要按学号分组
第2步，至少选修两门课程：也就是每个学生选修课程数目&amp;gt;=2，对分组结果指定条件
分析思路
select 查询结果 [学号,每个学生选修课程数目：汇总函数count]
from 从哪张表中查找数据 [课程的学生学号：课程表score]
where 查询条件 [至少选修两门课程：需要先计算出每个学生选修了多少门课，需要用分组，所以这里没有where子句]
group by 分组 [每个学生选修课程数目：按课程号分组，然后用汇总函数count计算出选修了多少门课]
having 对分组结果指定条件 [至少选修两门课程：每个学生选修课程数目&amp;gt;=2]
*/
select 学号, count(课程号) as 选修课程数目
from score
group by 学号
having count(课程号)&amp;gt;=2;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;查询同名同性学生名单并统计同名人数&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;/* 
翻译成大白话，问题解析：
1）查找出姓名相同的学生有谁，每个姓名相同学生的人数
查询结果：姓名,人数
条件：怎么算姓名相同？按姓名分组后人数大于等于2，因为同名的人数大于等于2

分析思路
select 查询结果 [姓名,人数：汇总函数count(*)]
from 从哪张表中查找数据 [学生表student]
where 查询条件 [没有]
group by 分组 [姓名相同：按姓名分组]
having 对分组结果指定条件 [姓名相同：count(*)&amp;gt;=2]
order by 对查询结果排序[没有];
*/
 
select 姓名,count(*) as 人数
from student
group by 姓名
having count(*)&amp;gt;=2;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;查询不及格的课程并按课程号从大到小排列&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;/* 
分析思路
select 查询结果 [课程号]
from 从哪张表中查找数据 [成绩表score]
where 查询条件 [不及格：成绩 &amp;lt;60]
group by 分组 [没有]
having 对分组结果指定条件 [没有]
order by 对查询结果排序[课程号从大到小排列：降序desc];
*/
select 课程号
from score 
where 成绩&amp;lt;60
order by 课程号 desc;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;查询每门课程的平均成绩，结果按平均成绩升序排序，平均成绩相同时，按课程号降序排列&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;/* 
分析思路
select 查询结果 [课程号,平均成绩：汇总函数avg(成绩)]
from 从哪张表中查找数据 [成绩表score]
where 查询条件 [没有]
group by 分组 [每门课程：按课程号分组]
having 对分组结果指定条件 [没有]
order by 对查询结果排序[按平均成绩升序排序:asc，平均成绩相同时，按课程号降序排列:desc];
*/
select 课程号, avg(成绩) as 平均成绩
from score
group by 课程号
order by 平均成绩 asc,课程号 desc;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;检索课程编号为“0004”且分数小于60的学生学号，结果按按分数降序排列&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;/* 
分析思路
select 查询结果 []
from 从哪张表中查找数据 [成绩表score]
where 查询条件 [课程编号为“04”且分数小于60]
group by 分组 [没有]
having 对分组结果指定条件 []
order by 对查询结果排序[查询结果按按分数降序排列];
*/
select 学号
from score
where 课程号=&amp;apos;04&amp;apos; and 成绩 &amp;lt;60
order by 成绩 desc;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;统计每门课程的学生选修人数(超过2人的课程才统计)&lt;/p&gt; &lt;p&gt;要求输出课程号和选修人数，查询结果按人数降序排序，若人数相同，按课程号升序排序&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;/* 
分析思路
select 查询结果 [要求输出课程号和选修人数]
from 从哪张表中查找数据 []
where 查询条件 []
group by 分组 [每门课程：按课程号分组]
having 对分组结果指定条件 [学生选修人数(超过2人的课程才统计)：每门课程学生人数&amp;gt;2]
order by 对查询结果排序[查询结果按人数降序排序，若人数相同，按课程号升序排序];
*/
select 课程号, count(学号) as &amp;apos;选修人数&amp;apos;
from score
group by 课程号
having count(学号)&amp;gt;2
order by count(学号) desc,课程号 asc;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;查询两门以上不及格课程的同学的学号及其平均成绩&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;/*
分析思路
先分解题目：
1）[两门以上][不及格课程]限制条件
2）[同学的学号及其平均成绩]，也就是每个学生的平均成绩，显示学号，平均成绩
分析过程：
第1步：得到每个学生的平均成绩，显示学号，平均成绩
第2步：再加上限制条件：
1）不及格课程
2）两门以上[不及格课程]：课程数目&amp;gt;2
 
 
/* 
第1步：得到每个学生的平均成绩，显示学号，平均成绩
select 查询结果 [学号,平均成绩：汇总函数avg(成绩)]
from 从哪张表中查找数据 [涉及到成绩：成绩表score]
where 查询条件 [没有]
group by 分组 [每个学生的平均：按学号分组]
having 对分组结果指定条件 [没有]
order by 对查询结果排序[没有];
*/
select 学号, avg(成绩) as 平均成绩
from score
group by 学号;
 
 
/* 
第2步：再加上限制条件：
1）不及格课程
2）两门以上[不及格课程]
select 查询结果 [学号,平均成绩：汇总函数avg(成绩)]
from 从哪张表中查找数据 [涉及到成绩：成绩表score]
where 查询条件 [限制条件：不及格课程，平均成绩&amp;lt;60]
group by 分组 [每个学生的平均：按学号分组]
having 对分组结果指定条件 [限制条件：课程数目&amp;gt;2,汇总函数count(课程号)&amp;gt;2]
order by 对查询结果排序[没有];
*/
select 学号, avg(成绩) as 平均成绩
from score
where 成绩 &amp;lt;60
group by 学号
having count(课程号)&amp;gt;=2;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;如果上面题目不会做，可以复习这部分涉及到的sql知识：&lt;/p&gt; &lt;h6&gt;3.复杂查询&lt;/h6&gt; &lt;p&gt;查询所有课程成绩小于60分学生的学号、姓名&lt;/p&gt; &lt;p&gt;【知识点】子查询&lt;/p&gt; &lt;p&gt;1.翻译成大白话&lt;/p&gt; &lt;p&gt;1）查询结果：学生学号，姓名 2）查询条件：所有课程成绩 &amp;lt; 60 的学生，需要从成绩表里查找，用到子查询&lt;/p&gt; &lt;p&gt;第1步，写子查询（所有课程成绩 &amp;lt; 60 的学生）&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;select 查询结果[学号]
from 从哪张表中查找数据[成绩表：score]
where 查询条件[成绩 &amp;lt; 60]
group by 分组[没有]
having 对分组结果指定条件[没有]
order by 对查询结果排序[没有]
limit 从查询结果中取出指定行[没有];
select 学号 
from score
where 成绩 &amp;lt; 60;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;第2步，查询结果：学生学号，姓名，条件是前面1步查到的学号&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;select 查询结果[学号,姓名]
from 从哪张表中查找数据[学生表:student]
where 查询条件[用到运算符in]
group by 分组[没有]
having 对分组结果指定条件[没有]
order by 对查询结果排序[没有]
limit 从查询结果中取出指定行[没有];
select 学号,姓名
from student
where  学号 in (
select 学号 
from score
where 成绩 &amp;lt; 60
);&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;查询没有学全所有课的学生的学号、姓名&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;/*
查找出学号，条件：没有学全所有课，也就是该学生选修的课程数 &amp;lt; 总的课程数
【考察知识点】in，子查询
*/
select 学号,姓名
from student
where 学号 in(
select 学号 
from score
group by 学号
having count(课程号) &amp;lt; (select count(课程号) from course)
);&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;查询出只选修了两门课程的全部学生的学号和姓名&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;select 学号,姓名
from student
where 学号 in(
select 学号
from score
group by 学号
having count(课程号)=2
);&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;1990年出生的学生名单&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874586" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;/*
查找1990年出生的学生名单
学生表中出生日期列的类型是datetime
*/
select 学号,姓名 
from student 
where year(出生日期)=1990; &lt;/code&gt;&lt;/pre&gt; &lt;p&gt;查询各科成绩前两名的记录&lt;/p&gt; &lt;p&gt;这类问题其实就是常见的：分组取每组最大值、最小值，每组最大的N条（top N）记录。&lt;/p&gt; &lt;h2&gt;sql面试题：topN问题&lt;/h2&gt; &lt;p&gt;工作中会经常遇到这样的业务问题：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;如何找到每个类别下用户最喜欢的产品是哪个？&lt;/li&gt;  &lt;li&gt;如果找到每个类别下用户点击最多的5个商品是什么？&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;这类问题其实就是常见的：分组取每组最大值、最小值，每组最大的N条（top N）记录。&lt;/p&gt; &lt;p&gt;面对该类问题，如何解决呢？&lt;/p&gt; &lt;p&gt;下面我们通过成绩表的例子来给出答案。&lt;/p&gt; &lt;p&gt;成绩表是学生的成绩，里面有学号（学生的学号），课程号（学生选修课程的课程号），成绩（学生选修该课程取得的成绩）&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874587" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;h6&gt;分组取每组最大值&lt;/h6&gt; &lt;p&gt;案例：按课程号分组取成绩最大值所在行的数据&lt;/p&gt; &lt;p&gt;我们可以使用分组（group by）和汇总函数得到每个组里的一个值（最大值，最小值，平均值等）。但是无法得到成绩最大值所在行的数据。&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;select 课程号,max(成绩) as 最大成绩
from score 
group by 课程号;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874588" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;我们可以使用关联子查询来实现：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;select * 
from score as a 
where 成绩 = (
select max(成绩) 
from score as b 
where b.课程号 = a.课程号);&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874589" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;上面查询结果课程号“0001”有2行数据，是因为最大成绩80有2个&lt;/p&gt; &lt;h6&gt;分组取每组最小值&lt;/h6&gt; &lt;p&gt;案例：按课程号分组取成绩最小值所在行的数据&lt;/p&gt; &lt;p&gt;同样的使用关联子查询来实现&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;select * 
from score as a 
where 成绩 = (
select min(成绩) 
from score as b 
where b.课程号 = a.课程号);&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874590" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;h6&gt;每组最大的N条记录&lt;/h6&gt; &lt;p&gt;案例：查询各科成绩前两名的记录&lt;/p&gt; &lt;p&gt;第1步，查出有哪些组&lt;/p&gt; &lt;p&gt;我们可以按课程号分组，查询出有哪些组，对应这个问题里就是有哪些课程号&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;select 课程号,max(成绩) as 最大成绩
from score 
group by 课程号;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874591" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;第2步：先使用order by子句按成绩降序排序（desc），然后使用limt子句返回topN（对应这个问题返回的成绩前两名）&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;-- 课程号&amp;apos;0001&amp;apos; 这一组里成绩前2名
select * 
from score 
where 课程号 = &amp;apos;0001&amp;apos; 
order by 成绩  desc 
limit 2;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;同样的，可以写出其他组的（其他课程号）取出成绩前2名的sql&lt;/p&gt; &lt;p&gt;第3步，使用union all 将每组选出的数据合并到一起&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;-- 左右滑动可以可拿到全部sql
(select * from score where 课程号 = &amp;apos;0001&amp;apos; order by 成绩  desc limit 2)
union all
(select * from score where 课程号 = &amp;apos;0002&amp;apos; order by 成绩  desc limit 2)
union all
(select * from score where 课程号 = &amp;apos;0003&amp;apos; order by 成绩  desc limit 2);&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874592" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;前面我们使用order by子句按某个列降序排序（desc）得到的是每组最大的N个记录。如果想要达到每组最小的N个记录，将order by子句按某个列升序排序（asc）即可。&lt;/p&gt; &lt;p&gt;求topN的问题还可以使用自定义变量来实现，这个在后续再介绍。&lt;/p&gt; &lt;p&gt;如果对多表合并还不了解的，可以看下我讲过的《从零学会SQL》的“多表查询”。&lt;/p&gt; &lt;h6&gt;总结&lt;/h6&gt; &lt;p&gt;常见面试题：分组取每组最大值、最小值，每组最大的N条（top N）记录。&lt;/p&gt; &lt;h2&gt;多表查询&lt;/h2&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874593" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;查询所有学生的学号、姓名、选课数、总成绩&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;select a.学号,a.姓名,count(b.课程号) as 选课数,sum(b.成绩) as 总成绩
from student as a left join score as b
on a.学号 = b.学号
group by a.学号;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;查询平均成绩大于85的所有学生的学号、姓名和平均成绩&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;select a.学号,a.姓名, avg(b.成绩) as 平均成绩
from student as a left join score as b
on a.学号 = b.学号
group by a.学号
having avg(b.成绩)&amp;gt;85;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;查询学生的选课情况：学号，姓名，课程号，课程名称&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;select a.学号, a.姓名, c.课程号,c.课程名称
from student a inner join score b on a.学号=b.学号
inner join course c on b.课程号=c.课程号;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;查询出每门课程的及格人数和不及格人数&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;-- 考察case表达式
select 课程号,
sum(case when 成绩&amp;gt;=60 then 1 
  else 0 
    end) as 及格人数,
sum(case when 成绩 &amp;lt;  60 then 1 
  else 0 
    end) as 不及格人数
from score
group by 课程号;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;使用分段  &lt;code&gt;[100-85],[85-70],[70-60],[&amp;lt;60]&lt;/code&gt;来统计各科成绩，分别统计：各分数段人数，课程号和课程名称&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;-- 考察case表达式
select a.课程号,b.课程名称,
sum(case when 成绩 between 85 and 100 
  then 1 else 0 end) as &amp;apos;[100-85]&amp;apos;,
sum(case when 成绩 &amp;gt;=70 and 成绩&amp;lt;85 
  then 1 else 0 end) as &amp;apos;[85-70]&amp;apos;,
sum(case when 成绩&amp;gt;=60 and 成绩&amp;lt;70  
  then 1 else 0 end) as &amp;apos;[70-60]&amp;apos;,
sum(case when 成绩&amp;lt;60 then 1 else 0 end) as &amp;apos;[&amp;lt;60]&amp;apos;
from score as a right join course as b 
on a.课程号=b.课程号
group by a.课程号,b.课程名称;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;查询课程编号为0003且课程成绩在80分以上的学生的学号和姓名|&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;select a.学号,a.姓名
from student  as a inner join score as b on a.学号=b.学号
where b.课程号=&amp;apos;0003&amp;apos; and b.成绩&amp;gt;80;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;下面是学生的成绩表（表名score，列名：学号、课程号、成绩）&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874594" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;使用sql实现将该表行转列为下面的表结构&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874595" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;【面试题类型总结】这类题目属于行列如何互换，解题思路如下：&lt;/p&gt; &lt;p&gt;【面试题】下面是学生的成绩表（表名score，列名：学号、课程号、成绩）&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874596" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;使用sql实现将该表行转列为下面的表结构&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874597" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;【解答】&lt;/p&gt; &lt;p&gt;第1步，使用常量列输出目标表的结构&lt;/p&gt; &lt;p&gt;可以看到查询结果已经和目标表非常接近了&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;select 学号,&amp;apos;课程号0001&amp;apos;,&amp;apos;课程号0002&amp;apos;,&amp;apos;课程号0003&amp;apos;
from score;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874598" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;第2步，使用case表达式，替换常量列为对应的成绩&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;select 学号,
(case 课程号 when &amp;apos;0001&amp;apos; then 成绩 else 0 end) as &amp;apos;课程号0001&amp;apos;,
(case 课程号 when &amp;apos;0002&amp;apos; then 成绩 else 0 end) as  &amp;apos;课程号0002&amp;apos;,
(case 课程号 when &amp;apos;0003&amp;apos; then 成绩 else 0 end) as &amp;apos;课程号0003&amp;apos;
from score;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874599" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;在这个查询结果中，每一行表示了某个学生某一门课程的成绩。比如第一行是&amp;apos;学号0001&amp;apos;选修&amp;apos;课程号00001&amp;apos;的成绩，而其他两列的&amp;apos;课程号0002&amp;apos;和&amp;apos;课程号0003&amp;apos;成绩为0。&lt;/p&gt; &lt;p&gt;每个学生选修某门课程的成绩在下图的每个方块内。我们可以通过分组，取出每门课程的成绩。&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874600" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;第3关，分组&lt;/p&gt; &lt;p&gt;分组，并使用最大值函数max取出上图每个方块里的最大值&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;select 学号,
max(case 课程号 when &amp;apos;0001&amp;apos; then 成绩 else 0 end) as &amp;apos;课程号0001&amp;apos;,
max(case 课程号 when &amp;apos;0002&amp;apos; then 成绩 else 0 end) as &amp;apos;课程号0002&amp;apos;,
max(case 课程号 when &amp;apos;0003&amp;apos; then 成绩 else 0 end) as &amp;apos;课程号0003&amp;apos;
from score
group by 学号;&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;这样我们就得到了目标表（行列互换）&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/remote/1460000040874601" title=""&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;作者：sh_c_2450957609  &lt;br /&gt;blog.csdn.net/u010565545/article/details/100785261&lt;/p&gt; &lt;p&gt;  &lt;img alt="" src="https://segmentfault.com/img/bVbHCzg" title=""&gt;&lt;/img&gt;&lt;/p&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>数据库 sql 后端 运维 程序员</category>
      <guid isPermaLink="true">https://itindex.net/detail/61860-%E5%B8%B8%E8%A7%81-sql-%E9%9D%A2%E8%AF%95</guid>
      <pubDate>Wed, 27 Oct 2021 22:28:15 CST</pubDate>
    </item>
    <item>
      <title>何为多标签分类？这里有几种实用的经典方法</title>
      <link>https://itindex.net/detail/61820-%E6%A0%87%E7%AD%BE-%E5%88%86%E7%B1%BB-%E7%BB%8F%E5%85%B8</link>
      <description>&lt;section&gt;众所周知，二分类任务旨在将给定的输入分为 0 和 1 两类。而多标签分类（又称多目标分类）一次性地根据给定输入预测多个二分类目标。例如，模型可以预测给定的图片是一条狗还是一只猫，同时预测其毛皮是长还是短。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;在多分类任务中，预测目标是互斥的，这意味着一个输入可以对应于多个分类。本文将介绍一些可能提升多标签分类模型性能的小技巧。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;&lt;strong&gt;模型评估函数&lt;/strong&gt;&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;通过在「每一列」（分类标签）上计算模型评估函数并取得分均值，我们可以将大多数二分类评估函数用于多标签分类任务。对数损失或二分类&lt;mark data-type=concepts data-id=1786086f-5b63-4eee-b9ed-dad4d64cdc86&gt;交叉熵&lt;/mark&gt;就是其中一种评估函数。为了更好地考虑到类别不均衡现象，我们可以使用 ROC-AUC 作为评估函数。&lt;/section&gt;&lt;p&gt;&lt;img data-ratio="0.75" data-s="300,640" src="https://image.jiqizhixin.com/uploads/editor/27b5d6fd-9094-4ac1-98db-3b66f0eccbf6/640.png" data-type="png" data-w="700" data-imgqrcoded="1" class="fr-fic fr-dib" style="width: 700%;"&gt;&lt;/p&gt;&lt;section&gt;&lt;em&gt;图 1：ROC-AUC 曲线&lt;/em&gt;&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;&lt;strong&gt;建模技巧&lt;/strong&gt;&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;在介绍构建特征的技巧之前，本文将介绍一些设计适用于多标签分类场景的模型的小技巧。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;对于大多数非&lt;mark data-type=tech_methods data-id=72b0bcc0-d8f9-4edd-919f-fa7c2560388c&gt;神经网络&lt;/mark&gt;模型而言，我们唯一的选择是为每个目标训练一个分类器，然后将预测结果融合起来。为此，「scikit-learn」程序库提供了一个简单的封装类「OneVsRestClassifier」。尽管这个封装类可以使分类器能够执行多标签任务，但我们不应采用这种方法，其弊端如下：（1）我们会为每个目标训练一个新模型，因此训练时间相对较长。（2）模型无法学习不同标签之间的关系或标签的相关性。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;第二个问题可以通过执行一个两阶段训练过程来解决。其中，我们将目标的预测结果和原始特征相结合，作为第二阶段训练的输入。这样做的缺点是，由于需要训练的模型数量是之前的两倍，训练时间将大幅度提升。&lt;mark data-type=tech_methods data-id=72b0bcc0-d8f9-4edd-919f-fa7c2560388c&gt;神经网络&lt;/mark&gt;（NN）则适用于这种场景，其中标签的数量即为网络中输出&lt;mark data-type=concepts data-id=b5cce590-1c61-4d22-8e75-fe74128079c3&gt;神经元&lt;/mark&gt;的数量。我们可以直接将任意的二分类损失应用于&lt;mark data-type=tech_methods data-id=72b0bcc0-d8f9-4edd-919f-fa7c2560388c&gt;神经网络&lt;/mark&gt;模型，同时该模型会输出所有的目标。此时，我们只需要训练一个模型，且网络可以通过输出&lt;mark data-type=concepts data-id=b5cce590-1c61-4d22-8e75-fe74128079c3&gt;神经元&lt;/mark&gt;学习不同标签的相关性，从而解决上文中提出的非&lt;mark data-type=tech_methods data-id=72b0bcc0-d8f9-4edd-919f-fa7c2560388c&gt;神经网络&lt;/mark&gt;模型的两个问题。&lt;/section&gt;&lt;p&gt;&lt;img data-ratio="0.7615780445969125" data-s="300,640" src="https://image.jiqizhixin.com/uploads/editor/87a41475-ddd8-4c14-8a5b-3d68ca4fd6a5/640.png" data-type="png" data-w="583" data-imgqrcoded="1" class="fr-fic fr-dib" style="width: 700%;"&gt;&lt;/p&gt;&lt;section&gt;&lt;em&gt;图 2：&lt;mark data-type=tech_methods data-id=72b0bcc0-d8f9-4edd-919f-fa7c2560388c&gt;神经网络&lt;/mark&gt;&lt;/em&gt;&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;&lt;strong&gt;有监督的&lt;mark data-type=tech_tasks data-id=d1095f57-1940-4e97-8738-8bcb7e4e2d17&gt;特征选择&lt;/mark&gt;方法&lt;/strong&gt;&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;在开始&lt;mark data-type=tech_tasks data-id=898dc2c6-690b-4c29-82b6-f79e7b71d329&gt;特征工程&lt;/mark&gt;或&lt;mark data-type=tech_tasks data-id=d1095f57-1940-4e97-8738-8bcb7e4e2d17&gt;特征选择&lt;/mark&gt;之前，需要对特征进行归一化和标准化处理。使用「scikit-learn」库中的「Quantile Transformer」将减小数据的&lt;mark data-type=concepts data-id=8813e986-a020-4faf-9be4-d8e6c63bd46e&gt;偏度&lt;/mark&gt;，使特征服从正态分布。此外，还可以通过对数据采取「减去均值，除以标准差」的操作，对特征进行标准化处理。该过程与「Quantile Transformer」完成了类似的工作，其目的都是对数据进行变换，使数据变得更加鲁棒。然而，「Quantile Transformer」的计算开销较高。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;大多数算法都是为单一目标设计的，因此使用有监督&lt;mark data-type=tech_tasks data-id=d1095f57-1940-4e97-8738-8bcb7e4e2d17&gt;特征选择&lt;/mark&gt;方法稍微有些困难。为了解决这个问题，我们可以将多标签分类任务转化为多类&lt;mark data-type=concepts data-id=aaeb1c15-66f2-4822-91bb-b441607f9ecf&gt;分类问题&lt;/mark&gt;。「Label Powerset」就是其中一种流行的解决方案，它将训练数据中的每一个独特的标签组合转化为一个类。「scikit-multilearn」程序库中包含实现该方案的工具。&lt;/section&gt;&lt;p&gt;&lt;img data-ratio="0.2842857142857143" data-s="300,640" src="https://image.jiqizhixin.com/uploads/editor/dbb29f48-ac4c-4c42-b382-89dbecb1287c/640.png" data-type="png" data-w="700" data-imgqrcoded="1" class="fr-fic fr-dib" style="width: 700%;"&gt;&lt;/p&gt;&lt;section&gt;&lt;em&gt;图 3：Label Powerset 方法&lt;/em&gt;&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;在完成转换后，我们可以使用「&lt;mark data-type=concepts data-id=ecbad6d7-cde5-46ea-9bc6-960549585514&gt;信息增益&lt;/mark&gt;」和「&lt;mark data-type=concepts data-id=af8f95fc-c9f8-4525-911f-1ce70d1fcd8a&gt;卡方&lt;/mark&gt;」等方法来挑选特征。尽管这种方法是可行的，但是却很难处理上百甚至上千对不同的独特标签组合。此时，使用无监督&lt;mark data-type=tech_tasks data-id=d1095f57-1940-4e97-8738-8bcb7e4e2d17&gt;特征选择&lt;/mark&gt;方法可能更合适。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;&lt;strong&gt;无监督&lt;mark data-type=tech_tasks data-id=d1095f57-1940-4e97-8738-8bcb7e4e2d17&gt;特征选择&lt;/mark&gt;方法&lt;/strong&gt;&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;在无监督方法中，我们不需要考虑多标签任务的特性，这是因为无标签方法并不依赖于标签。典型的无监督&lt;mark data-type=tech_tasks data-id=d1095f57-1940-4e97-8738-8bcb7e4e2d17&gt;特征选择&lt;/mark&gt;方法包括：&lt;/section&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;mark data-type=tech_methods data-id=c9520edd-b2a1-4d42-9736-9885456c2280&gt;主成分分析&lt;/mark&gt;（PCA）或其它的&lt;mark data-type=tech_methods data-id=e8b8f7cb-7950-4d85-9558-b27ed2af7a24&gt;因子分析&lt;/mark&gt;方法。此类方法会去除掉特征中的冗余信息，并为模型抽取出有用的特征。请确保在使用 PCA 之前对数据进行标准化处理，从而使每个特征对分析的贡献相等。另一个使用 PCA 的技巧是，我们可以将该算法简化后的数据作为模型可选择使用的额外信息与原始数据连接起来，而不是直接使用简化后的数据。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;方差阈值。这是一种简单有效的降低特征维度的方法。我们丢弃具有低方差或离散型的特征。可以通过找到一个更好的选择阈值对此进行优化，0.5 是一个不错的初始阈值。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;mark data-type=concepts data-id=de069734-8912-43fb-b365-3b014165bc4d&gt;聚类&lt;/mark&gt;。通过根据输入数据创建&lt;mark data-type=concepts data-id=de069734-8912-43fb-b365-3b014165bc4d&gt;聚类&lt;/mark&gt;簇来构建新特征，然后将相应的&lt;mark data-type=concepts data-id=de069734-8912-43fb-b365-3b014165bc4d&gt;聚类&lt;/mark&gt;分配给每一行输入数据，作为一列新的特征。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;img data-ratio="1.076036866359447" data-s="300,640" src="https://image.jiqizhixin.com/uploads/editor/4809e0ca-9ee9-490c-82bf-b58b8995045a/640.png" data-type="png" data-w="434" data-imgqrcoded="1" class="fr-fic fr-dib" style="width: 700%;"&gt;&lt;/p&gt;&lt;section&gt;&lt;em&gt;图 4：K - 均值&lt;mark data-type=concepts data-id=de069734-8912-43fb-b365-3b014165bc4d&gt;聚类&lt;/mark&gt;&lt;/em&gt;&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;&lt;strong&gt;&lt;mark data-type=tech_methods data-id=c3eb4c40-0c52-43ef-a8ea-21152e4d29be&gt;上采样&lt;/mark&gt;方法&lt;/strong&gt;&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;当&lt;mark data-type=concepts data-id=36ed3828-6811-4e98-ae02-961092c733a4&gt;分类数据&lt;/mark&gt;高度不均衡时，可以使用&lt;mark data-type=tech_methods data-id=c3eb4c40-0c52-43ef-a8ea-21152e4d29be&gt;上采样&lt;/mark&gt;方法为稀有类生成人造样本，从而让模型关注稀有类。为了在多标签场景下创建新样本，我们可以使用多标签合成少数类过采样技术（MLSMOTE）。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;代码链接：https://github.com/niteshsukhwani/MLSMOTE&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;该方法由原始的 SMOTE 方法修改而来。在生成少数类的数据并分配少数标签后，我们还通过统计每个标签在相邻数据点中出现的次数来生成其它相关的标签，并保留出现频次高于一半统计的数据点的标签。&lt;/section&gt;&lt;section&gt;&lt;br&gt;&lt;/section&gt;&lt;section&gt;&lt;em&gt;原文链接：https://andy-wang.medium.com/bags-of-tricks-for-multi-label-classification-dc54b87f79ec&lt;/em&gt;&lt;/section&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/61820-%E6%A0%87%E7%AD%BE-%E5%88%86%E7%B1%BB-%E7%BB%8F%E5%85%B8</guid>
      <pubDate>Tue, 12 Oct 2021 15:01:57 CST</pubDate>
    </item>
    <item>
      <title>全球分布式数据库遇到的经典问题</title>
      <link>https://itindex.net/detail/61317-%E5%85%A8%E7%90%83-%E5%88%86%E5%B8%83-%E6%95%B0%E6%8D%AE%E5%BA%93</link>
      <description>&lt;p&gt;全球分布式数据库因为地理距离较远(上万公里), 网络通信延迟一般在 100ms 级别, 所以只能采取异步复制的方案. 采取异步复制方案, 那就决定了最终数据被复制的时效性无法得到保证, 例如正常情况仅仅比网络延迟多几毫秒(100ms+). 但坏情况时, 例如, 因为网络线路不好, 数据可能要花费数秒甚至数分钟才能同步. 这就导致了非常恼人的用户体验.&lt;/p&gt;
 &lt;p&gt;考虑这样的场景:&lt;/p&gt;
 &lt;blockquote&gt;
  &lt;p&gt;某网络游戏平台的用户 A 在中国, 而用户 B 是他曾经的邻居, 目前在美国. 某日, 用户 A 将游戏中的道具转给了用户 B, A 在游戏中看到了明确的操作成功的提示, 而且刷新也确认道具已经转交.&lt;/p&gt;
  &lt;p&gt;A 在私下用微信告知了这个操作, 然后让 B 在游戏中查看自己的道具背包.&lt;/p&gt;
  &lt;p&gt;该游戏平台在中国有一个数据库, 在美国也有一个数据库, 两地的数据库是异步复制(最终一致性)的. 因为游戏平台自己的网络线路问题, 这个操作的数据一直没有同步到美国. 但是, 微信所使用的网络线路没有问题, B 收到了 A 的微信消息.&lt;/p&gt;
  &lt;p&gt;B 在美国不断地刷新, 一直看不到道具, 这让他非常疑惑. 明明 A 说道具已经转交了呀, 而且还发截图了.&lt;/p&gt;
&lt;/blockquote&gt;
 &lt;p&gt;这就是经典的异步复制(最终一致性)导致的问题. 要怎么解决呢? 有很多方案, 但是, 正如”没有银弹”一样, 每一种方案都有缺陷. 我们一种一种地分析.&lt;/p&gt;
 &lt;p&gt;首先, 我们把结构简化, 整个系统只有两个数据库, 分别在中国和美国, 还有两个用户, A 和 B 分别在中国和美国. A 和 B 虽然通过游戏平台的业务逻辑代码访问数据, 但我们简化, 让他们直接访问数据, 让他们可以直接看到数据库的数据.&lt;/p&gt;
 &lt;h3&gt;方案1 - 用户读回源&lt;/h3&gt;
 &lt;p&gt;这个方案很直观, 既然 A 是在中国做的操作, 写的是中国的数据库, 那么 B 也应该访问中国的数据, 而不是美国的数据库. 如果这样做, 绝对不会出现不一致的情况. 也就是说, 单点存储没有一致性问题.&lt;/p&gt;
 &lt;p&gt;但是, B 在什么情况下应该回源访问中国的数据库呢? 如果他每一次查看背包, 都要访问中国的数据库, 那么他会觉得游戏平台的服务非常”慢”. 而平台在美国部署的数据库没有起作用, 因为部署美国数据库的一个初衷就是让美国的用户访问速度”快”起来.&lt;/p&gt;
 &lt;h3&gt;方案2 - 用户写多处&lt;/h3&gt;
 &lt;p&gt;这个方案也很直观, 用户 A 不仅仅写中国的数据库, 还主动连接美国的数据库写, 双写. 所以, 只要写成功, B 在美国就能立即看到, 因为已经写了美国的数据库啊…&lt;/p&gt;
 &lt;p&gt;这个方案也有问题, 第一个问题是慢的问题, A 要连接美国的数据库写数据, 显然会很慢. 但是, 没办法, 要么读慢, 要么写慢, 一致性只能用通信来保证, 而通信又受光速所限, 逃不掉.&lt;/p&gt;
 &lt;p&gt;第二个问题是, 如果写中国数据库成功, 而写美国数据成功, 那么用户应该认为写操作了还是没成功呢? 这个问题没有唯一解, 只能用户自己决定. 如果用户认为成功了, 那么就会出现开头例子所说的不一致的问题. 如果认为没成功, 那么用户只能不断重试. 哈哈, 这就是经典的 CAP 理论, 想要一致性, 就必须要放弃严格的一致性. 不过, 我们开头举的例子是追求一致性的, 所以, 结论是: 不成功, 用户重试.&lt;/p&gt;
 &lt;h3&gt;方案3 - 数据库强一致性读写&lt;/h3&gt;
 &lt;p&gt;前面的两种方案, 不仅有缺陷, 重要的是, 把责任全推给用户. 其实, 数据库本身可以做很多事, 如果数据库做了这些事, 用户就能省功夫. 所以, 我们看看数据库系统能做什么.&lt;/p&gt;
 &lt;p&gt;如果把中国和美国两个数据库共同组成一个 raft 复制组(集群), 这样的话, 似乎能解决问题? 等等, raft 具有单一的固定 leader, 所以, 如果 leader 在中国, 美国用户肯定要回源到中国写数据. 但是, 我们可以提供配套的 SDK, 用户不需要关心自己有没有回源.&lt;/p&gt;
 &lt;p&gt;读操作也要回源, 无论用 raft 还是 paxos, 都是基于通信, 所谓通信, 就是回源. 不过, 可以优化回源的数据量, 例如, raft 就可以通过 ReadIndex 技术只回源 binlog 序号, 减少了通信数据量.&lt;/p&gt;
 &lt;p&gt;这个方案无论是写还是读, 都很慢, 方案不好. 这也违反了”小范围同步复制(强一致), 大范围异步复制(最终一致)”的原则.&lt;/p&gt;
 &lt;h3&gt;方案4 - 数据库提供同步(sync)原语&lt;/h3&gt;
 &lt;p&gt;“小范围同步复制(强一致), 大范围异步复制(最终一致)”, 这个原则是真理, 不能违反. 所以, 数据库自己不能解决全部问题, 还是需要用户一起配合.&lt;/p&gt;
 &lt;p&gt;借鉴 Memory Barrier 思想, 数据库可以提供一些同步(sync)原语, 以确保数据能同步到期望的地方. 数据同步仍然由数据库来做, 脏活累活由数据库来做, 用户只需要提出请求.&lt;/p&gt;
 &lt;p&gt;数据库提供 sync_write 原语, 用户 A 在中国写入数据库之后, 请求数据库 sync_write. 数据库收到该请求, 立即获取本地的 binlog 序号, 然后向美国查询 binlog 序号, 如果美国的序号比中国的序号小, 说明之前的写入操作可能还没有同步到美国,   &lt;strong&gt;等待&lt;/strong&gt;, 然后继续轮询. 直到确认同步状态后, 再返回响应给用户 A. 这时, 用户 A 再私下通过微信告诉 B 去查看游戏背包, B 一定会立即看到更新.&lt;/p&gt;
 &lt;p&gt;数据库提供 sync_read 原语, 用户 B 在美国读取数据前, 先请求数据库 sync_read. 数据库收到该请求, 立即向中国查询最新的 binlog 序号, 然后和自己本地的序号比较. 如果美国的序号比中国的序号小, 那么就  &lt;strong&gt;等待&lt;/strong&gt;, 然后继续比较一次. 直至确认美国的序号等于或者大于刚才查询到的中国的序号, 这才返回响应. B 拿到响应后, 再去查看游戏背包, 一定会看到更新. 注意: 查询中国的序号只做一次.&lt;/p&gt;
 &lt;p&gt;只要用户 A sync_write, 或者用户 B sync_read, 就能满足一致性, 不需要两人同时做. 而其它的正常请求, 不需要这两个同步原语, 不会有速度慢的问题.&lt;/p&gt;
 &lt;h3&gt;总结&lt;/h3&gt;
 &lt;p&gt;因为地理距离较远而造成网络通信延迟, 这是无法避免. 只要想避免出现不一致的情况, 就必须进行回源(通信). 可以在写的时候通信, 也可以在读的时候通信. 数据库可以提供灵活的手段让用户选择, 让用户自己决定. 而用户(应用开发)自己要区分哪些操作需要一致性, 哪些不需要. 脏活累活可以交给数据库做, 但用户自己也要做细分.&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;没有银弹, 切不可痴心妄想!&lt;/strong&gt;&lt;/p&gt;


 &lt;h3&gt;Related posts:&lt;/h3&gt; &lt;ol&gt;  &lt;li&gt;   &lt;a href="http://www.ideawu.net/blog/archives/1105.html" rel="bookmark" title="Permanent Link: Raft &amp;#36873;&amp;#20027;&amp;#20248;&amp;#21270;&amp;#20043; PreVote"&gt;Raft 选主优化之 PreVote&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://www.ideawu.net/blog/archives/1108.html" rel="bookmark" title="Permanent Link: &amp;#8220;&amp;#19968;&amp;#33268;&amp;#24615;&amp;#8221;&amp;#26159;&amp;#38236;&amp;#33457;&amp;#27700;&amp;#26376;"&gt;“一致性”是镜花水月&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://www.ideawu.net/blog/archives/1120.html" rel="bookmark" title="Permanent Link: Paxos&amp;#21644;Raft&amp;#35835;&amp;#20248;&amp;#21270; &amp;#8211; Quorum Read &amp;#21644; Read Index"&gt;Paxos和Raft读优化 – Quorum Read 和 Read Index&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://www.ideawu.net/blog/archives/1117.html" rel="bookmark" title="Permanent Link: &amp;#20998;&amp;#24067;&amp;#24335;&amp;#23384;&amp;#20648;&amp;#21517;&amp;#35789;&amp;#35299;&amp;#26512; &amp;#8211; &amp;#19968;&amp;#33268;&amp;#24615;"&gt;分布式存储名词解析 – 一致性&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://www.ideawu.net/blog/archives/1106.html" rel="bookmark" title="Permanent Link: &amp;#20026;&amp;#20160;&amp;#20040; Leader Based &amp;#30340;&amp;#20998;&amp;#24067;&amp;#24335;&amp;#21327;&amp;#35758; Raft &amp;#26159;&amp;#26356;&amp;#22909;&amp;#30340;"&gt;为什么 Leader Based 的分布式协议 Raft 是更好的&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>分布式 数据库</category>
      <guid isPermaLink="true">https://itindex.net/detail/61317-%E5%85%A8%E7%90%83-%E5%88%86%E5%B8%83-%E6%95%B0%E6%8D%AE%E5%BA%93</guid>
      <pubDate>Fri, 09 Apr 2021 22:03:57 CST</pubDate>
    </item>
    <item>
      <title>什么是mmap？ 经典题目</title>
      <link>https://itindex.net/detail/61275-mmap-%E7%BB%8F%E5%85%B8</link>
      <description>&lt;div&gt;  &lt;p&gt;平时在面试中你肯定会经常碰见的问题就是：RocketMQ为什么快？Kafka为什么快？什么是mmap？&lt;/p&gt;
  &lt;p&gt;这一类的问题都逃不过的一个点就是   &lt;strong&gt;零拷贝&lt;/strong&gt;，虽然还有一些其他的原因，但是今天我们的话题主要就是零拷贝。&lt;/p&gt;
  &lt;h1&gt;传统IO&lt;/h1&gt;
  &lt;p&gt;在开始谈零拷贝之前，首先要对传统的IO方式有一个概念。&lt;/p&gt;
  &lt;p&gt;基于传统的IO方式，底层实际上通过调用   &lt;code&gt;read()&lt;/code&gt;和   &lt;code&gt;write()&lt;/code&gt;来实现。&lt;/p&gt;
  &lt;p&gt;通过   &lt;code&gt;read()&lt;/code&gt;把数据从硬盘读取到内核缓冲区，再复制到用户缓冲区；然后再通过   &lt;code&gt;write()&lt;/code&gt;写入到   &lt;code&gt;socket缓冲区&lt;/code&gt;，最后写入网卡设备。&lt;/p&gt;
  &lt;p&gt;   &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3b69a3bdc26c4bf9be84cf3677d04fef~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
  &lt;p&gt;整个过程发生了   &lt;strong&gt;4次用户态和内核态的上下文切换&lt;/strong&gt;和   &lt;strong&gt;4次拷贝&lt;/strong&gt;，具体流程如下：&lt;/p&gt;
  &lt;ol&gt;
   &lt;li&gt;用户进程通过    &lt;code&gt;read()&lt;/code&gt;方法向操作系统发起调用，此时上下文从用户态转向内核态&lt;/li&gt;
   &lt;li&gt;DMA控制器把数据从硬盘中拷贝到读缓冲区&lt;/li&gt;
   &lt;li&gt;CPU把读缓冲区数据拷贝到应用缓冲区，上下文从内核态转为用户态，    &lt;code&gt;read()&lt;/code&gt;返回&lt;/li&gt;
   &lt;li&gt;用户进程通过    &lt;code&gt;write()&lt;/code&gt;方法发起调用，上下文从用户态转为内核态&lt;/li&gt;
   &lt;li&gt;CPU将应用缓冲区中数据拷贝到socket缓冲区&lt;/li&gt;
   &lt;li&gt;DMA控制器把数据从socket缓冲区拷贝到网卡，上下文从内核态切换回用户态，    &lt;code&gt;write()&lt;/code&gt;返回&lt;/li&gt;
&lt;/ol&gt;
  &lt;p&gt;   &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/3b0c6e94c9cc493c8d1cad2e07b9ddb0~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
  &lt;p&gt;那么，这里指的   &lt;strong&gt;用户态&lt;/strong&gt;、   &lt;strong&gt;内核态&lt;/strong&gt;指的是什么？上下文切换又是什么？&lt;/p&gt;
  &lt;p&gt;简单来说，用户空间指的就是用户进程的运行空间，内核空间就是内核的运行空间。&lt;/p&gt;
  &lt;p&gt;如果进程运行在内核空间就是内核态，运行在用户空间就是用户态。&lt;/p&gt;
  &lt;p&gt;为了安全起见，他们之间是互相隔离的，而在用户态和内核态之间的上下文切换也是比较耗时的。&lt;/p&gt;
  &lt;p&gt;从上面我们可以看到，一次简单的IO过程产生了4次上下文切换，这个无疑在高并发场景下会对性能产生较大的影响。&lt;/p&gt;
  &lt;p&gt;那么什么又是   &lt;strong&gt;DMA&lt;/strong&gt;拷贝呢？&lt;/p&gt;
  &lt;p&gt;因为对于一个IO操作而言，都是通过CPU发出对应的指令来完成，但是相比CPU来说，IO的速度太慢了，CPU有大量的时间处于等待IO的状态。&lt;/p&gt;
  &lt;p&gt;因此就产生了DMA（Direct Memory Access）直接内存访问技术，本质上来说他就是一块主板上独立的芯片，通过它来进行内存和IO设备的数据传输，从而减少CPU的等待时间。&lt;/p&gt;
  &lt;p&gt;但是无论谁来拷贝，频繁的拷贝耗时也是对性能的影响。&lt;/p&gt;
  &lt;h1&gt;零拷贝&lt;/h1&gt;
  &lt;blockquote&gt;
   &lt;p&gt;零拷贝技术是指计算机执行操作时，CPU不需要先将数据从某处内存复制到另一个特定区域，这种技术通常用于通过网络传输文件时节省CPU周期和内存带宽。&lt;/p&gt;
&lt;/blockquote&gt;
  &lt;p&gt;那么对于零拷贝而言，并非真的是完全没有数据拷贝的过程，只不过是减少用户态和内核态的切换次数以及CPU拷贝的次数。&lt;/p&gt;
  &lt;p&gt;这里，仅仅有针对性的来谈谈几种常见的零拷贝技术。&lt;/p&gt;
  &lt;h3&gt;mmap+write&lt;/h3&gt;
  &lt;p&gt;mmap+write简单来说就是使用   &lt;code&gt;mmap&lt;/code&gt;替换了read+write中的read操作，减少了一次CPU的拷贝。&lt;/p&gt;
  &lt;p&gt;   &lt;code&gt;mmap&lt;/code&gt;主要实现方式是将读缓冲区的地址和用户缓冲区的地址进行映射，内核缓冲区和应用缓冲区共享，从而减少了从读缓冲区到用户缓冲区的一次CPU拷贝。&lt;/p&gt;
  &lt;p&gt;   &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/b306256e43ba468abd5137775769cac1~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
  &lt;p&gt;整个过程发生了   &lt;strong&gt;4次用户态和内核态的上下文切换&lt;/strong&gt;和   &lt;strong&gt;3次拷贝&lt;/strong&gt;，具体流程如下：&lt;/p&gt;
  &lt;ol&gt;
   &lt;li&gt;用户进程通过    &lt;code&gt;mmap()&lt;/code&gt;方法向操作系统发起调用，上下文从用户态转向内核态&lt;/li&gt;
   &lt;li&gt;DMA控制器把数据从硬盘中拷贝到读缓冲区&lt;/li&gt;
   &lt;li&gt;    &lt;strong&gt;上下文从内核态转为用户态，mmap调用返回&lt;/strong&gt;&lt;/li&gt;
   &lt;li&gt;用户进程通过    &lt;code&gt;write()&lt;/code&gt;方法发起调用，上下文从用户态转为内核态&lt;/li&gt;
   &lt;li&gt;    &lt;strong&gt;CPU将读缓冲区中数据拷贝到socket缓冲区&lt;/strong&gt;&lt;/li&gt;
   &lt;li&gt;DMA控制器把数据从socket缓冲区拷贝到网卡，上下文从内核态切换回用户态，    &lt;code&gt;write()&lt;/code&gt;返回&lt;/li&gt;
&lt;/ol&gt;
  &lt;p&gt;   &lt;code&gt;mmap&lt;/code&gt;的方式节省了一次CPU拷贝，同时由于用户进程中的内存是虚拟的，只是映射到内核的读缓冲区，所以可以节省一半的内存空间，比较适合大文件的传输。&lt;/p&gt;
  &lt;h3&gt;sendfile&lt;/h3&gt;
  &lt;p&gt;相比   &lt;code&gt;mmap&lt;/code&gt;来说，   &lt;code&gt;sendfile&lt;/code&gt;同样减少了一次CPU拷贝，而且还减少了2次上下文切换。&lt;/p&gt;
  &lt;p&gt;   &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a88054a6ce4b48f498e5a1fb6b5ace55~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
  &lt;p&gt;   &lt;code&gt;sendfile&lt;/code&gt;是Linux2.1内核版本后引入的一个系统调用函数，通过使用   &lt;code&gt;sendfile&lt;/code&gt;数据可以直接在内核空间进行传输，因此避免了用户空间和内核空间的拷贝，同时由于使用   &lt;code&gt;sendfile&lt;/code&gt;替代了   &lt;code&gt;read+write&lt;/code&gt;从而节省了一次系统调用，也就是2次上下文切换。&lt;/p&gt;
  &lt;p&gt;   &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d6d68cc34030404a85d30d39c60ab3e4~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
  &lt;p&gt;整个过程发生了   &lt;strong&gt;2次用户态和内核态的上下文切换&lt;/strong&gt;和   &lt;strong&gt;3次拷贝&lt;/strong&gt;，具体流程如下：&lt;/p&gt;
  &lt;ol&gt;
   &lt;li&gt;用户进程通过    &lt;code&gt;sendfile()&lt;/code&gt;方法向操作系统发起调用，上下文从用户态转向内核态&lt;/li&gt;
   &lt;li&gt;DMA控制器把数据从硬盘中拷贝到读缓冲区&lt;/li&gt;
   &lt;li&gt;CPU将读缓冲区中数据拷贝到socket缓冲区&lt;/li&gt;
   &lt;li&gt;DMA控制器把数据从socket缓冲区拷贝到网卡，上下文从内核态切换回用户态，    &lt;code&gt;sendfile&lt;/code&gt;调用返回&lt;/li&gt;
&lt;/ol&gt;
  &lt;p&gt;   &lt;code&gt;sendfile&lt;/code&gt;方法IO数据对用户空间完全不可见，所以只能适用于完全不需要用户空间处理的情况，比如静态文件服务器。&lt;/p&gt;
  &lt;h3&gt;sendfile+DMA Scatter/Gather&lt;/h3&gt;
  &lt;p&gt;Linux2.4内核版本之后对   &lt;code&gt;sendfile&lt;/code&gt;做了进一步优化，通过引入新的硬件支持，这个方式叫做DMA Scatter/Gather 分散/收集功能。&lt;/p&gt;
  &lt;p&gt;它将读缓冲区中的数据描述信息--内存地址和偏移量记录到socket缓冲区，由 DMA 根据这些将数据从读缓冲区拷贝到网卡，相比之前版本减少了一次CPU拷贝的过程&lt;/p&gt;
  &lt;p&gt;   &lt;img alt="" src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/a97c4913546e4ee38f9a44cbec0b7a97~tplv-k3u1fbpfcp-zoom-1.image"&gt;&lt;/img&gt;&lt;/p&gt;
  &lt;p&gt;整个过程发生了   &lt;strong&gt;2次用户态和内核态的上下文切换&lt;/strong&gt;和   &lt;strong&gt;2次拷贝&lt;/strong&gt;，其中更重要的是完全没有CPU拷贝，具体流程如下：&lt;/p&gt;
  &lt;ol&gt;
   &lt;li&gt;用户进程通过    &lt;code&gt;sendfile()&lt;/code&gt;方法向操作系统发起调用，上下文从用户态转向内核态&lt;/li&gt;
   &lt;li&gt;DMA控制器利用scatter把数据从硬盘中拷贝到读缓冲区离散存储&lt;/li&gt;
   &lt;li&gt;CPU把读缓冲区中的文件描述符和数据长度发送到socket缓冲区&lt;/li&gt;
   &lt;li&gt;DMA控制器根据文件描述符和数据长度，使用scatter/gather把数据从内核缓冲区拷贝到网卡&lt;/li&gt;
   &lt;li&gt;    &lt;code&gt;sendfile()&lt;/code&gt;调用返回，上下文从内核态切换回用户态&lt;/li&gt;
&lt;/ol&gt;
  &lt;p&gt;   &lt;code&gt;DMA gather&lt;/code&gt;和   &lt;code&gt;sendfile&lt;/code&gt;一样数据对用户空间不可见，而且需要硬件支持，同时输入文件描述符只能是文件，但是过程中完全没有CPU拷贝过程，极大提升了性能。&lt;/p&gt;
  &lt;h1&gt;应用场景&lt;/h1&gt;
  &lt;p&gt;对于文章开头说的两个场景：RocketMQ和Kafka都使用到了零拷贝的技术。&lt;/p&gt;
  &lt;p&gt;对于MQ而言，无非就是生产者发送数据到MQ然后持久化到磁盘，之后消费者从MQ读取数据。&lt;/p&gt;
  &lt;p&gt;对于RocketMQ来说这两个步骤使用的是   &lt;code&gt;mmap+write&lt;/code&gt;，而Kafka则是使用   &lt;code&gt;mmap+write&lt;/code&gt;持久化数据，发送数据使用   &lt;code&gt;sendfile&lt;/code&gt;。&lt;/p&gt;
  &lt;h1&gt;总结&lt;/h1&gt;
  &lt;p&gt;由于CPU和IO速度的差异问题，产生了DMA技术，通过DMA搬运来减少CPU的等待时间。&lt;/p&gt;
  &lt;p&gt;传统的IO   &lt;code&gt;read+write&lt;/code&gt;方式会产生2次DMA拷贝+2次CPU拷贝，同时有4次上下文切换。&lt;/p&gt;
  &lt;p&gt;而通过   &lt;code&gt;mmap+write&lt;/code&gt;方式则产生2次DMA拷贝+1次CPU拷贝，4次上下文切换，通过内存映射减少了一次CPU拷贝，可以减少内存使用，适合大文件的传输。&lt;/p&gt;
  &lt;p&gt;   &lt;code&gt;sendfile&lt;/code&gt;方式是新增的一个系统调用函数，产生2次DMA拷贝+1次CPU拷贝，但是只有2次上下文切换。因为只有一次调用，减少了上下文的切换，但是用户空间对IO数据不可见，适用于静态文件服务器。&lt;/p&gt;
  &lt;p&gt;   &lt;code&gt;sendfile+DMA gather&lt;/code&gt;方式产生2次DMA拷贝，没有CPU拷贝，而且也只有2次上下文切换。虽然极大地提升了性能，但是需要依赖新的硬件设备支持。&lt;/p&gt;
  &lt;blockquote&gt;
   &lt;p&gt;参考：&lt;/p&gt;
   &lt;p&gt;    &lt;a href="https://juejin.cn/post/6844903949359644680#heading-19" target="_blank"&gt;juejin.cn/post/684490…&lt;/a&gt;&lt;/p&gt;
   &lt;p&gt;    &lt;a href="https://www.cnblogs.com/xiaolincoding/p/13719610.html" rel="nofollow noopener noreferrer" target="_blank"&gt;www.cnblogs.com/xiaolincodi…&lt;/a&gt;&lt;/p&gt;
   &lt;p&gt;    &lt;a href="https://time.geekbang.org/column/article/118657" rel="nofollow noopener noreferrer" target="_blank"&gt;time.geekbang.org/column/arti…&lt;/a&gt;&lt;/p&gt;
   &lt;p&gt;    &lt;a href="https://www.toutiao.com/i6898240850917114380/" rel="nofollow noopener noreferrer" target="_blank"&gt;www.toutiao.com/i6898240850…&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;&lt;/div&gt;  &lt;div&gt;&lt;/div&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/61275-mmap-%E7%BB%8F%E5%85%B8</guid>
      <pubDate>Wed, 17 Mar 2021 07:57:26 CST</pubDate>
    </item>
    <item>
      <title>经典复刻，诺基亚 6300 4G 开启预售：KaiOS 系统+骁龙 210，首发价 399 元</title>
      <link>https://itindex.net/detail/61113-%E7%BB%8F%E5%85%B8-%E5%A4%8D%E5%88%BB-%E8%AF%BA%E5%9F%BA%E4%BA%9A</link>
      <description>&lt;p&gt;IT之家12月26日消息 诺基亚 6300 4G 现已开启预售，搭载 KaiOS 系统，首发到手价 399 元。&lt;/p&gt; &lt;p&gt;  &lt;img alt="image.png" src="https://img.ithome.com/newsuploadfiles/2020/12/20201226080029_8352.jpg" title="image.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;诺基亚表示，6300 4G 在设计方面从 2007 年的初代诺基亚 6300 上汲取了一些灵感，但经过了现代化的改造，更加适合目前使用。&lt;/p&gt; &lt;p&gt;  &lt;img alt="image.png" src="https://img.ithome.com/newsuploadfiles/2020/12/20201226080046_5779.jpg" title="image.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;IT之家了解到，诺基亚 6300 4G 采用 2.4 英寸 QVGA 显示屏，支持 Wi-Fi、蓝牙与 FM 收音机，配备 3.5mm 耳机孔，内置 1500mAh 电池，官方称拥有 27.9 天待机时间，通话时间 8.2 小时。&lt;/p&gt; &lt;p&gt;  &lt;img alt="image.png" src="https://img.ithome.com/newsuploadfiles/2020/12/20201226080141_6292.jpg" title="image.png"&gt;&lt;/img&gt;&lt;/p&gt; &lt;p&gt;此外，诺基亚 6300 4G 搭载骁龙 210 处理器，支持 4G 全网通与双卡双待，其手机应用商店有 UC 浏览器、PDF 阅读器和二维码扫描器等应用。&lt;/p&gt; &lt;a href="https://union-click.jd.com/jdc?e=&amp;p=AyIGZRprFQMTBlUdWBIHFQBWKx9KWkxYZUIeUENQDEsFA1BWThgOTkRHXE4ZVRpaFAIUBFIeXBIBDV4QRwYlZndfAV4ESWByA1Z7WktXdnECTAxDch4LZR5aHQoXAFUcWCUBEABXHV8QARU3NnxSJQIXNwN1WxQDEwZcG1gWCiIHVhxfFwcaBl0TaxUFEw5dHlodAxoPVh5rFQoVNwlZCVRAIjdlGGslMhI3VisFewNBB1BIXBQHfF0OHhJSWUsEOxlYHAAVAlIeaxcDEwVX" target="_blank"&gt;  &lt;img src="https://img14.360buyimg.com/pop/jfs/t1/134818/29/20136/60223/5fd9aea2E094b42eb/058ece0eac32af84.jpg"&gt;&lt;/img&gt;京东诺基亚 NOKIA 6300 4G429元直达链接&lt;/a&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/61113-%E7%BB%8F%E5%85%B8-%E5%A4%8D%E5%88%BB-%E8%AF%BA%E5%9F%BA%E4%BA%9A</guid>
      <pubDate>Sat, 26 Dec 2020 08:02:44 CST</pubDate>
    </item>
    <item>
      <title>盘点 Spring Security 框架中的八大经典设计模式</title>
      <link>https://itindex.net/detail/60793-%E7%9B%98%E7%82%B9-spring-security</link>
      <description>&lt;p&gt;上次有小伙伴建议，源码分析太枯燥了，要是能够结合设计模式一起来，这样更有助于大家理解 Spring Security 源码，同时还能复习一波设计模式。&lt;/p&gt; &lt;p&gt;因此松哥今天就试着整一篇，和大家来聊一聊 Spring Security 中涉及到的设计模式，不过 Spring Security 中涉及到的设计模式还是非常多的，松哥这里讲几个，剩下的欢迎小伙伴们留言补充。&lt;/p&gt; &lt;h2&gt;1.模板方法模式&lt;/h2&gt; &lt;blockquote&gt;Template Pattern(模板方法模式)是一个抽象类公开定义了执行它的方法的模板。它的子类可以按需要重写方法实现，但调用将以抽象类中定义的方式进行，这是一种行为型模式。&lt;/blockquote&gt; &lt;p&gt;模板方法方式优点如下：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;在父类中提取了公共的部分代码，便于代码复用和扩展。&lt;/li&gt;  &lt;li&gt;部分方法是由子类实现的，子类可以通过扩展方式增加相应的功能，符合开闭原则。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;缺点如下：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;对每个不同的实现都需要定义一个子类，导致类的个数增加，系统更加复杂，设计也更加抽象。&lt;/li&gt;  &lt;li&gt;父类中的抽象方法由子类实现，子类执行的结果会影响父类的结果，增加了代码理解难度。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;介绍完模板方法模式，大家可能大概猜到了 Spring Security 中哪些地方用到模板方法模式了。&lt;/p&gt; &lt;p&gt;我举几个简单的例子。&lt;/p&gt; &lt;p&gt;第一个例子是 AbstractUserDetailsAuthenticationProvider 类的设计。大家都知道这个类是用来做验证的，认证的逻辑在这个方法中都定义好了，但是该类却定义了两个抽象方法：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;retrieveUser 该方法用户从数据源中获取用户对象。&lt;/li&gt;  &lt;li&gt;additionalAuthenticationChecks 该方法用来做额外的校验（登录凭证的校验）&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;这两个抽象方法是在 DaoAuthenticationProvider 中实现的。DaoAuthenticationProvider 的实现就是从数据库中加载用户，默认检验登录凭证也都是验证密码。&lt;/p&gt; &lt;p&gt;如果你的数据源来自其他地方，或者登录凭证不是密码，那么自定义类继承自 AbstractUserDetailsAuthenticationProvider 并重写它里边的这两个方法即可。&lt;/p&gt; &lt;h2&gt;2.责任链模式&lt;/h2&gt; &lt;blockquote&gt;Chain of Responsibility Pattern(责任链模式) ，在这种模式中，通常每个接收者都包含对另一个接收者的引用，如果一个对象不能处理该请求，那么它会把相同的请求传给下一个接收者，依此类推。在这个过程中，客户只需要将请求发送到责任链上即可，无须关心请求的处理细节和请求的传递过程，所以责任链将请求的发送者和请求的处理者解耦了。&lt;/blockquote&gt; &lt;p&gt;责任链模式优点如下：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;降低对象之间的耦合度。&lt;/li&gt;  &lt;li&gt;增强了系统的可扩展性。&lt;/li&gt;  &lt;li&gt;当工作流程发生变化，可以动态地改变链内的成员或者调动它们的次序。&lt;/li&gt;  &lt;li&gt;简化了对象之间的连接，每个对象只需保持一个指向其后继者的引用，不需保持其他所有处理者的引用。&lt;/li&gt;  &lt;li&gt;责任分担，每个类只需要处理自己该处理的工作，符合类的单一职责原则。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;缺点如下：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;对比较长的职责链，请求的处理可能涉及多个处理对象，系统性能将受到一定影响。&lt;/li&gt;  &lt;li&gt;职责链建立的合理性要靠客户端来保证，增加了客户端的复杂性。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;很明显，Spring Security 中的过滤器链就是一种责任链模式。一个请求到达后，被过滤器链中的过滤器逐个进行处理，过滤器链中的过滤器每个都具有不同的职能并且互不相扰，我们还可以通过 HttpSecurity 来动态配置过滤器链中的过滤器（即添加/删除过滤器链中的过滤器）。&lt;/p&gt; &lt;p&gt;具体的代码在 FilterChainProxy$VirtualFilterChain 中，如下：&lt;/p&gt; &lt;p&gt;那么接下来我们就来看看 VirtualFilterChain：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;private static class VirtualFilterChain implements FilterChain {
    private final FilterChain originalChain;
    private final List&amp;lt;Filter&amp;gt; additionalFilters;
    private final FirewalledRequest firewalledRequest;
    private final int size;
    private int currentPosition = 0;
    private VirtualFilterChain(FirewalledRequest firewalledRequest,
            FilterChain chain, List&amp;lt;Filter&amp;gt; additionalFilters) {
        this.originalChain = chain;
        this.additionalFilters = additionalFilters;
        this.size = additionalFilters.size();
        this.firewalledRequest = firewalledRequest;
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response)
            throws IOException, ServletException {
        if (currentPosition == size) {
            if (logger.isDebugEnabled()) {
                logger.debug(UrlUtils.buildRequestUrl(firewalledRequest)
                        + &amp;quot; reached end of additional filter chain; proceeding with original chain&amp;quot;);
            }
            // Deactivate path stripping as we exit the security filter chain
            this.firewalledRequest.reset();
            originalChain.doFilter(request, response);
        }
        else {
            currentPosition++;
            Filter nextFilter = additionalFilters.get(currentPosition - 1);
            if (logger.isDebugEnabled()) {
                logger.debug(UrlUtils.buildRequestUrl(firewalledRequest)
                        + &amp;quot; at position &amp;quot; + currentPosition + &amp;quot; of &amp;quot; + size
                        + &amp;quot; in additional filter chain; firing Filter: &amp;apos;&amp;quot;
                        + nextFilter.getClass().getSimpleName() + &amp;quot;&amp;apos;&amp;quot;);
            }
            nextFilter.doFilter(request, response, this);
        }
    }
}&lt;/code&gt;&lt;/pre&gt; &lt;ol&gt;  &lt;li&gt;VirtualFilterChain 类中首先声明了 5 个全局属性，originalChain 表示原生的过滤器链，也就是 Web Filter；additionalFilters 表示 Spring Security 中的过滤器链；firewalledRequest 表示当前请求；size 表示过滤器链中过滤器的个数；currentPosition 则是过滤器链遍历时候的下标。&lt;/li&gt;  &lt;li&gt;doFilter 方法就是 Spring Security 中过滤器挨个执行的过程，如果    &lt;code&gt;currentPosition == size&lt;/code&gt;，表示过滤器链已经执行完毕，此时通过调用 originalChain.doFilter 进入到原生过滤链方法中，同时也退出了 Spring Security 过滤器链。否则就从 additionalFilters 取出 Spring Security 过滤器链中的一个个过滤器，挨个调用 doFilter 方法。nextFilter.doFilter 就是过滤器链挨个往下走。&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;关于 FilterChainProxy 的介绍，参见：  &lt;a href="https://mp.weixin.qq.com/s/EZsChg5YG0TBadU4q_CAnA" rel="nofollow noreferrer"&gt;深入理解 FilterChainProxy【源码篇】&lt;/a&gt;&lt;/p&gt; &lt;h2&gt;3.策略模式&lt;/h2&gt; &lt;blockquote&gt;Strategy Pattern(策略模式)，它定义了一系列算法，将每一个算法封装起来，并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化，也称为政策模式(Policy)。&lt;/blockquote&gt; &lt;p&gt;策略模式的优点：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;策略模式提供了对“开闭原则”的完美支持，用户可以在不修改原有系统的基础上选择具体的策略，也可以灵活地扩展新的策略。&lt;/li&gt;  &lt;li&gt;策略模式提供了管理相关的策略的方式。&lt;/li&gt;  &lt;li&gt;策略模式提供了可以替换继承关系的办法。&lt;/li&gt;  &lt;li&gt;使用策略模式可以避免使用多重条件转移语句。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;策略模式的缺点：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;客户端必须知道所有的策略类，并自行决定使用哪一个策略类。&lt;/li&gt;  &lt;li&gt;策略模式将造成产生很多策略类（可以通过使用享元模式在一定程度上减少对象的数量）。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Spring Security 中使用策略模式的地方也有好几个。&lt;/p&gt; &lt;p&gt;第一个就是用户登录信息存储。&lt;/p&gt; &lt;p&gt;在 SecurityContextHolder 中定义登录用户信息存储的方法，就定义了三种不同的策略：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;public class SecurityContextHolder {
    // ~ Static fields/initializers
    // =====================================================================================

    public static final String MODE_THREADLOCAL = &amp;quot;MODE_THREADLOCAL&amp;quot;;
    public static final String MODE_INHERITABLETHREADLOCAL = &amp;quot;MODE_INHERITABLETHREADLOCAL&amp;quot;;
    public static final String MODE_GLOBAL = &amp;quot;MODE_GLOBAL&amp;quot;;
    public static final String SYSTEM_PROPERTY = &amp;quot;spring.security.strategy&amp;quot;;
    private static String strategyName = System.getProperty(SYSTEM_PROPERTY);
    private static SecurityContextHolderStrategy strategy;
}&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;用户可以自行选择使用哪一种策略！具体参见：  &lt;a href="https://mp.weixin.qq.com/s/4dcQ6lohB3sEcnkAXxdZwg" rel="nofollow noreferrer"&gt;在 Spring Security 中，我就想从子线程获取用户登录信息，怎么办？&lt;/a&gt;&lt;/p&gt; &lt;p&gt;还有一个就是 session 并发管理。&lt;/p&gt; &lt;p&gt;在 AbstractAuthenticationProcessingFilter#doFilter 方法中，有如下代码：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
        throws IOException, ServletException {
    //省略
        sessionStrategy.onAuthentication(authResult, request, response);
    //省略
}&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;这就是一种策略模式。&lt;/p&gt; &lt;p&gt;Session 并发管理可以参考：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;   &lt;a href="https://mp.weixin.qq.com/s/9SaNvVfiivWUIAe6OZgpZQ" rel="nofollow noreferrer"&gt;什么是会话固定攻击？Spring Boot 中要如何防御会话固定攻击？&lt;/a&gt;&lt;/li&gt;  &lt;li&gt;   &lt;a href="https://mp.weixin.qq.com/s/EAacxjaNg8BJRkTkGFLLpQ" rel="nofollow noreferrer"&gt;集群化部署，Spring Security 要如何处理 session 共享？&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;当然，这样的例子还有很多，我就不一一列举了。&lt;/p&gt; &lt;h2&gt;4.代理模式&lt;/h2&gt; &lt;blockquote&gt;Proxy Pattern(代理模式) ：给某一个对象提供一个代理，并由代理对象控制对原对象的引用，它是一种对象结构型模式。&lt;/blockquote&gt; &lt;p&gt;代理模式的优点：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;一定程度上降低了系统的耦合度。&lt;/li&gt;  &lt;li&gt;代理对象可以扩展目标对象的功能。&lt;/li&gt;  &lt;li&gt;代理对象可以保护目标对象。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;缺点：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;在客户端和真实对象之间增加了代理，可能会导致请求的处理速度变慢。&lt;/li&gt;  &lt;li&gt;增加了系统复杂度。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;代理模式在 Spring Security 中最重要的应用就是 Spring Security 过滤器链接入 Web Filter 的过程，使用了 Spring 提供的 DelegatingFilterProxy，这就是一个典型的代理模式：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;public class DelegatingFilterProxy extends GenericFilterBean {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        // Lazily initialize the delegate if necessary.
        Filter delegateToUse = this.delegate;
        if (delegateToUse == null) {
            synchronized (this.delegateMonitor) {
                delegateToUse = this.delegate;
                if (delegateToUse == null) {
                    WebApplicationContext wac = findWebApplicationContext();
                    if (wac == null) {
                        throw new IllegalStateException(&amp;quot;No WebApplicationContext found: &amp;quot; +
                                &amp;quot;no ContextLoaderListener or DispatcherServlet registered?&amp;quot;);
                    }
                    delegateToUse = initDelegate(wac);
                }
                this.delegate = delegateToUse;
            }
        }

        // Let the delegate perform the actual doFilter operation.
        invokeDelegate(delegateToUse, request, response, filterChain);
    }
}&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;当然还有其他很多地方也用到代理模式，我就不一一列举了，欢迎小伙伴们留言补充。&lt;/p&gt; &lt;h2&gt;5.适配器模式&lt;/h2&gt; &lt;blockquote&gt;Adapter Pattern(适配器模式)，大家平时用的手机充电器学名叫做电源适配器，它的作用是把 220V 的电压转为手机可用的 5V 电压。所以适配器模式其实也是类似作用，将一个接口转换成客户希望的另一个接口，适配器模式使接口不兼容的类可以一起工作。适配器模式又分为类适配器模式、对象适配器模式以及接口适配器模式。&lt;/blockquote&gt; &lt;p&gt;适配器模式的优点：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;解耦，通过引入一个适配器类来重用现有的适配者类，而无须修改原有代码。&lt;/li&gt;  &lt;li&gt;增加了类的透明性和复用性。&lt;/li&gt;  &lt;li&gt;具有较好的灵活性和扩展性都。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;缺点：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;由于 Java 不支持多重继承，一次最多只能适配一个适配者类，而且目标抽象类只能为抽象类，不能为具体类，其使用有一定的局限性。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Spring Security 中的适配器模式也是非常多的，例如我们最为常见的 WebSecurityConfigurerAdapter，该类让两个原本不相关的 WebSecurity 和 HttpSecurity 能够在一起工作。&lt;/p&gt; &lt;p&gt;具体参见：[深入理解 WebSecurityConfigurerAdapter【源码篇】]()&lt;/p&gt; &lt;h2&gt;6.建造者模式&lt;/h2&gt; &lt;blockquote&gt;Builder Pattern(建造者模式)是将一个复杂对象的构建与它的表示分离，使得同样的构建过程可以创建不同的对象出来，用户只需要指定复杂对象的类型和内容就可以构建对象，而不需要知道内部的具体构建细节。&lt;/blockquote&gt; &lt;p&gt;建造者模式优点：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;将产品本身与产品的创建过程解耦，使得相同的创建过程可以创建不同的产品对象，而客户端不需要知道产品内部细节。&lt;/li&gt;  &lt;li&gt;每一个产品对应一个建造者，用户使用不同的建造者可以创建不同的产品，建造者本身可以轻松修改或者添加。&lt;/li&gt;  &lt;li&gt;可以更加精细地控制产品的创建过程。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;缺点：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;创建的产品需要有一定的相似性，如果差异过大，则不适合建造者模式。&lt;/li&gt;  &lt;li&gt;产品本身的复杂度会提高建造者的复杂度。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Spring Security 中对于建造者模式的使用也是非常多，例如典型的 AuthenticationManagerBuilder，它想要建造的对象是 AuthenticationManager，对应的建造方法则是 build。一般建造者模式中建造者类命名以 builder 结尾，而建造方法命名为 build()。&lt;/p&gt; &lt;p&gt;关于 AuthenticationManagerBuilder，参见：  &lt;a href="https://mp.weixin.qq.com/s/kB4m0YJas9LHuNT8JH5ZmQ" rel="nofollow noreferrer"&gt;深入理解 AuthenticationManagerBuilder 【源码篇】&lt;/a&gt; 一文。&lt;/p&gt; &lt;h2&gt;7.观察者模式&lt;/h2&gt; &lt;blockquote&gt;Observer(观察者模式)指多个对象间存在一对多的依赖关系，当一个对象的状态发生改变时，所有依赖于它的对象都得到通知并自动更新，观察者模式也称为发布-订阅模式、模型-视图模式，它是对象行为型模式。&lt;/blockquote&gt; &lt;p&gt;观察者模式优点：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;降低了目标与观察者之间的耦合关系，两者之间是抽象耦合关系。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;缺点：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;目标与观察者之间的依赖关系并没有完全解除，而且有可能出现循环引用。&lt;/li&gt;  &lt;li&gt;当观察者对象很多时，程序执行效率降低。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;在 Spring 框架中，观察者模式用于实现 ApplicationContext 的事件处理功能。Spring 为我们提供了 ApplicationEvent 类和 ApplicationListener 接口来启用事件处理。Spring 应用程序中的任何 Bean 实现 ApplicationListener 接口，都会接收到 ApplicationEvent 作为事件发布者推送的消息。在这里，事件发布者是主题(Subject) 和实现 ApplicationListener 的 Bean 的观察者(Observer)。&lt;/p&gt; &lt;p&gt;具体到 Spring Security 中，如登录成功事件发布，session 销毁事件等等，都算是观察者模式。&lt;/p&gt; &lt;p&gt;例如 AbstractAuthenticationProcessingFilter#successfulAuthentication 方法：&lt;/p&gt; &lt;pre&gt;  &lt;code&gt;protected void successfulAuthentication(HttpServletRequest request,
        HttpServletResponse response, FilterChain chain, Authentication authResult)
        throws IOException, ServletException {
    if (logger.isDebugEnabled()) {
        logger.debug(&amp;quot;Authentication success. Updating SecurityContextHolder to contain: &amp;quot;
                + authResult);
    }
    SecurityContextHolder.getContext().setAuthentication(authResult);
    rememberMeServices.loginSuccess(request, response, authResult);
    // Fire event
    if (this.eventPublisher != null) {
        eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(
                authResult, this.getClass()));
    }
    successHandler.onAuthenticationSuccess(request, response, authResult);
}&lt;/code&gt;&lt;/pre&gt; &lt;p&gt;类似还有很多，如 session 销毁事件等（参见  &lt;a href="https://mp.weixin.qq.com/s/9f2e4Ua2_fxEd-S9Y7DDtA" rel="nofollow noreferrer"&gt;Spring Security 自动踢掉前一个登录用户，一个配置搞定！&lt;/a&gt;），我这里就不一一列举了。&lt;/p&gt; &lt;h2&gt;8.装饰模式&lt;/h2&gt; &lt;blockquote&gt;Decorator(装饰模式)是指在不改变现有对象结构的情况下，动态地给该对象增加一些额外功能的模式。&lt;/blockquote&gt; &lt;p&gt;装饰模式的优点：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;可以灵活的扩展一个类的功能。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;缺点：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;增加了许多子类，使程序变得很复杂。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Spring Security 中对于装饰模式也有许多应用。最典型的就是一个请求在通过过滤器链的时候会不停的变，会不停的调整它的功能，通过装饰模式设计出了请求的许多类，例如：&lt;/p&gt; &lt;ul&gt;  &lt;li&gt;HeaderWriterRequest&lt;/li&gt;  &lt;li&gt;FirewalledRequest&lt;/li&gt;  &lt;li&gt;StrictHttpFirewall&lt;/li&gt;  &lt;li&gt;SaveToSessionRequestWrapper&lt;/li&gt;  &lt;li&gt;...&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;等等，类似的很多，我就不一一赘述了。&lt;/p&gt; &lt;h2&gt;小结&lt;/h2&gt; &lt;p&gt;松哥的 Spring Security 还在持续连载中，未来连载完了还会总结出更多的设计模式，这里先列出来八个和小伙伴们分享，如果小伙伴们有自己的见解，也欢迎留言补充。&lt;/p&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>java spring springsecurity</category>
      <guid isPermaLink="true">https://itindex.net/detail/60793-%E7%9B%98%E7%82%B9-spring-security</guid>
      <pubDate>Thu, 30 Jul 2020 09:33:50 CST</pubDate>
    </item>
    <item>
      <title>不衰的经典: ARIES事务恢复 [数据库学习的成人试炼] - 知乎</title>
      <link>https://itindex.net/detail/60655-%E7%BB%8F%E5%85%B8-aries-%E6%95%B0%E6%8D%AE%E5%BA%93</link>
      <description>&lt;div&gt;    &lt;p&gt;      &lt;strong&gt;一不小心文章又写长了。。。。&lt;/strong&gt;&lt;/p&gt;    &lt;h2&gt;前言&lt;/h2&gt;    &lt;p&gt;已经好几个月没写东西了, 比较忙, 开的技能树有点多, 主要在刷概率/统计/优化/NLP相关的东西, 分布式的东西看的比较少, 只是偶尔刷刷小红书的推荐论文还有看看datalake相关的东西; 不过ARIES这篇论文还是很值得在知乎记个笔记的.&lt;/p&gt;    &lt;p&gt;ARIES这篇是在刷      &lt;a href="https://link.zhihu.com/?target=http%3A//www.redbook.io/" rel="nofollow noreferrer" target="_blank"&gt;小红书&lt;/a&gt;的时候在第三章“Techniques Everyone Should Know”(很明显我还没入门啊, 这些paper几乎都没看过。。。。)一章里看到的, 全文69页，有点难读, 主要是因为作者在行文的时候穿插了大量的和SystemR和DB2等系统的算法各种对比, 使得不了解这两个系统的读者容易&amp;quot;走神&amp;quot;, 和理解混乱；&lt;/p&gt;    &lt;img src="data:image/svg+xml;utf8,&lt;svg xmlns='http://www.w3.org/2000/svg' width='1440' height='806'&gt;&lt;/svg&gt;" width="1440"&gt;&lt;/img&gt;    &lt;p&gt;92年的老论文了, 但是它提供了一个经典的“No Force, Steal” write-Ahead-Log的实现, 而“No Force, Steal”所带来的高性能，是(按小红书编者所言)“几乎是所有商用数据库都必定提供的”,&lt;/p&gt;    &lt;blockquote&gt;...these policies allow high performance are present in almost every commercial RDBMS offering but in turn add complexity to the database...&lt;/blockquote&gt;    &lt;p&gt;而这篇论文的重要性和难度, 对它的通读理解像是经历数据库学习的“成人试炼”&lt;/p&gt;    &lt;blockquote&gt;... it is perhaps the      &lt;strong&gt;        &lt;em&gt;most complicated paper&lt;/em&gt;&lt;/strong&gt;in this collection. In graduate database courses, this paper is a      &lt;strong&gt;        &lt;em&gt;rite of passage&lt;/em&gt;&lt;/strong&gt;. However, this material is fundamental, so it is important to understand...&lt;/blockquote&gt;    &lt;p&gt;(就笔者本人的读后感来讲, 这篇论文的复杂之处在于各个方面的环环相扣, 很难脱离开其他东西来单独理解其中的一面, 而需要整体有个印象之后，再精读一遍才能理解其中的奥妙配合;)&lt;/p&gt;    &lt;hr&gt;&lt;/hr&gt;    &lt;h2&gt;概念, 术语, 缩写, 和数据结构&lt;/h2&gt;    &lt;p&gt;      &lt;strong&gt;Tx:&lt;/strong&gt;指事务&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;硬盘页面&lt;/strong&gt;：硬盘文件的一页&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;内存页面&lt;/strong&gt;：硬盘页面被取出放进内存时的内存镜像, 被修改完后, 内存页面可以写回相应的硬盘页面;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;脏页&lt;/strong&gt;: 内存页面写了内容, 但是内容还没有同步回硬盘页面;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;Buffer Manager(BM)&lt;/strong&gt;: 当有事务需要写某页面时, 负责把硬盘页面放进Buffer里变成内存页面, 同时负责把内存页面写回硬盘, 由于内存有限, Buffer Manager需要小心调节什么时候把内存页面写回硬盘并释放内存空间&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;Log Record&lt;/strong&gt;: 数据库的页面操作和一些数据管理的操作都需要记录在一个log里; Log Record有3种, Redo/Undo/CLR(Compensation Log Record),&lt;/p&gt;    &lt;ol&gt;      &lt;li&gt;        &lt;strong&gt;Redo Log&lt;/strong&gt;记录了一个(Page-oriented级, 后边会解释)&amp;quot;写入/更改&amp;quot;数据库的操作所需要的的信息, 使得当脏页还没写回硬盘，系统就崩溃了的情况下, 可以通过Redo log来重复这个&amp;quot;写入/更改&amp;quot;操作, 恢复需要写的内容;        &lt;strong&gt;Redo Log对已经Commit的Tx非常重要&lt;/strong&gt;, 因为ARIES不要求tx commit时，tx所写的脏页都必须同步回硬盘；所以tx commit后，如果系统崩溃的话，我们就可以用Redo Log来replay对页面的更改来保证Committed Tx的写不丢失;（这就是Non-Force Policy）&lt;/li&gt;      &lt;li&gt;        &lt;strong&gt;Undo Log&lt;/strong&gt;记录了rollback一个(Logical级，后边会解释)&amp;quot;写入/更改&amp;quot;数据库的操作所需要的的信息。 Undo Log对保证能够rollback Tx非常重要, 因为ARIES允许把还没commit的Tx所修改的页面被BM同步回硬盘，腾出内存空间给别的Tx使用（这就是Steal），那么如果最终我们需要rollback这个Tx, 我们需要Undo Log来rollback这个tx之前的&amp;quot;写入/更改&amp;quot;&lt;/li&gt;      &lt;li&gt;        &lt;strong&gt;CLR(Compensation Log Record)&lt;/strong&gt;：CLR是ARIES的关键之一，当我们需要rollback，而使用Undo Log时，我们不仅需要按照Undo Log来更改(rollback)内存页面到之前的imge，(此后BM会决定什么时候把内存页同步回物理页面)，而且要记录具体如何修改这个页面的细节在log里作为一个CLR记录(由于Undo Log只是Logical Log，不具体指定需要修改哪个页面，比如Undo只是说要改哪个row，具体row在哪个页面不关心, CLR可以看作Undo Log的页面级执行细节log，或者伴随log), 这个CLR在Page-oriented级记录了如何更改一个页面来达到Undo的效果；由于CLR代表了页面级的修改, 所以CLR也看作是一种Redo Log(当Rollback需要redo时, 比如rollback更改了内存页面，但是内存页面还没有被同步回物理页面，此时系统崩溃重启，我们需要redo这个CLR)；&lt;/li&gt;&lt;/ol&gt;    &lt;p&gt;      &lt;strong&gt;        &lt;em&gt;重点: ARIES使用Page-oriented级的Redo/CLR, 而使用Logical级的Undo&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;Log Record上需要记录的信息:&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;strong&gt;TxID&lt;/strong&gt;: 哪个Tx写了这个Log Record&lt;/li&gt;      &lt;li&gt;        &lt;strong&gt;LSN(log sequence number):&lt;/strong&gt;只增logNumber, 每个Log Record一个, 按写入顺序增长, 连续的log未必属于同一个Tx&lt;/li&gt;      &lt;li&gt;        &lt;strong&gt;PrevLSN&lt;/strong&gt;: 本Log Record上记录        &lt;strong&gt;同一个Tx&lt;/strong&gt;的上一个写的Log Record的LSN&lt;/li&gt;      &lt;li&gt;        &lt;strong&gt;PageId&lt;/strong&gt;: 本Log Record要更改哪个数据页面&lt;/li&gt;      &lt;li&gt;        &lt;strong&gt;UndoPrevLSN&lt;/strong&gt;: 只存在于CLR这种Log Record上, 对应其所属的Undo Log Record的PrevLSN，或者说伴随的Undo Log处理完后，同一个Tx的上一个Log Record的LSN, (CLR是处理Undo Log时生成的), 它使得Tx的回溯Log Chain跳过了其相应的伴随Undo Log Record, 后边可以看到, 这是保证Undo Log不被多次处理的关键;&lt;/li&gt;&lt;/ul&gt;    &lt;img src="data:image/svg+xml;utf8,&lt;svg xmlns='http://www.w3.org/2000/svg' width='1084' height='632'&gt;&lt;/svg&gt;" width="1084"&gt;&lt;/img&gt;1, 2, 3可以看作合并的Redo/Undo log, 3‘ 和2’ 是3和2所的对应的CLR, 虚线代表它们的UndoPrevLSN“指针”    &lt;p&gt;      &lt;strong&gt;page_LSN&lt;/strong&gt;: 内存/物理页面上的一个field, 记录的最后一个对当前页面进行修改的Log Record的LSN；对一个页面来说，ARIES只需要维护一个LSN即可，&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;Force the log&lt;/strong&gt;: 强制把内存里的log按顺序写入硬盘, 直到某LSN, 系统可以运行后台进程来异步的force the log; （注意: 任何的log append都不需要立刻写入硬盘, 只需要存在于内存, BM会决定什么时候来把log写回硬盘;）&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;Physically undo/redo&lt;/strong&gt;: 比如把记录更改前的row(或者此row的fields)的image作为undo log, 把更改后的row(或者此row的fields)的image作为redo log;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;Operationally undo/redo&lt;/strong&gt;: 相对于Physical，比如记录“add 5”到row15的field3上, 而不是记录add 5之后这个row或者这个field的image;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;WAL(Write Ahead Log)协议：&lt;/strong&gt;在ARIES的设计里,BM有很大的自由来决定什么时候来把脏页写回物理页面(主要体现在Non-Force, Steal里); BM只需要遵守WAL协议即可:&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;strong&gt;内存页面同步回物理页面之前, 必须保证所有对这个页面更改的Undo Log都已经force to disk了&lt;/strong&gt;&lt;/li&gt;      &lt;li&gt;        &lt;strong&gt;在一个Tx Commit之前, 所有这个Tx的Redo Log都必须force to disk&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;      &lt;strong&gt;Steal policy&lt;/strong&gt;：如果对内存页面的更改可以随意同步回硬盘而不需要等待Tx commit, 那么我们称BM遵循了Steal policy；&lt;/p&gt;    &lt;p&gt;使用Steal Policy主要是为了避免以下问题，如果我们使用“必须等待所有更改过页面的Tx都commit了才同步这个内存页到物理页面”的Non-Steal Policy, 那么&lt;/p&gt;    &lt;ol&gt;      &lt;li&gt;﻿如果需要支持行锁, 那么一个页面可能有多个行被不同的Tx更改, 那么这个页面必须等待所有的Tx都Commit, 但是如果不断有新的Tx来更改这个页面呢？这个页面就迟迟无法同步回物理页面，如果有长(持续时间)事务，那么情况会更糟&lt;/li&gt;      &lt;li&gt;在这种情况下, 要么我们每隔一段时间来锁住页面, 保证没有新的Tx可以更改这个页面, 这样等所有当前更改这个页面的Tx都commit之后就可以写回物理页面了（但是这样严重影响吞吐）；或者另外一种策略，持续不同步其回物理页面, 那么当内存页面持续被更改, 这个页面的物理页面内容就会远远落后于正确的内存页面; 那么failure recovery的时候, 就必须要花费非常多的Redo cost;&lt;/li&gt;      &lt;li&gt;同时non-steal policy也比Steal policy复杂, 因为要记录哪些脏页有uncommitted更改; 而steal policy写回物理页面时完全不在乎Tx commit了没有, 所以不需要区分脏页到底有没有uncommitted更改&lt;/li&gt;&lt;/ol&gt;    &lt;p&gt;      &lt;strong&gt;﻿Force policy&lt;/strong&gt;: 之前也提到了, 如果我们要求Tx在commit前, 它所有的更改的页面必须写回到硬盘(同步回物理页面), 那我们说BM遵循force policy；相反, 如果我们没有这个要求, 那么BM遵循non-force policy&lt;/p&gt;    &lt;p&gt;      &lt;em&gt;        &lt;strong&gt;重点: ARIES的BM遵循 “Non-Force，Steal” Policy&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;    &lt;p&gt;除了Steal, 还有一个选择是完全不更改页面, 只等待commit时一起更改, 这叫做Deferred upating, 和ARIES的实现关系不大, 简单英文原文笔记下 （给未来的自己备注, 读者可以略过）&lt;/p&gt;    &lt;blockquote&gt;      &lt;strong&gt;﻿Deferred updating&lt;/strong&gt;is said to occur if, even in the virtual storage database buffers, the updates are not performed in-place when the transaction issues the corresponding database calls. The updates are kept in a pending list elsewhere and are performed in-place, using the pending list information, only after it is determined that the transaction is definitely committing. If the transaction needs to be rolled back, then the pending list is discarded or ignored. The deferred updating policy has implications on whether a transaction can “see” its own updates or not, and on whether partial rollbacks are possible or not.&lt;/blockquote&gt;    &lt;p&gt;      &lt;strong&gt;Page-oriented redo:&lt;/strong&gt;如果对页面的更改的伴随Redo log具体描述了一个页面是怎么更改的, 而不需要去查数据库的内部metadata, 且当failure recovery的时候, Redo发生在同一个页面; 那么我们说使用了Page-oriented redo; 注意: 这意味着页面的Redo是完全相互无关的, 可以independent的并行进行;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;Logical redo:&lt;/strong&gt;只在逻辑层面去记录修改, 比如我要把第n个row修改为xxx，但是具体第n个row是在哪个页面需要在redo的时候去检索, 由于磁盘管理或者index page leaf split的缘故, 一个逻辑row可能会从一个页面迁移到其他页面去, 那么一个对这个row的原始更改所发生的页面和failure recovery的时候需要redo的页面可能会不同;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;page-oriented undo/ logical undo：同理&lt;/strong&gt;&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;Logical undo可以获得更高的并行度: 这是因为Logica undo允许一个Tx_A的uncommitted更改, 被另外一个Tx_B 移动到其他页面去(当Tx_B发生在Tx_A之后, 且需要分index的leaf page时)，如果只支持page-oriented undo, 那么Undo就已经写死了undo哪个页面了, 所以Tx-B必须等待Tx-A commit之后(绝对不会发生Undo Tx-A的情况), 才能进行分index leaf page，移动Tx-A的数据的操作;&lt;/li&gt;      &lt;li&gt;支持logical undo, 那么即使逻辑row 被移动到了其他页面, 我们也可以在failure recovery的时候查询索引来找到row被移动到的页面来对其undo；&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;Tx Table&lt;/strong&gt;: 用来记录所有正在进行的Tx信息的table, 包含&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;        &lt;strong&gt;LastLSN:&lt;/strong&gt;Tx最新写的Log Record的LSN，注意，rollback时, 由于处理Undo log需要写CLR, 这些CLR会append在log queue里, 那么CLR也会被认为是&amp;quot;Tx最新写的Log Record&amp;quot; 而更新到Tx Table的LastLSN里；&lt;/li&gt;      &lt;li&gt;        &lt;strong&gt;UndoNxtLSN:&lt;/strong&gt;rollback时下一个需要处理的log record;  如果最新的log是CLR, 那么这个值就是CLR的UndoNxtLSN值, 而如果最新的log不是CLR, 那么这个值和LastLSN一致；&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;      &lt;strong&gt;Dirty_Page Table和RecLSN&lt;/strong&gt;: 用来记录脏页的Redo Log的“可能的”开始位置，由BM维护，每当BM把一个物理页面取出到内存之后，都会在Dirty_Page Table里注册一条关于这个页面的信息，并把当前Log队列的下一个要分配的LSN记录在Dirty_Page Table里的对应这个页面的RecLSN属性里, 这样无论之后这个脏页被更改多少次,  我们都可以知道，物理页面和内存页面的差异是从这个记录的RecLSN开始的, RecLSN之前的Log和这个脏页无关, 同时如果从RecLSN开始replay的话，可以保证找到所有这个页面从硬盘取出后的所有更改; 而当BM把内存页面同步回物理页面之后，则可以删除Dirty_Page table里对应的条目；&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;hr&gt;&lt;/hr&gt;    &lt;h2&gt;数据库的正常写操作和Rollback操作&lt;/h2&gt;    &lt;p&gt;相对Failure Recovery时如何利用log来恢复数据库, 我们先来看没有failure时, 数据库如何记录log和更改页面, 如何rollback更改;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;首先所有的更改都必须完成(1)如果页面没有在buffer里, 申请BM把物理页面取出(如果是insert,有时需要创建新页面)；(2)对页面加短latch, 保证此期间没有其他进程可以修改页面, (3)对内存页面进行更改, 记录Undo和Redo log，更改Tx Table来update UndoPrevLSN和LastLSN (4)解latch  (latch只是用来保证同一时间只有一个进程修改页面, 和数据库维护Tx Isolation的锁不是一个概念, 和Tx的commit/abort无关)&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;Commit流程&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;由于WAL协议的要求, 这个Tx所写的所有Redo Log都必须force到硬盘, 然后在log里记录一个End Record。&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;Rollback流程&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;当application需要Tx rollback, 或者deadlock需要杀掉某Tx时, 都需要在非系统崩溃的情况下rollback Tx; 当收到rollback请求后, 我们从此Tx的Tx table的UndoPrevLSN开始处理Log Record;&lt;/p&gt;    &lt;ol&gt;      &lt;li&gt;当处理的log是Redo Log, 不做处理，继续通过PrevLSN往前找其他属于本Tx的log&lt;/li&gt;      &lt;li&gt;当处理的log是Undo Log, 查找应该更改哪个页面(因为Undo Log是Logical的), 然后对相应页面加latch, rollback页面并记录伴随的CLR并append到log里，更改Tx Table, 解Latch&lt;/li&gt;      &lt;li&gt;如此处理直到所有的属于这个Tx的Log都被处理完毕, 在log里记录一个End Record;&lt;/li&gt;&lt;/ol&gt;    &lt;img src="data:image/svg+xml;utf8,&lt;svg xmlns='http://www.w3.org/2000/svg' width='720' height='420'&gt;&lt;/svg&gt;" width="720"&gt;&lt;/img&gt;假设我们在log写到LSN3的位置时, 决定Rollback, 那么依次处理3，2，1的同时会往log队列里写CLR3‘ CLR2’， CLR1‘    &lt;p&gt;可以看到当我们rollback一个Tx时, 我们会从Tx的当前UndoPrevLSN往回根据Log Record的PrevLSN(在failure Recovery的情况下有可能会遇到CLR，则需要用CLR的UndoPrevLSN来回溯，此乃后话)找Undo Log, 而对于每一个Undo Log, 都往当前的log队列里新append一个CLR;&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;UNDO/REDO Log的append顺序&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;如果一个逻辑修改操作的伴随Redo/Undo log比较小, 那么它们的信息可以记录在一个Record Log里, 否则我们需要分开记录Redo/Undo log, 此时, (1)      &lt;strong&gt;Undo Log一定要先于Redo Log记录&lt;/strong&gt;, 且(2)      &lt;strong&gt;内存页面的page_LSN要记录Redo log的LSN而不是Undo log的LSN&lt;/strong&gt;； 条件(1)防止了刚记录完Redo, 系统就崩溃造成只有Redolog而没有undo log; 这会和之后的Failure Recovery 算法冲突, 由于Failure Recovery 算法需要先replay所有的Redo来“恢复历史”, 如果一个修改只有Redo, 那么redo完的页面无法undo; 而相反的, 如果只有Undo而没有Redo, 那么。。。=&amp;gt; 论文没写 -_-  （大家可以自行思考下如何处理）条件(2)保证这个页面不会被Redo多次，这和之后的Failure Recovery相关，Redo pass的时候要根据页面上的page_LSN来决定当前的Redo内容是否已经apply到了此页面上&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;BM异步同步内存页面到物理页面&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;BM只需要遵守WAL协议，在这个唯一限制下，BM可以充分利用Batching来加速把内存页写回物理页面的吞吐; 对于经常被修改的Hot Page, BM可以选择对这个hot page制作一个in memory copy然后把这个copy同步回物理页面，这样可以防止同步时所加的latch影响对这个hot page的更改操作性能；&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;hr&gt;&lt;/hr&gt;    &lt;h2&gt;异步Checkpointing&lt;/h2&gt;    &lt;p&gt;ARIES的checkpointing是指把dirty_page table和Tx table（还有其他数据库的metadata比如tablespace, indexspace和主题相关性较小）备份起来, 这个过程可以是异步进行的, 而不需要锁住这两个表来保证checkpoint的时候没有别的进程更改它们，这就保证了系统在checkpointing的时候也可以正常进行所有其他操作；而在checkpointing的过程中Tx Table和dirty_page table有变化也不影响Failure Recovery的正确性(因为可以分析log来恢复准确的信息，后边会讲)&lt;/p&gt;    &lt;p&gt;当Checkpointing开始时, 需要先写一个begin-chkpt Record到Log里，然后开始记录当前的Tx table和dirty_page table到硬盘, dirty_page table甚至可以100行100行的记录而不需要一口气全部记录写到硬盘去（这样可以加比较短时间和scope比较小的Latch, 而不必Latch住整个dirty_table）；&lt;/p&gt;    &lt;p&gt;当所有需要记录的东西都记录好了，在log里记录一个end-chkpt record, 并在一个预定义好高可用性储存记录下master record，记录begin-chkpt的LSN；只有begin-chkpt而没有end-chkpt的checkpointing作废不用；&lt;/p&gt;    &lt;p&gt;注意: ARIES不要求所有的脏页都同步回物理页面之后才开始checkpoint, 所以会有很多物理页很老的脏页的Redo log的LSN比begin-chkpt Record的LSN要小;&lt;/p&gt;    &lt;hr&gt;&lt;/hr&gt;    &lt;h2&gt;Failure Recovery&lt;/h2&gt;    &lt;p&gt;当数据库突然崩溃， 需要重新启动恢复状态时，所有还在进行的Tx都需要rollback; 且所有已经commit了的Tx都需要保证它们的更改可以恢复; 由于ARIES的&amp;quot;Non Force, Steal&amp;quot;策略，可以遇到以下情况:&lt;/p&gt;    &lt;ol&gt;      &lt;li&gt;已经commit的tx的更改没有写回硬盘, 物理页面是老的落后于commit所需要的状态, 需要redo恢复commit后的的物理页面&lt;/li&gt;      &lt;li&gt;没有commit的page已经写回disk, 需要把这些更改从物理页面里Undo回去&lt;/li&gt;      &lt;li&gt;已经commit的tx的更改已经写回物理页面, 那么对这些Tx和页面不需要任何进一步操作&lt;/li&gt;&lt;/ol&gt;    &lt;p&gt;那么如何知道页面和Tx应该属于上边哪一种情况呢？ARIES首先使用一个Analysis Pass来分析log&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;Analysis Pass&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;Analysis Pass从checkpoint完成时记录在master record的begin-chkpt Record开始扫描log, 直到log末尾; 在这个过程中      &lt;strong&gt;只读log的内容而不会查看任何页面的内容&lt;/strong&gt;;&lt;/p&gt;    &lt;p&gt;首先, 从checkpoint里恢复Tx Table和Dirty_page table，&lt;/p&gt;    &lt;p&gt;对于每个遇到的Redo Record(CLR也算Redo Log), 如果它所属的Tx不在Tx Table里则加入, 遇到Tx的End Record则从Tx Table里移除此Tx; 这样保证分析完log后, 所有系统崩溃时正在进行的Tx(还没commit或者还没rollback完毕的Tx)都在Tx Table里(也包括正在rollback但是还没完成的Tx)，同时Tx Table的每个Tx的UndoNxtLSN也会被更新到正确的位置(Tx写的最后一个Redo Log的LSN，而如果当系统崩溃时Tx正在进行Rollback, 那么Tx写的最后一个CLR的LSN会记录在Tx Table的这个Tx的UndoNxtLSN里)；&lt;/p&gt;    &lt;p&gt;对于遇到的每个Redo Log Record(CLR也算Redo Log)的所对应的page, 如果它没有在Dirty_page table里，则把此页面加入并把当前Redo Log的LSN记录为其ResLSN；这样当log分析完毕后，Dirty_page table里有系统崩溃时所有“可能的脏页“记录（由于BM不在Log里记录它什么时候把脏页同步回物理页面, 所以我们不查看物理页面内容，是无法得知BM有没有把脏页写回的，而只能通过checkpoint的dirty_page table的snapshot来得知checkpoint时哪些是脏页，和通过Redo Log来判断哪些页面在checkpoint之后曾经被更改过, 从而最大程度恢复这个“可能的”Dirty_page table，如果想要精准的得知一个页面是否在系统崩溃时有未同步到硬盘的内容，我们需要把物理页面读出来检查其Page_LSN, 这会在Redo pass里提到)&lt;/p&gt;    &lt;p&gt;根据恢复的“可能的”Dirty_page table，我们计算所有的“可能的”脏页的ResLSN, 那么最小的ResLSN就是我们RedoLSN, 即Redo开始扫描log的位置; 因为我们知道RedoLSN之前所有的Redo Log所伴随的更改，都已经被同步回硬盘页面了；&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;REDO Pass&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;从﻿RedoLSN开始扫描log, 如果log是redo/CLR，且它们对应的页面在“可能的”Dirty_page table里，那么需要通知BM把页面从硬盘取出，如果此页面的page_LSN比当前的redo/CLR的LSN大，那么说明这个页面已经进行过这个更改了，跳过此Log Record, 否则按照Redo/CLR的log内容对页面进行更改；&lt;/p&gt;    &lt;p&gt;在Redo Pass里，我们会恢复数据库的“历史状态”到Failure产生时的状态&lt;/p&gt;    &lt;ul&gt;      &lt;li&gt;如果系统崩溃时，Tx在正常进行数据修改，还没有commit, 且它的某个页面修改没有被BM同步到硬盘, 在系统崩溃时这些修改丢失，那么Redo pass可以正确的把这些页面取出到内存并进行修改, 这些修改会在之后的undo pass被rollback&lt;/li&gt;      &lt;li&gt;如果系统崩溃时，Tx已经commit，但是由于NonForce Policy, 有些修改还没有被BM同步到硬盘，那么Redo pass也可以正确的把这些页面取出到内存并进行修改，由于这些Tx已经commit掉了，没有记录在Analysis pass结束时的Tx Table里，所以接下来的undo pass不会处理这些Tx的undo log，所以它们的更改不会被Undo；&lt;/li&gt;      &lt;li&gt;如果系统崩溃时，Tx在进行Rollback, 那么这个Tx的Redo Log集合包括所有的正常写数据库时生成的Redo Log, 和之后rollback时产生的CLR, 这些Redo Log和CLR所更改的页面都有可能还没被同步回物理页面, 那么Redo pass会保证这些Redo/CLR对应的更改apply到相应的页面去, 那么就可以把rollback的进度恢复到数据库崩溃时的状态，由于Tx Table里记录了最新的CLR作为这个Tx的UndoNxtLSN，那么之后的Undo Pass会接着之前的Rollback进度继续进行Rollback操作（具体看Undo Pass）；&lt;/li&gt;&lt;/ul&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;Redo pass时的BM算法更改&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;Redo pass开始后，BM就可以开始把脏页同步回物理页面了，但此时BM不能把任何页面从dirty_page table中删去, 这是因为目前的dirty_page table是提供了&amp;quot;可能的&amp;quot;脏页列表，Redo pass需要这个列表来判断需不需要把其中的页面拿出来，并对比它的page_LSN和其对应的所有Redo Log来判断是否需要修改页面， 比如一个页面的page_LSN是10，它被LSN11, LSN12, LSN20, LSN100的Redo Log记录的“更新”修改过，那么analysis pass会把这个页面记录在dirty_page table里, 假设Redo Pass刚处理到LSN50时, BM决定同步这个页面到物理页面去, 此时如果BM把这个页面从dirty_page table中删去, 那么LSN100的更改就丢失了;&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;UNDO Pass&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;Redo pass结束后, 系统就恢复正常了, 只是所有还在进行的Tx（此时还记录在Tx Table中的Tx）都必须被Rollback, rollback算法和正常情况一致，但是多了CLR的处理情况（重新贴一遍省去往回翻页）；&lt;/p&gt;    &lt;ol&gt;      &lt;li&gt;当处理的log是Redo Log, 不用处理，通过PrevLSN继续往前找&lt;/li&gt;      &lt;li&gt;当处理的log是Undo Log, 查找应该更改哪个页面(因为Undo Log是Logical的), 然后对相应页面加latch, rollback页面并记录伴随的CLR并append到log里，更改Tx Table, 解Latch&lt;/li&gt;      &lt;li&gt;当处理的log是CLR, 那么通过UndoNxtLSN继续往前查找&lt;/li&gt;      &lt;li&gt;如此处理直到所有的属于这个Tx的Log都被处理完毕, 在log里记录一个End Record; 此Tx的Failure Recovery的Rollback结束&lt;/li&gt;&lt;/ol&gt;    &lt;img src="data:image/svg+xml;utf8,&lt;svg xmlns='http://www.w3.org/2000/svg' width='720' height='420'&gt;&lt;/svg&gt;" width="720"&gt;&lt;/img&gt;    &lt;p&gt;再次回到这个图，可以看到，如果Redo pass处理了CLR 2‘, 那么Undo Pass时，CLR2‘会直接跳到Log1，这样只有Log1的Undo被处理，生成新的CLR1‘；由于CLR3’和CLR2‘在redo pass时已经Replay过了，那么2和3的Undo都必定已经完成；&lt;/p&gt;    &lt;p&gt;在Undo Pass开始时，BM算法恢复正常，可以随意把脏页写回物理页面后从dirty_page table中删去脏页(并不影响Undo pass的工作)&lt;/p&gt;    &lt;p&gt;Undo pass结束后，整个数据库就恢复到了一个没有任何Tx的consistent状态了，就好像没有任何failure发生一样，只是所有的还在进行的Tx都被rollback了；&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;注意&lt;/strong&gt;：在页面层，由于CLR是在Redo pass里处理的，所以如果Tx在Rollingback的时候出现failure，或者正在做Failure Recovery时再次出现failure, 那么CLR可能已经生成但是其伴随的对页面的具体undo更改只发生在内存页面而还没有被同步回物理页面；那么其实CLR是在Redo pass而不是Undo pass里被“重新replay的”; CLR是一种Redo, 这是理解ARIES的重点之一&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;无锁的ARIES&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;整个Failure Recovery的过程中，都不需要事务级的锁, 这是由于所有的更改在语意级都是绝对互斥的，一个还没commit的Tx如果可以进行某种“更改”并生成其伴随的Undo/Redo log，那么绝对不会有其他Tx可以更改同一个Object，从而生成冲突的Undo/Redo log, 换句话说，所有的Redo/Undo/CLR都在高层语意上是无冲突的，不同的Tx也许回改同一个页面，但是它们绝对不会更改同一个Row(如果数据库支持行锁)或者可以更改同一个Row，但是绝不会更改同一个Field(如果数据库支持field级锁)；无锁的Rollback是避免死锁的关键, 这样就不会发生Rollback和另外一个Rollback相互死锁的尴尬，此时需要Rollback一个Rollback, 这也是很多数据库设计力图避免的问题；&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;Failure Recovery的 并行化考虑&lt;/strong&gt;&lt;/p&gt;    &lt;ol&gt;      &lt;li&gt;由于Redo的时候需要把“可能的”脏页取出到内存，那么Analysis pass可以直接开始取这些页面而不必等待Redo pass开始&lt;/li&gt;      &lt;li&gt;Redo是页面级的，那么不同页面的Redo可以并行恢复&lt;/li&gt;      &lt;li&gt;Undo是Tx级的，不同的Tx可以并行进行Undo pass&lt;/li&gt;&lt;/ol&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;Undo pass开始时就允许数据库接受新Tx&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;如果需要尽快恢复数据库使其可以接受新Tx，则需要在Redo时把需要加的事务锁都加好, 这样接受新的Tx也不会发生问题(比如阻止新Tx读到还在Rollback的Tx的更改数据); 一种方式是在checkpoint的时候把锁表也记录下来, 并在进行Redo时根据需要加事务锁，在Undo pass时，只要注意Undo/CLR的情况，如果一个obj的所有更改都已经被Rollback了, 那么这个obj的锁可以立刻去除，而不必等待这个Tx Rollback结束；      &lt;br /&gt;&lt;/p&gt;    &lt;hr&gt;&lt;/hr&gt;    &lt;h2&gt;Nested Top Action&lt;/h2&gt;    &lt;p&gt;ARIES的设计使得它很容易实现“需要Rollback又不需要Rollback的inner Tx”，比如当一个Tx-A需要插入很多新数据，所以处理进程在这个Tx-A的context下拓展了一个文件空间用来insert，而数据库可以允许另外一个Tx-B在Tx-A commit之前来使用这块新区域；此时：&lt;/p&gt;    &lt;ol&gt;      &lt;li&gt;如果拓展文件空间的操作还没完成系统就崩溃了，那么这个进行了一半的“拓展文件空间”的操作需要和Tx-A一起rollback&lt;/li&gt;      &lt;li&gt;如果拓展文件空间的操作完成了，那么这个操作则不需要和Tx-A一起rollback；这是因为 可能某Tx-B也把自己的内容写入到这个新区域了，此时Tx-A rollback连带rollback这个“拓展文件空间”操作的话，Tx-B的内容就被错误删除了；&lt;/li&gt;&lt;/ol&gt;    &lt;p&gt;ARIES的结构解决这个问题非常简单，在inner Tx完成前，把正常的Redo/Undo log写好，Undo里写正常的Rollback的逻辑，这样在完成前所有情况和一般情况一致，系统崩溃inner Tx会enclosing Tx一起rollback；而当inner Tx完成后，对已经写好的Undo立刻写一个伴随的dummy CLR来跳过这些Undo就好了，这样在Redo Pass的时候，这些Dummy CLR不会有任何作用，而在Undo pass的时候这些CLR的UndoNxtLSN可以跳过它们的伴随Undo Log；这样就保证enclosing Tx在Undo的时候自动跳过Undo这个完成的inner Tx.&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;h2&gt;      &lt;strong&gt;﻿Space Management&lt;/strong&gt;&lt;/h2&gt;    &lt;p&gt;还有一个很好的例子来体现Logical Undo的好处，就是数据库的Space Management，一般数据库要维护一个free space inventory pages(FSIP)来记录每个页面还有多少空间；为了性能，只维护近似值，比如只有当阀值超过25%,50%,75%...才更新这个信息，这样就使得不必每个操作都update这个信息(比如很多时候free space的变化只有0.x%)；通过Logic Undo，Undo就和Redo解耦合了，比如Tx-A的更改正好使得页面从23%变成了%27，超过25%的阀值，所以Tx-A更新FSIP，但是后来Tx-B也更新这个页面使得页面使用率变成了44%，此时如果Rollback Tx-A，我们并不需要Undo我们对FSIP的更改；(实现Redo/Undo的非对称性)&lt;/p&gt;    &lt;hr&gt;&lt;/hr&gt;    &lt;h2&gt;一些总结思考&lt;/h2&gt;    &lt;p&gt;ARIES的&amp;quot;Non-Force，Steal&amp;quot;policy给了BM最大的灵活度，和对commit process的最小的限制；BM只需要保证WAL协议即可，除此之外ARIES的正确性完全不受BM自己的优化同步算法影响；&lt;/p&gt;    &lt;p&gt;ARIES使用page-oriented Redo log和Logical Undo Log，这使得系统的其他部分实现非常灵活，如果暂时不考虑undo log的部分，只考虑Redo，那么其实Redo就是为了防止page在内存中更改的易失，而当page同步回硬盘后，则不需要redo log来重写了，所以page上要记录LSN作为进度来保证不会duplicate redo，而page的LSN是只前进的，其实就好像是对“前进”的操作的“确定性”记录，对于page来说，它只知道有人需要对它进行写，而不需要知道到底这个写是为了Redo还是为了Undo；&lt;/p&gt;    &lt;p&gt;Redo log是为了“记住已经在page上进行过了的操作”，这些操作是已经发生了的(只是还没写回硬盘), 它们之所以可以进行，是因为很多check已经做完了，这是为什么Redo log设计为page-oriented的关键；&lt;/p&gt;    &lt;p&gt;相比之下，Undo Log是为了“记住未来如果要rollback我们应该做什么”，如果把Undo设计为底层页面级应该做什么操作，我们就把现在的环境和未来“绑死”了，而未来是充满非确定性的(比如index分页), 而如果高层的Logical Undo没有写死我们应该对页面做什么，应该对哪个页面做什么， 而只是把语意层面必须要做的Undo信息留下了，这样，我们就允许了底层的各种细节可以发生变化，只要语意层面在未来把“更改”rollback即可，从而使得系统的其他逻辑可以对这些细节进行更改(比如移动未committed的数据到其他页面)而不必被Failure Recovery的逻辑所束缚；&lt;/p&gt;    &lt;p&gt;Logical的Undo Log终归要被翻译成为对具体页面的更改，而CLR作为Undo Log的底层页面级伴随Log，为ARIES扣上了关键的一环，因为只有当Rollback成为事实, 才需要“现在立刻对页面进行Undo”时(而不是对“未来进行筹划&amp;quot;)，那么CLR是page-oriented 的设计就非常自然了；CLR可以看作Undo的具像化，一个page的历史是由完成的Redo chain和CLR组成的，Undo只是为了在“更合适”的时间转化为CLR而已；&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;ARIES这篇论文讲了非常多的东西，这里只选笔者觉得比较有用有意思的节选出来用自己的理解；强烈推荐对数据库有兴趣的同学去读原文，经历完这个      &lt;em&gt;rite of passage，可以&lt;/em&gt;承受ARIES的难度      &lt;em&gt;，&lt;/em&gt;你不会再害怕任何复杂的数据库论文（大概。。。）；&lt;/p&gt;    &lt;p&gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;（完）&lt;/p&gt;&lt;/div&gt;
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/60655-%E7%BB%8F%E5%85%B8-aries-%E6%95%B0%E6%8D%AE%E5%BA%93</guid>
      <pubDate>Mon, 08 Jun 2020 22:44:47 CST</pubDate>
    </item>
    <item>
      <title>经典机器学习 | 如何做到预流失与流失挽回？</title>
      <link>https://itindex.net/detail/59922-%E7%BB%8F%E5%85%B8-%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0-%E9%A2%84%E6%B5%81</link>
      <description>&lt;blockquote data-author-name="" data-content-utf8-length="256" data-source-title="" data-type="2" data-url=""&gt;&lt;section&gt;&lt;section&gt;导语：预流失用户，即有流失倾向，但还没有开始真正流失的用户。相较于流失用户而言，预流失用户处于观望阶段，或许对现有产品有所顾虑，或许对于潜在的流向（竞品）有所顾虑，或许是在等待些什么；流失用户，即已经流失了的用户，或许是因为游戏弃坑，或许选择了其他产品，用户肯定还在玩些什么，只是不再来你这儿了。文章介绍了如何通过经典的&lt;mark data-type=techmethods data-id=1a0e9c5e-6502-4cd7-8683-6b5ca6c48be2&gt;机器学习&lt;/mark&gt;(Machine Learning, ML)方法来寻找那些流失可能性比较高的用户、寻找那些回流意愿比较大的用户。运营同学针对这些用户就可以重点干预，降低预流失用户比例，拉高用户的回流比例。&lt;/section&gt;&lt;/section&gt;&lt;/blockquote&gt;&lt;section&gt;&lt;section data-mpa-template="t"&gt;&lt;blockquote&gt;&lt;strong&gt;背景&lt;/strong&gt;&lt;/blockquote&gt;&lt;/section&gt;&lt;/section&gt;&lt;p&gt;在日常游戏运营中，我们常常需要提高目标用户的留存率、提高流失用户的回流率、精准运营、节约运营资源。基于以上的述求，我们将经典&lt;mark data-type=techmethods data-id=1a0e9c5e-6502-4cd7-8683-6b5ca6c48be2&gt;机器学习&lt;/mark&gt;实践于预流失和流失挽回两个场景。 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/p&gt;&lt;p&gt;模型整体设计流程图如下：&lt;/p&gt;&lt;p&gt;&lt;img data-ratio="1.33843537414966" data-src="https://mmbiz.qpic.cn/mmbiz_png/b96CibCt70iaYNp9ibbYt5S7B7R3JYPypRb8W1URWNLt0TI0oWxQW0Dk30AMgbwwQRXqrqjKFeMULJsvMI73QnPGQ/640" data-w="588" src="https://image.jiqizhixin.com/uploads/editor/dc218f7d-1646-4b9b-8b4e-7cf4c9a9ad9c/640.png" data-fail="0" class="fr-fic fr-dib" style="width: 700%;"&gt;&lt;/p&gt;&lt;section&gt;&lt;section data-mpa-template="t"&gt;&lt;blockquote&gt;&lt;strong&gt;预流失与流失挽回概述&lt;/strong&gt;&lt;/blockquote&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;section data-mpa-template="t"&gt;&lt;h3&gt;&lt;strong&gt;1. 预流失&lt;/strong&gt;&lt;/h3&gt;&lt;/section&gt;&lt;/section&gt;&lt;p&gt;预流失用户，即有流失倾向，但还没有开始真正流失的用户。相较于流失用户而言，预流失用户处于观望阶段，或许对现有产品有所顾虑，或许对于潜在的流向（竞品）有所顾虑，或许是在等待些什么。&lt;/p&gt;&lt;section&gt;&lt;section data-mpa-template="t"&gt;&lt;h3&gt;&lt;strong&gt;2. 流失挽回&lt;/strong&gt;&lt;/h3&gt;&lt;/section&gt;&lt;/section&gt;&lt;p&gt;流失用户，即已经流失了的用户，或许是因为游戏弃坑，或许选择了其他产品，用户肯定还在玩些什么，只是不再来你这儿了。&lt;/p&gt;&lt;section&gt;&lt;section data-mpa-template="t"&gt;&lt;blockquote&gt;&lt;strong&gt;获得训练数据&lt;/strong&gt;&lt;/blockquote&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;section data-mpa-template="t"&gt;&lt;h3&gt;&lt;strong&gt;1. 基础数据&lt;/strong&gt;&lt;/h3&gt;&lt;/section&gt;&lt;/section&gt;&lt;p&gt;&lt;img data-ratio="0.5689655172413793" data-src="https://mmbiz.qpic.cn/mmbiz_png/b96CibCt70iaYNp9ibbYt5S7B7R3JYPypRbDbjLoBZChLkaozFQLNuQZ5ibBxVkePN5qU9z6RZXhIrhaSX2ArSMhhQ/640" data-w="580" src="https://image.jiqizhixin.com/uploads/editor/1fa8201c-6672-4e3e-8fa4-a8972027cc2a/640.png" data-fail="0" class="fr-fic fr-dib" style="width: 700%;"&gt;&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;基础数据是最基础也是最重要的第一步，需要我们去寻找、清洗各种原始数据，原始数据包括用户的登录数据、充值数据和用户数据几个模块。&lt;/p&gt;&lt;p&gt;模型训练自然是数据越多越好的。&lt;/p&gt;&lt;section&gt;&lt;section data-mpa-template="t"&gt;&lt;h3&gt;&lt;strong&gt;2. 给用户打标签&lt;/strong&gt;&lt;/h3&gt;&lt;/section&gt;&lt;/section&gt;&lt;p&gt;&lt;img data-ratio="0.11868686868686869" data-src="https://mmbiz.qpic.cn/mmbiz_png/b96CibCt70iaYNp9ibbYt5S7B7R3JYPypRbmSwy3cLff7ECv7yA5U97ibZ0Q5vaY8a327Y9cmwY0GUZY6qkQsj1MYQ/640" data-w="792" src="https://image.jiqizhixin.com/uploads/editor/cef9b7a8-4af0-4c3c-ba0c-3bfaf725be37/640.png" data-fail="0" class="fr-fic fr-dib" style="width: 700%;"&gt;&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;预流失，判断用户是否会流失，如果上上周活跃，上周不活跃则是流失用户，label=1；反之上周活跃，则label=0。我们可以以周为单位，读取过去四周、八周或者更多的原始数据。&lt;/p&gt;&lt;p&gt;在流失挽回场景，label的判断&lt;mark data-type=concepts data-id=95a97f4b-79d2-4bbc-91ae-300f074dff9f&gt;逻辑&lt;/mark&gt;正好相反，如下图所示&lt;/p&gt;&lt;p&gt;&lt;img data-ratio="0.09192825112107623" data-src="https://mmbiz.qpic.cn/mmbiz_png/b96CibCt70iaYNp9ibbYt5S7B7R3JYPypRbyOMGX0YmkRpGSNtdOaicJ8QC5jO0IH1VCXVc9Np6qPeYFU9lJGcfajA/640" data-w="892" src="https://image.jiqizhixin.com/uploads/editor/d41b4933-03be-4881-bbc4-5886242b3214/640.png" data-fail="0" class="fr-fic fr-dib" style="width: 700%;"&gt;&lt;/p&gt;&lt;section&gt;&lt;section data-mpa-template="t"&gt;&lt;blockquote&gt;&lt;strong&gt;准备训练测试数据&lt;/strong&gt;&lt;/blockquote&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;section data-mpa-template="t"&gt;&lt;h3&gt;&lt;strong&gt;1. 训练测试数据划分&lt;/strong&gt;&lt;/h3&gt;&lt;/section&gt;&lt;/section&gt;&lt;p&gt;&lt;img data-ratio="0.27835051546391754" data-src="https://mmbiz.qpic.cn/mmbiz_png/b96CibCt70iaYNp9ibbYt5S7B7R3JYPypRbz8Kk9iaqczNJSibEThiaO4aKxta7cjcmolLyVgF6hUUCWRx3Zkj5BzTDA/640" data-w="776" src="https://image.jiqizhixin.com/uploads/editor/500fb58d-5402-4a50-be5f-7d9afd85f15f/640.png" data-fail="0" class="fr-fic fr-dib" style="width: 700%;"&gt;&lt;/p&gt;&lt;p&gt;根据自己的数据集大小合理的划分出三种数据，&lt;mark data-type=concepts data-id=698eae06-517e-4332-ba61-2de17c83ffb6&gt;验证集&lt;/mark&gt;在训练的时候用于模型调参，测试集在最后的最后模型所有&lt;mark data-type=concepts data-id=2e982b73-88e2-41e8-a430-f7ae5a9af4bf&gt;参数&lt;/mark&gt;设定后用于验证模型效果。&lt;/p&gt;&lt;section&gt;&lt;section data-mpa-template="t"&gt;&lt;h3&gt;&lt;strong&gt;2. 正负样本均衡&lt;/strong&gt;&lt;/h3&gt;&lt;/section&gt;&lt;/section&gt;&lt;p&gt;如果实际数据中正负样本的比例严重不均衡，则有必要处理一下。处理办法是有放回的随机采样，code 示例如下：&lt;/p&gt;&lt;section&gt;&lt;pre data-lang="python"&gt;&lt;code&gt;# 正负样本均衡&lt;/code&gt;&lt;code&gt;import random&lt;/code&gt;&lt;code&gt;pos_vs_neg = 1.0&lt;/code&gt;&lt;code&gt;pos_data_count = train_df.filter(train_df[&amp;#39;ilabel&amp;#39;] == 1).count()&lt;/code&gt;&lt;code&gt;neg_data_count = train_df.filter(train_df[&amp;#39;ilabel&amp;#39;] == 0).count()&lt;/code&gt;&lt;code&gt;gap = pos_data_count-neg_data_count*pos_vs_neg&lt;/code&gt;&lt;code&gt;print(&amp;#39;from &amp;#39;, pos_data_count, neg_data_count, &amp;#39;to&amp;#39;, pos_data_count, neg_data_count*pos_vs_neg, &amp;#39;gap&amp;#39;, gap)&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;if gap&amp;gt;0: # 正样本多，取样负样本&lt;/code&gt;&lt;code&gt;   data_add = train_df.filter(train_df[&amp;#39;ilabel&amp;#39;] == 0).sample(True, gap/neg_data_count, random.randint(1, 1000))&lt;/code&gt;&lt;code&gt;   train_df = train_df.union(data_add)&lt;/code&gt;&lt;code&gt;elif gap&amp;lt;0: # 负样本多，取样正样本&lt;/code&gt;&lt;code&gt;   data_add = train_df.filter(train_df[&amp;#39;ilabel&amp;#39;] == 1).sample(True, -gap/pos_data_count, random.randint(1, 1000))&lt;/code&gt;&lt;code&gt;   train_df = train_df.union(data_add)    &lt;/code&gt;&lt;code&gt;print(train_df.filter(train_df[&amp;#39;ilabel&amp;#39;] == 1).count(), train_df.filter(train_df[&amp;#39;ilabel&amp;#39;] == 0).count())&lt;/code&gt;&lt;code&gt;print(&amp;#39;balancing data finish&amp;#39;)&lt;/code&gt;&lt;/pre&gt;&lt;/section&gt;&lt;p&gt;（左滑可查看完整代码，下同）&lt;/p&gt;&lt;section&gt;&lt;section data-mpa-template="t"&gt;&lt;blockquote&gt;&lt;strong&gt;&lt;mark data-type=concepts data-id=898dc2c6-690b-4c29-82b6-f79e7b71d329&gt;特征工程&lt;/mark&gt;&lt;/strong&gt;&lt;/blockquote&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;section data-mpa-template="t"&gt;&lt;h3&gt;&lt;strong&gt;1. 特征选取&lt;/strong&gt;&lt;/h3&gt;&lt;/section&gt;&lt;/section&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;&lt;img data-ratio="1.660847880299252" data-src="https://mmbiz.qpic.cn/mmbiz_png/b96CibCt70iaYNp9ibbYt5S7B7R3JYPypRb2d8jBn7F2ZRQyQHB1RWiaJnMUicogzQw13PAibn2UH11ClsPI4vGlyiaicw/640" data-w="401" src="https://image.jiqizhixin.com/uploads/editor/9f71a87f-a7a6-4adf-bb20-db6d72a50633/640.png" data-fail="0" class="fr-fic fr-dib" style="width: 700%;"&gt;&lt;/p&gt;&lt;p&gt;这里只简单的截取了一些常用到的特征，大家可以根据自己的场景增加各种简单特征、组合特征。日期特征需要注意一下，不同的游戏上线时间不一样、日期格式的数据也不方便运算，比如20181231,20190101,20190102其实都只差一天，但是数值上却差了很大，这里我们直接将日期转换成距今天天数，日期数据数值化，很方便后续的计算处理。 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/p&gt;&lt;section&gt;&lt;section data-mpa-template="t"&gt;&lt;h3&gt;&lt;strong&gt;2. 特征处理&lt;/strong&gt;&lt;/h3&gt;&lt;/section&gt;&lt;/section&gt;&lt;p&gt;&lt;img data-ratio="0.5218340611353712" data-src="https://mmbiz.qpic.cn/mmbiz_png/b96CibCt70iaYNp9ibbYt5S7B7R3JYPypRbXHXY57uVygPribXVTOasU73G9tV04iaiclWlibSgaFZk7ReVnTHt96icyMQ/640" data-w="458" src="https://image.jiqizhixin.com/uploads/editor/5c1a0ed3-6369-41c9-86b5-92ebebdad051/640.png" data-fail="0" class="fr-fic fr-dib" style="width: 700%;"&gt;&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;2.1 缺失值填充&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;在预流失场景中，我们针对登录数据、充值数据做了填0处理，针对日期时间数据做填最大值处理。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;2.2 zscore标准化&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;不同特征的取值范围对模型训练的影响不言而喻，我们有必要对许多特征做一次标准化，比如登陆次数、充值金额等等。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;2.3 onehot处理&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;对于枚举类型的特征，最常用的编码就是OneHot，比如性别。&lt;/p&gt;&lt;section&gt;&lt;section data-mpa-template="t"&gt;&lt;blockquote&gt;&lt;strong&gt;训练模型&lt;/strong&gt;&lt;/blockquote&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;section data-mpa-template="t"&gt;&lt;h3&gt;&lt;strong&gt;1. &lt;strong&gt;模型选择&lt;/strong&gt;&lt;/strong&gt;&lt;/h3&gt;&lt;/section&gt;&lt;/section&gt;&lt;p&gt;预测流失Score和回流Score有许许多多的模型可以选择，本文以LR为例，早点介绍如何在生产过程中实践经典&lt;mark data-type=techmethods data-id=1a0e9c5e-6502-4cd7-8683-6b5ca6c48be2&gt;机器学习&lt;/mark&gt;算法。LR详细介绍参考以下两个链接&lt;/p&gt;&lt;p&gt;&lt;a data-linktype="2" href="https://spark.apache.org/docs/latest/ml-classification-regression.html#logistic-regression" target="_blank"&gt;Logistic regression Docs&lt;/a&gt;&lt;a data-linktype="2" href="https://spark.apache.org/docs/latest/ml-classification-regression.html#logistic-regression" target="_blank"&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a data-linktype="2" href="https://spark.apache.org/docs/latest/api/python/pyspark.ml.html#pyspark.ml.classification.LogisticRegression" target="_blank"&gt;pyspark.ml.classification.LogisticRegression APIs&lt;/a&gt;&lt;a data-linktype="2" href="https://spark.apache.org/docs/latest/api/python/pyspark.ml.html#pyspark.ml.classification.LogisticRegression" target="_blank"&gt;&lt;/a&gt;&lt;/p&gt;&lt;section&gt;&lt;section data-mpa-template="t"&gt;&lt;h3&gt;&lt;strong&gt;2. 模型调参&lt;/strong&gt;&lt;/h3&gt;&lt;/section&gt;&lt;/section&gt;&lt;p&gt;使用&lt;mark data-type=concepts data-id=698eae06-517e-4332-ba61-2de17c83ffb6&gt;验证集&lt;/mark&gt;数据对模型进行调参，以下是LR的可配置&lt;mark data-type=concepts data-id=2e982b73-88e2-41e8-a430-f7ae5a9af4bf&gt;参数&lt;/mark&gt;&lt;/p&gt;&lt;section&gt;&lt;pre data-lang="kotlin"&gt;&lt;code&gt;aggregationDepth: suggested depth for treeAggregate (&amp;gt;= 2). (default: 2)&lt;/code&gt;&lt;code&gt;elasticNetParam: the ElasticNet mixing parameter, in range [0, 1]. For alpha = 0, the penalty is an L2 penalty. For alpha = 1, it is an L1 penalty. (default: 0.0)&lt;/code&gt;&lt;code&gt;family: The name of family which is a description of the label distribution to be used in the model. Supported options: auto, binomial, multinomial (default: auto)&lt;/code&gt;&lt;code&gt;featuresCol: features column name. (default: features)&lt;/code&gt;&lt;code&gt;fitIntercept: whether to fit an intercept term. (default: True)&lt;/code&gt;&lt;code&gt;labelCol: label column name. (default: label, current: ilabel)&lt;/code&gt;&lt;code&gt;maxIter: max number of iterations (&amp;gt;= 0). (default: 100, current: 1000)&lt;/code&gt;&lt;code&gt;predictionCol: prediction column name. (default: prediction)&lt;/code&gt;&lt;code&gt;probabilityCol: Column name for predicted class conditional probabilities. Note: Not all models output well-calibrated probability estimates! These probabilities should be treated as confidences, not precise probabilities. (default: probability, current: score)&lt;/code&gt;&lt;code&gt;rawPredictionCol: raw prediction (a.k.a. confidence) column name. (default: rawPrediction)&lt;/code&gt;&lt;code&gt;regParam: regularization parameter (&amp;gt;= 0). (default: 0.0, current: 0.03)&lt;/code&gt;&lt;code&gt;standardization: whether to standardize the training features before fitting the model. (default: True)&lt;/code&gt;&lt;code&gt;threshold: Threshold in binary classification prediction, in range [0, 1]. If threshold and thresholds are both set, they must match.e.g. if threshold is p, then thresholds must be equal to [1-p, p]. (default: 0.5, current: 0.6)&lt;/code&gt;&lt;code&gt;thresholds: Thresholds in multi-class classification to adjust the probability of predicting each class. Array must have length equal to the number of classes, with values &amp;gt; 0, excepting that at most one value may be 0. The class with largest value p/t is predicted, where p is the original probability of that class and t is the class&amp;#39;s threshold. (undefined)&lt;/code&gt;&lt;code&gt;tol: the convergence tolerance for iterative algorithms (&amp;gt;= 0). (default: 1e-06)&lt;/code&gt;&lt;/pre&gt;&lt;/section&gt;&lt;p&gt;其中常用的&lt;mark data-type=concepts data-id=2e982b73-88e2-41e8-a430-f7ae5a9af4bf&gt;参数&lt;/mark&gt;如最大迭代次数maxIter=1000、正则项regParam=0.03,阈值threshold=0.6&lt;/p&gt;&lt;section&gt;&lt;section data-mpa-template="t"&gt;&lt;blockquote&gt;&lt;strong&gt;离线模型评估&lt;/strong&gt;&lt;/blockquote&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;section data-mpa-template="t"&gt;&lt;h3&gt;&lt;strong&gt;1. 评估指标&lt;/strong&gt;&lt;/h3&gt;&lt;/section&gt;&lt;/section&gt;&lt;p&gt;离线评估的指标有AUC、&lt;mark data-type=concepts data-id=8be77eae-12da-4e9e-9a88-b7f5bae98c2e&gt;准确率&lt;/mark&gt;、召回率、&lt;mark data-type=techmethods data-id=82aeeeba-b738-4a05-b9c2-7ec567c401fe&gt;F1值&lt;/mark&gt;&lt;/p&gt;&lt;p&gt;AUC的介绍可以查看博客&lt;a data-linktype="2" href="https://blog.csdn.net/u013385925/article/details/80385873" target="_blank"&gt;AUC，ROC我看到的最透彻的讲解&lt;/a&gt;，AUC用来衡量一个模型的性能。&lt;mark data-type=concepts data-id=8be77eae-12da-4e9e-9a88-b7f5bae98c2e&gt;准确率&lt;/mark&gt;指的是预测为正样本中有多少是预测对了，召回率指的是有多少正样本被预测出来了。&lt;mark data-type=techmethods data-id=82aeeeba-b738-4a05-b9c2-7ec567c401fe&gt;F1值&lt;/mark&gt;是权衡&lt;mark data-type=concepts data-id=8be77eae-12da-4e9e-9a88-b7f5bae98c2e&gt;准确率&lt;/mark&gt;和召回率的一个数值。&lt;mark data-type=concepts data-id=8be77eae-12da-4e9e-9a88-b7f5bae98c2e&gt;准确率&lt;/mark&gt;、召回率、&lt;mark data-type=techmethods data-id=82aeeeba-b738-4a05-b9c2-7ec567c401fe&gt;F1值&lt;/mark&gt;随阈值的改变而改变，根据产品的实际场景合理的选择阈值。&lt;/p&gt;&lt;p&gt;实现demo，提供三种计算AUC的办法&lt;/p&gt;&lt;section&gt;&lt;pre data-lang="python"&gt;&lt;code&gt;&amp;#39;&amp;#39;&amp;#39;模型评估&amp;#39;&amp;#39;&amp;#39;&lt;/code&gt;&lt;code&gt;# 模型评估&lt;/code&gt;&lt;code&gt;## 训练数据的AUC&lt;/code&gt;&lt;code&gt;print(&amp;quot;train auc is %.6f&amp;quot; %lr_model.summary.areaUnderROC)&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;## 方法一，使用pyspark.mllib.evaluation.BinaryClassificationMetrics来计算AUC&lt;/code&gt;&lt;code&gt;# BinaryClassificationMetrics的&lt;mark data-type=concepts data-id=2e982b73-88e2-41e8-a430-f7ae5a9af4bf&gt;参数&lt;/mark&gt;是 RDD of (score, label) pairs，其中score表示预测为1的概率&lt;/code&gt;&lt;code&gt;binary_metrics = BinaryClassificationMetrics(&lt;/code&gt;&lt;code&gt;   result_df.selectExpr([&amp;#39;ilabel&amp;#39;, &amp;#39;score&amp;#39;]) \&lt;/code&gt;&lt;code&gt;   .rdd.map(lambda x: (float(x[&amp;#39;score&amp;#39;][1]), float(x[&amp;#39;ilabel&amp;#39;]))))&lt;/code&gt;&lt;code&gt;print(&amp;quot;test auc is %.6f&amp;quot; %binary_metrics.areaUnderROC)&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;## 方法二，使用pyspark.ml.evaluation.BinaryClassificationEvaluator来计算AUC&lt;/code&gt;&lt;code&gt;from pyspark.ml.evaluation import BinaryClassificationEvaluator&lt;/code&gt;&lt;code&gt;binary_evaluator = BinaryClassificationEvaluator(rawPredictionCol=&amp;#39;rawPrediction&amp;#39;, labelCol=&amp;#39;ilabel&amp;#39;, metricName=&amp;#39;areaUnderROC&amp;#39;)&lt;/code&gt;&lt;code&gt;print(&amp;quot;test auc is %.6f&amp;quot; %binary_evaluator.evaluate(result_df))&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;## 方法三，使用BinaryLogisticRegressionSummary来计算AUC，注意，直接传入test data，不需要提前预测&lt;/code&gt;&lt;code&gt;print(&amp;quot;test auc is %.6f&amp;quot; %lr_model.evaluate(test_df).areaUnderROC)&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;tn = result_df.filter(result_df[&amp;#39;ilabel&amp;#39;] == 0).filter(result_df[&amp;#39;prediction&amp;#39;] == 0).count()&lt;/code&gt;&lt;code&gt;fp = result_df.filter(result_df[&amp;#39;ilabel&amp;#39;] == 0).filter(result_df[&amp;#39;prediction&amp;#39;] == 1).count()&lt;/code&gt;&lt;code&gt;fn = result_df.filter(result_df[&amp;#39;ilabel&amp;#39;] == 1).filter(result_df[&amp;#39;prediction&amp;#39;] == 0).count()&lt;/code&gt;&lt;code&gt;tp = result_df.filter(result_df[&amp;#39;ilabel&amp;#39;] == 1).filter(result_df[&amp;#39;prediction&amp;#39;] == 1).count()&lt;/code&gt;&lt;code&gt;print(tn, fp, fn, tp)&lt;/code&gt;&lt;code&gt;precision = tp*1.0 / (fp+tp)&lt;/code&gt;&lt;code&gt;recall = tp*1.0 / (fn+tp)&lt;/code&gt;&lt;code&gt;f1 = 2*precision*recall / (precision+recall)&lt;/code&gt;&lt;code&gt;print(&amp;quot;test precision is %.6f&amp;quot; %(precision))&lt;/code&gt;&lt;code&gt;print(&amp;quot;test recall is %.6f&amp;quot; %(recall))&lt;/code&gt;&lt;code&gt;print(&amp;quot;test f1 is %.6f&amp;quot; %(f1))&lt;/code&gt;&lt;/pre&gt;&lt;/section&gt;&lt;p&gt;&lt;strong&gt;&lt;img data-ratio="0.9561752988047809" data-src="https://mmbiz.qpic.cn/mmbiz_png/b96CibCt70iaYNp9ibbYt5S7B7R3JYPypRbL9afrGmu1K14UomXjgzUCl2Gr5AX4n3GfWcLEYKIzwtuiblWnw4r3EA/640" data-w="753" src="https://image.jiqizhixin.com/uploads/editor/f333b355-c5c5-4175-bd35-416650a0f79c/640.png" data-fail="0" class="fr-fic fr-dib" style="width: 700%;"&gt;&lt;/strong&gt;&lt;/p&gt;&lt;section&gt;&lt;section data-mpa-template="t"&gt;&lt;h3&gt;&lt;strong&gt;2. &lt;mark data-type=concepts data-id=356ac86d-6db9-47be-a5fb-b1c9bb405bcc&gt;学习曲线&lt;/mark&gt;&lt;/strong&gt;&lt;/h3&gt;&lt;/section&gt;&lt;/section&gt;&lt;p&gt;通过分析&lt;mark data-type=concepts data-id=356ac86d-6db9-47be-a5fb-b1c9bb405bcc&gt;学习曲线&lt;/mark&gt;，可以诊断高偏差、高方差问题&lt;/p&gt;&lt;p&gt;&lt;img data-ratio="0.6608315098468271" data-src="https://mmbiz.qpic.cn/mmbiz_png/b96CibCt70iaYNp9ibbYt5S7B7R3JYPypRb0qIMpZNe000pbXBQqzlCRcwBPIlBcR79bPO62J8xFGUC49O4TYEREw/640" data-w="457" src="https://image.jiqizhixin.com/uploads/editor/c22ec9bb-8279-486d-b567-e8b062356711/640.png" data-fail="0" class="fr-fic fr-dib" style="width: 700%;"&gt;&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;高偏差，&lt;mark data-type=concepts data-id=174750bc-c8ac-40b1-aa62-27ee956389f8&gt;欠拟合&lt;/mark&gt;，随着训练样本数量增加，最后测试集、&lt;mark data-type=concepts data-id=698eae06-517e-4332-ba61-2de17c83ffb6&gt;验证集&lt;/mark&gt;的误差都停在高位，彼此很接近。&lt;br&gt;尝试解决办法：获得更多的特征、增加多项式特征、减少&lt;mark data-type=concepts data-id=c51052b5-4cd8-4df0-99bb-5aa643c2f027&gt;正则化&lt;/mark&gt;程度&amp;lambda;。&lt;/p&gt;&lt;p&gt;&lt;img data-ratio="0.7081218274111675" data-src="https://mmbiz.qpic.cn/mmbiz_png/b96CibCt70iaYNp9ibbYt5S7B7R3JYPypRbo0anicjrHaia7MV8Bn85yzIOkXw2xUXV2hJfn7UAlKR5tDBfqTYcKEeA/640" data-w="394" src="https://image.jiqizhixin.com/uploads/editor/e1650b86-ed7f-461e-b2fc-e291001703fe/640.png" data-fail="0" class="fr-fic fr-dib" style="width: 700%;"&gt;&lt;/p&gt;&lt;p&gt;&lt;br&gt;&lt;/p&gt;&lt;p&gt;高方差，&lt;mark data-type=concepts data-id=af836eef-be90-4143-a022-46fae3904f0e&gt;过拟合&lt;/mark&gt;，测试集和&lt;mark data-type=concepts data-id=698eae06-517e-4332-ba61-2de17c83ffb6&gt;验证集&lt;/mark&gt;的误差逐渐接近，但还是有一定的距离，随着样本数的增加误差正在逐渐趋于稳定。&lt;br&gt;尝试解决办法：更多的训练样本、减少特征的数量、增加&lt;mark data-type=concepts data-id=c51052b5-4cd8-4df0-99bb-5aa643c2f027&gt;正则化&lt;/mark&gt;程度&amp;lambda;。&lt;/p&gt;&lt;section&gt;&lt;section data-mpa-template="t"&gt;&lt;blockquote&gt;&lt;strong&gt;预测数据&lt;/strong&gt;&lt;/blockquote&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;section data-mpa-template="t"&gt;&lt;h3&gt;&lt;strong&gt;1. 获得预测数据&lt;/strong&gt;&lt;/h3&gt;&lt;/section&gt;&lt;/section&gt;&lt;p&gt;预流失场景中预测数据为本周活跃的用户，预测其是否会在下一周流失；流失场景中预测数据为本周流失用户，预测其是否会在下周回流。&lt;/p&gt;&lt;section&gt;&lt;section data-mpa-template="t"&gt;&lt;h3&gt;&lt;strong&gt;2. 预测数据分组&lt;/strong&gt;&lt;/h3&gt;&lt;/section&gt;&lt;/section&gt;&lt;p&gt;&lt;img data-ratio="0.19741935483870968" data-src="https://mmbiz.qpic.cn/mmbiz_png/b96CibCt70iaYNp9ibbYt5S7B7R3JYPypRb1FDW7lXPViarrB7Nqppah7yJuTxibJvOqpibVuxN6SDrI0YcfKPM3sJwA/640" data-w="775" src="https://image.jiqizhixin.com/uploads/editor/55914e22-444a-4e5d-918f-847b6fb63700/640.png" data-fail="0" class="fr-fic fr-dib" style="width: 700%;"&gt;&lt;/p&gt;&lt;p&gt;首先，将预测数据分成模型预测、随机两组，模型预测组用模型预测Score值，随机预测组用rand的方法输出Score值，再比较Score值与阈值的大小来判断当前样本为正或者负；&lt;/p&gt;&lt;p&gt;然后，将预测后的数据分成2*2组，一个是线上干预组，另一组是线上不干预的对照组，用于对比线上干预的效果。&lt;/p&gt;&lt;section&gt;&lt;section data-mpa-template="t"&gt;&lt;h3&gt;&lt;strong&gt;3. 上线效果分析&lt;/strong&gt;&lt;/h3&gt;&lt;/section&gt;&lt;/section&gt;&lt;p&gt;&lt;img data-ratio="0.3037249283667622" data-src="https://mmbiz.qpic.cn/mmbiz_png/b96CibCt70iaYNp9ibbYt5S7B7R3JYPypRbYIrPWBFN3UkYib8uGe0KZQj60HW4QDLcjFiajShtuSeT7pMPSM4xJlNg/640" data-w="349" src="https://image.jiqizhixin.com/uploads/editor/88e3e4c4-2e7b-4adf-8cd5-c7630d707eea/640.png" data-fail="0" class="fr-fic fr-dib" style="width: 700%;"&gt;&lt;/p&gt;&lt;p&gt;如上图所示，效果分析分为模型效果和干预效果两个维度&lt;/p&gt;&lt;p&gt;&lt;strong&gt;3.1 模型效果&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;分析模型效果时我们需要控制变量，排除干预、不干预的影响。预期模型预测的&lt;mark data-type=concepts data-id=8be77eae-12da-4e9e-9a88-b7f5bae98c2e&gt;准确率&lt;/mark&gt;普遍要好于随机预测的&lt;mark data-type=concepts data-id=8be77eae-12da-4e9e-9a88-b7f5bae98c2e&gt;准确率&lt;/mark&gt;。&lt;/p&gt;&lt;p&gt;同干预的情况下，对比A组和C组的&lt;mark data-type=concepts data-id=8be77eae-12da-4e9e-9a88-b7f5bae98c2e&gt;准确率&lt;/mark&gt;；同不干预的情况下，对比B组和D组的&lt;mark data-type=concepts data-id=8be77eae-12da-4e9e-9a88-b7f5bae98c2e&gt;准确率&lt;/mark&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;3.2 干预效果&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;同样需要排除不同策略预测的影响，预期干预组的留存率或者回流率要普遍好于对照组的留存率或回流率。&lt;/p&gt;&lt;p&gt;同模型预测情况下，对比A组和B组的留存率；同随机预测模型情况下，对比C组和D组的留存率&lt;/p&gt;&lt;section&gt;&lt;section data-mpa-template="t"&gt;&lt;blockquote&gt;&lt;strong&gt;小结&lt;/strong&gt;&lt;/blockquote&gt;&lt;/section&gt;&lt;/section&gt;&lt;p&gt;将全流程串起来，给出如下demo&lt;/p&gt;&lt;section&gt;&lt;pre data-lang="python"&gt;&lt;code&gt;from pyspark.sql import SparkSession&lt;/code&gt;&lt;code&gt;from pyspark.ml import Pipeline&lt;/code&gt;&lt;code&gt;from pyspark.ml.classification import LogisticRegression&lt;/code&gt;&lt;code&gt;from pyspark.ml.feature import StandardScaler, OneHotEncoder, HashingTF, Tokenizer, VectorAssembler&lt;/code&gt;&lt;code&gt;from pyspark.ml.evaluation import BinaryClassificationEvaluator&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;# 训练数据&lt;/code&gt;&lt;code&gt;# 预测数据&lt;/code&gt;&lt;code&gt;# 预测结果表&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;# 需要做缺失值处理的特征&lt;/code&gt;&lt;code&gt;missing_value_zero_features = [&amp;#39;lilastactdate&amp;#39; ...]&lt;/code&gt;&lt;code&gt;missing_value_max_features = [&amp;#39;dilastactdate&amp;#39; ...]&lt;/code&gt;&lt;code&gt;# z_score&lt;/code&gt;&lt;code&gt;z_score_features = [&amp;#39;lilastactdate&amp;#39; ...]&lt;/code&gt;&lt;code&gt;# one_hot_data&lt;/code&gt;&lt;code&gt;one_hot_features = [&amp;#39;idayact14_loss&amp;#39; ...]&lt;/code&gt;&lt;code&gt;print(&amp;#39;args init finish&amp;#39;)&lt;/code&gt;&lt;code&gt;   &lt;/code&gt;&lt;code&gt;def get_data():  &lt;/code&gt;&lt;code&gt;   # 获得训练数据&lt;/code&gt;&lt;code&gt;   session = SparkSession \&lt;/code&gt;&lt;code&gt;           .builder \&lt;/code&gt;&lt;code&gt;           .appName(&amp;quot;prelost-lr&amp;quot;) \&lt;/code&gt;&lt;code&gt;           .getOrCreate()&lt;/code&gt;&lt;code&gt;   train_df = ...&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;   # 缺失值过滤&lt;/code&gt;&lt;code&gt;   train_df = train_df.dropna(subset=[&amp;#39;sopenid&amp;#39;, &amp;#39;iuin&amp;#39;]) \&lt;/code&gt;&lt;code&gt;       .na.fill(0, missing_value_zero_features) \&lt;/code&gt;&lt;code&gt;       .na.fill(9999, missing_value_max_features)&lt;/code&gt;&lt;code&gt;       &lt;/code&gt;&lt;code&gt;   # 测试集和训练集&lt;/code&gt;&lt;code&gt;   (raw_train_data, raw_test_data) = train_df.randomSplit([0.7, 0.3], seed=43)&lt;/code&gt;&lt;code&gt;   print(&amp;#39;train data count is&amp;#39;, raw_train_data.count())&lt;/code&gt;&lt;code&gt;   print(&amp;#39;test data count is&amp;#39;, raw_test_data.count())&lt;/code&gt;&lt;code&gt;   return raw_train_data, raw_test_data&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;def features_clear():&lt;/code&gt;&lt;code&gt;   # Configure an ML pipeline, which consists of some stages&lt;/code&gt;&lt;code&gt;   # 将所有的z_score_features特征合并起来一起做归一化&lt;/code&gt;&lt;code&gt;   z_score_vector_assember = VectorAssembler(inputCols=z_score_features, outputCol=&amp;quot;z_score_features&amp;quot;)&lt;/code&gt;&lt;code&gt;   z_score_standard_scaler = StandardScaler(inputCol=z_score_vector_assember.getOutputCol(), outputCol=&amp;quot;z_score_features_scaled&amp;quot;)&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;   # 组合所有特征到features字段里&lt;/code&gt;&lt;code&gt;   features = [z_score_standard_scaler.getOutputCol()] + one_hot_features&lt;/code&gt;&lt;code&gt;   features_vector_assember = VectorAssembler(inputCols=features, outputCol=&amp;quot;features&amp;quot;)&lt;/code&gt;&lt;code&gt;   &lt;/code&gt;&lt;code&gt;   lr = LogisticRegression(maxIter=1000, regParam=0.03, threshold=0.6, labelCol=&amp;quot;ilabel&amp;quot;, probabilityCol=&amp;quot;score&amp;quot;)&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;   model_pipeline = Pipeline(stages=[z_score_vector_assember, z_score_standard_scaler,&lt;/code&gt;&lt;code&gt;                                        features_vector_assember, lr])&lt;/code&gt;&lt;code&gt;   print(&amp;#39;features clear pipeline config finish&amp;#39;)&lt;/code&gt;&lt;code&gt;   return model_pipeline&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;def model_train(model_pipeline, raw_train_data):&lt;/code&gt;&lt;code&gt;   model = model_pipeline.fit(raw_train_data)&lt;/code&gt;&lt;code&gt;   print(&amp;#39;model train finish&amp;#39;)&lt;/code&gt;&lt;code&gt;   return model&lt;/code&gt;&lt;code&gt;   &lt;/code&gt;&lt;code&gt;def model_evaluator(model, data):&lt;/code&gt;&lt;code&gt;   result_data = model.transform(data)&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;   binary_evaluator = BinaryClassificationEvaluator(rawPredictionCol=&amp;#39;rawPrediction&amp;#39;, labelCol=&amp;#39;ilabel&amp;#39;, metricName=&amp;#39;areaUnderROC&amp;#39;)&lt;/code&gt;&lt;code&gt;   print(&amp;quot;auc is %.6f&amp;quot; %binary_evaluator.evaluate(result_data))&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;   tn = result_data.filter(result_data[&amp;#39;ilabel&amp;#39;] == 0).filter(result_data[&amp;#39;prediction&amp;#39;] == 0).count()&lt;/code&gt;&lt;code&gt;   fp = result_data.filter(result_data[&amp;#39;ilabel&amp;#39;] == 0).filter(result_data[&amp;#39;prediction&amp;#39;] == 1).count()&lt;/code&gt;&lt;code&gt;   fn = result_data.filter(result_data[&amp;#39;ilabel&amp;#39;] == 1).filter(result_data[&amp;#39;prediction&amp;#39;] == 0).count()&lt;/code&gt;&lt;code&gt;   tp = result_data.filter(result_data[&amp;#39;ilabel&amp;#39;] == 1).filter(result_data[&amp;#39;prediction&amp;#39;] == 1).count()&lt;/code&gt;&lt;code&gt;   print(tn, fp, fn, tp)&lt;/code&gt;&lt;code&gt;   precision = tp*1.0 / (fp+tp)&lt;/code&gt;&lt;code&gt;   recall = tp*1.0 / (fn+tp)&lt;/code&gt;&lt;code&gt;   f1 = 2*precision*recall / (precision+recall)&lt;/code&gt;&lt;code&gt;   print(&amp;quot;precision is %.6f&amp;quot; %(precision))&lt;/code&gt;&lt;code&gt;   print(&amp;quot;recall is %.6f&amp;quot; %(recall))&lt;/code&gt;&lt;code&gt;   print(&amp;quot;f1 is %.6f&amp;quot; %(f1))&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;def model_predict():&lt;/code&gt;&lt;code&gt;   result_data = lr_model.transform(test_data)&lt;/code&gt;&lt;code&gt;   tdw_util = TDWUtil(tdw_user_name, tdw_user_pwd, tdw_db)&lt;/code&gt;&lt;code&gt;   tdw_util.dropPartition(tdw_predict_result_tbl, tdw_predict_result_tbl_pri_partition, level=0)&lt;/code&gt;&lt;code&gt;   tdw_util.createListPartition(tdw_predict_result_tbl, tdw_predict_result_tbl_pri_partition, tdw_predict_result_tbl_pri_date, 0)&lt;/code&gt;&lt;code&gt;   tdw.saveToTable(result_data, tdw_predict_result_tbl, tdw_predict_result_tbl_pri_partition)&lt;/code&gt;&lt;code&gt;   print(&amp;#39;save data into tdw finish&amp;#39;)&lt;/code&gt;&lt;code&gt;   &lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;
&lt;/code&gt;&lt;code&gt;raw_train_data, raw_test_data = get_data()&lt;/code&gt;&lt;code&gt;model_pipeline = features_clear()&lt;/code&gt;&lt;code&gt;model = model_train(model_pipeline, raw_train_data)&lt;/code&gt;&lt;code&gt;print(&amp;#39;------------------ train model ------------------&amp;#39;)&lt;/code&gt;&lt;code&gt;model_evaluator(model, raw_train_data)&lt;/code&gt;&lt;code&gt;print(&amp;#39;------------------ predict data ------------------&amp;#39;)&lt;/code&gt;&lt;code&gt;model_evaluator(model, raw_test_data)&lt;/code&gt;&lt;/pre&gt;&lt;/section&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/59922-%E7%BB%8F%E5%85%B8-%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0-%E9%A2%84%E6%B5%81</guid>
      <pubDate>Tue, 06 Aug 2019 16:17:20 CST</pubDate>
    </item>
    <item>
      <title>人脸识别经典算法二：LBP方法</title>
      <link>https://itindex.net/detail/59397-%E4%BA%BA%E8%84%B8%E8%AF%86%E5%88%AB-%E7%BB%8F%E5%85%B8-%E7%AE%97%E6%B3%95</link>
      <description>&lt;div&gt;  &lt;p&gt;与   &lt;a href="http://blog.csdn.net/smartempire/article/details/21406005" rel="nofollow"&gt;第一篇博文特征脸方法&lt;/a&gt;不同，LBP（Local
 Binary Patterns，局部二值模式）是提取局部特征作为判别依据的。LBP方法显著的优点是对光照不敏感，但是依然没有解决姿态和表情的问题。不过相比于特征脸方法，LBP的识别率已经有了很大的提升。在[1]的文章里，有些人脸库的识别率已经达到了98%+。&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;1、LBP特征提取&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;最初的LBP是定义在像素3x3邻域内的，以邻域中心像素为阈值，将相邻的8个像素的灰度值与其进行比较，若周围像素值大于中心像素值，则该像素点的位置被标记为1，否则为0。这样，3x3邻域内的8个点经比较可产生8位二进制数（通常转换为十进制数即LBP码，共256种），即得到该邻域中心像素点的LBP值，并用这个值来反映该区域的纹理信息。如下图所示：&lt;/p&gt;  &lt;p&gt;   &lt;img alt="" src="https://img-blog.csdn.net/20140409100451171"&gt;&lt;/img&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;用比较正式的公式来定义的话：&lt;/p&gt;  &lt;p&gt;   &lt;img alt="" src="https://img-blog.csdn.net/20140409102028328"&gt;&lt;/img&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;其中   &lt;img alt="" src="https://img-blog.csdn.net/20140409102051484"&gt;&lt;/img&gt;代表3x3邻域的中心元素，它的像素值为ic，ip代表邻域内其他像素的值。s(x)是符号函数，定义如下：   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;   &lt;img alt="" src="https://img-blog.csdn.net/20140409102057984"&gt;&lt;/img&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;LBP的改进版本&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;（1）圆形LBP算子&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;基本的 LBP算子的最大缺陷在于它只覆盖了一个固定半径范围内的小区域，这显然不能满足不同尺寸和频率纹理的需要。为了适应不同尺度的纹理特征，并达到灰度和旋转不变性的要求，Ojala等对 LBP 算子进行了改进，将 3×3邻域扩展到任意邻域，并用圆形邻域代替了正方形邻域，改进后的 LBP 算子允许在半径为 R 的圆形邻域内有任意多个像素点。从而得到了诸如半径为R的圆形区域内含有P个采样点的LBP算子。比如下图定了一个5x5的邻域：&lt;/p&gt;  &lt;p&gt;   &lt;img alt="" src="https://img-blog.csdn.net/20140409101523156"&gt;&lt;/img&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;上图内有八个黑色的采样点，每个采样点的值可以通过下式计算：&lt;/p&gt;  &lt;p&gt;   &lt;img alt="" src="https://img-blog.csdn.net/20140409102819171"&gt;&lt;/img&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;其中   &lt;img alt="" src="https://img-blog.csdn.net/20140409102904234"&gt;&lt;/img&gt;为邻域中心点，   &lt;img alt="" src="https://img-blog.csdn.net/20140409102917984"&gt;&lt;/img&gt;为某个采样点。通过上式可以计算任意个采样点的坐标，但是计算得到的坐标未必完全是整数，所以可以通过双线性插值来得到该采样点的像素值：&lt;/p&gt;  &lt;p&gt;   &lt;img alt="" src="https://img-blog.csdn.net/20140409103242671"&gt;&lt;/img&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;（2）LBP等价模式&lt;/strong&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;一个LBP算子可以产生不同的二进制模式，对于半径为R的圆形区域内含有P个采样点的LBP算子将会产生2^P种模式。很显然，随着邻域集内采样点数的增加，二进制模式的种类是急剧增加的。例如：5×5邻域内20个采样点，有2   &lt;sup&gt;20&lt;/sup&gt;＝1,048,576种二进制模式。如此多的二值模式无论对于纹理的提取还是对于纹理的识别、分类及信息的存取都是不利的。同时，过多的模式种类对于纹理的表达是不利的。例如，将LBP算子用于纹理分类或人脸识别时，常采用LBP模式的统计直方图来表达图像的信息，而较多的模式种类将使得数据量过大，且直方图过于稀疏。因此，需要对原始的LBP模式进行降维，使得数据量减少的情况下能最好的代表图像的信息。&lt;/p&gt;  &lt;p&gt;        为了解决二进制模式过多的问题，提高统计性，Ojala提出了采用一种“等价模式”（Uniform Pattern）来对LBP算子的模式种类进行降维。Ojala等认为，在实际图像中，绝大多数LBP模式最多只包含两次从1到0或从0到1的跳变。因此，Ojala将“等价模式”定义为：当某个LBP所对应的循环二进制数从0到1或从1到0最多有两次跳变时，该LBP所对应的二进制就称为一个等价模式类。如00000000（0次跳变），00000111（只含一次从0到1的跳变），10001111（先由1跳到0，再由0跳到1，共两次跳变）都是等价模式类。除等价模式类以外的模式都归为另一类，称为混合模式类，例如10010111（共四次跳变）。比如下图给出了几种等价模式的示意图。&lt;/p&gt;  &lt;p&gt;   &lt;img alt="" src="https://img-blog.csdn.net/20140409104010500"&gt;&lt;/img&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;       通过这样的改进，二进制模式的种类大大减少，而不会丢失任何信息。模式数量由原来的2   &lt;sup&gt;P&lt;/sup&gt;种减少为 P ( P-1)+2种，其中P表示邻域集内的采样点数。对于3×3邻域内8个采样点来说，二进制模式由原始的256种减少为58种，这使得特征向量的维数更少，并且可以减少高频噪声带来的影响。这几段摘自[2]。&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;通过上述方法，每个像素都会根据邻域信息得到一个LBP值，如果以图像的形式显示出来可以得到下图，明显LBP对光照有较强的鲁棒性。&lt;/p&gt;  &lt;p&gt;   &lt;img alt="" src="https://img-blog.csdn.net/20140409104518703"&gt;&lt;/img&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;2、LBP特征匹配&lt;/strong&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;如果将以上得到的LBP值直接用于人脸识别，其实和不提取LBP特征没什么区别，会造成计算量准确率等一系列问题。文献[1]中，将一副人脸图像分为7x7的子区域（如下图），并在子区域内根据LBP值统计其直方图，以直方图作为其判别特征。这样做的好处是在一定范围内避免图像没完全对准的情况，同时也对LBP特征做了降维处理。&lt;/p&gt;  &lt;p&gt;   &lt;img alt="" src="https://img-blog.csdn.net/20140409105549078"&gt;&lt;/img&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;对于得到的直方图特征，有多种方法可以判别其相似性，假设已知人脸直方图为M   &lt;sub&gt;i&lt;/sub&gt;​，待匹配人脸直方图为S   &lt;sub&gt;i&lt;/sub&gt;，那么可以通过:&lt;/p&gt;  &lt;p&gt;(1)直方图交叉核方法&lt;/p&gt;  &lt;p&gt;   &lt;img alt="" src="https://img-blog.csdn.net/20140409110315812"&gt;&lt;/img&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;该方法的介绍在博文：   &lt;a href="http://blog.csdn.net/smartempire/article/details/23168945" rel="nofollow"&gt;Histogram
 intersection(直方图交叉核,Pyramid Match Kernel)&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;(2)卡方统计方法&lt;/p&gt;  &lt;p&gt;   &lt;img alt="" src="https://img-blog.csdn.net/20140409110426046"&gt;&lt;/img&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;该方法的介绍在博文：   &lt;a href="http://blog.csdn.net/smartempire/article/details/23203183" rel="nofollow"&gt;卡方检验（Chi
 square statistic）&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;参考文献：&lt;/p&gt;  &lt;p&gt;[1]Timo Ahonen, Abdenour Hadid：Face Recognition with Local Binary Patterns&lt;/p&gt;  &lt;p&gt;[2]目标检测的图像特征提取之（二）LBP特征&lt;/p&gt;&lt;/div&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>geek</category>
      <guid isPermaLink="true">https://itindex.net/detail/59397-%E4%BA%BA%E8%84%B8%E8%AF%86%E5%88%AB-%E7%BB%8F%E5%85%B8-%E7%AE%97%E6%B3%95</guid>
      <pubDate>Tue, 26 Mar 2019 00:00:00 CST</pubDate>
    </item>
    <item>
      <title>国家命运与个人命运 | 吉林大学经济学院、金融学院院长李晓教授在2018年毕业典礼上的讲话</title>
      <link>https://itindex.net/detail/58505-%E5%9B%BD%E5%AE%B6%E5%91%BD%E8%BF%90-%E4%B8%AA%E4%BA%BA-%E5%91%BD%E8%BF%90</link>
      <description>&lt;div&gt;    &lt;p&gt;&lt;/p&gt;    &lt;p&gt;      &lt;img&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;亲爱的经济学院、金融学院的全体毕业生同学，尊敬的毕业生家长，经济学院的各位领导和老师，大家下午好！&lt;/p&gt;    &lt;p&gt;大家可能注意到，与以往不同，今天我准备了个讲话提纲，因为我认真地做了一些准备，权当是我给各位同学们上的最后一堂课，也包含着对各位同学的嘱托。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;今天我想讲三个方面的问题：&lt;/strong&gt;      &lt;strong&gt;第一是中美贸易战对我们意味着什么？第二是我们应当从中吸取什么样的教训？第三是想借此机会谈几点对同学们未来工作、生活的嘱托和希望。&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;第一个问题：中美贸易战对我们意味着什么？&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;从今年三月份一直到今天，世界上最为吸引眼球的事件不再是叙利亚，不再是北朝鲜，不再是俄罗斯世界杯，而是中美关系。具体说，就是中美贸易战真的要打响了。这是我们最不情愿看到的，也是力图避免的事情。但问题是主动权不在我们手里。对于这场贸易战，我的关注点不在贸易领域，它使我有着更为深重的忧虑和危机感。&lt;/p&gt;    &lt;p&gt;首先，从贸易角度来看，既然是美国发动的贸易战，那么权且按照美国方面的统计来看下面一组数据。去年，中国从美国的进口额为1300亿美元。前不久中国自卫性地反击了美国，征收美国500亿美元商品的25%的关税以后，特朗普又下令加征了我们2000亿美元，然后再准备如果中国反击，会再加增2000亿美元。这是个简单的算术问题。去年中国向美国出口约5000亿美元，现在两个2000亿加上一个500亿，他动用了4500亿，还剩下500亿美元左右的额度。而我们已经动用了500还剩800亿，美国追加的这2000亿，我们跟不上了。如果我们也同额度回击，不仅是将从美国的进口商品清零，而是负进口了，理论、实践上都是不现实的。这是美国对中国做出最具羞辱性的行为，但是没有办法，因为我们对美国市场依赖太深。&lt;/p&gt;    &lt;p&gt;我们知道，由于全球价值链的形成与发展，国家间的分工已经从产业内部分工发展到产品内部的分工。我们称之为生产工序的专业化。因此，一个国家在贸易中实际获得的收益与其实际贸易收支状况未必呈正向关系。再加上在此过程中，中美双方的统计方式不同，如是否将经香港的转口贸易统计在内，以及是按商品的离岸价格还是到岸价格统计等方面双方存在分歧，所以美方统计的中国对美贸易顺差比我方统计多出1000亿美元左右。按照美国商务部统计，美国对华贸易逆差从1985年开始的6亿美元增加到2017年的3752亿美元，创历史新高。这期间美国对华贸易逆差总额达到4.7万亿美元。而去年，美国对华贸易逆差占到了整个美国对外贸易逆差的将近一半。再从中国来看，我们对美国的顺差从2010年以来的八年时间里，平均超过78%，有四年超过80%，一年超过130%。&lt;/p&gt;    &lt;p&gt;这些数据意味这什么？说明对美贸易顺差成为中国经常项目顺差的最重要部分，没有了对美贸易顺差，我们的经常项目顺差将会大大缩小。&lt;/p&gt;    &lt;p&gt;另一方面，我们对美国制造业及其核心技术的依赖更为严重。“中兴事件”虽然尚未结束，但仅就目前的后果来看，不只是十几亿美元罚金的问题，美国国会已经否决了特朗普总统暂缓中止中兴业务的提案，即便最终通过该项提案，恐怕也要按照美国人的规则来改组中兴的管理层及企业管理机制和运行规则，美国甚至要派出一个监督官到这家中国企业。这起事件足以让我们清醒地看到自己同美国之间巨大的技术差距以及对美国核心技术的严重依赖。&lt;/p&gt;    &lt;p&gt;同时，我们对美国农产品的依赖也同样比较严重。去年，中国自产大豆1400万吨，总进口是9554万吨。大豆生产是非常耗费土地的，平均每生产一吨大豆需要八亩土地。这些进口大豆若是换成中国自种，要消耗7.6亿亩的土地。而中国的农业耕地红线是21亿亩，拿出三分之一的土地种大豆可能吗？答案很明显。不进口可以吗？很难。因为人民对高质量生活的向往和需求，使得植物蛋白是不可或缺的。而且这些蛋白加工以后的残渣可以用来喂猪喂牛，保障畜牧业发展。如果不进口，大豆及其附属品的价格都要提高，意味着要出现某些生活必需品的物价上涨。有人说，我们转向巴西进口吧！问题是，全球大豆生产的相当大部分被几家美国公司控制着。巴西大豆从生产、运营到销售几乎都是美国公司控制的。&lt;/p&gt;    &lt;p&gt;更为本质性的，是我们对“美元体系”的依赖。听过我课的同学们，一定清楚这个原理。&lt;/p&gt;    &lt;p&gt;总体来看，现今的“美元体系”主要靠三个机制来运行：&lt;/p&gt;    &lt;p&gt;一个是商品美元还流机制。中国、日本、德国等“贸易国家”向美国出口赚取美元以后，还要将其中相当大部分借给美国。美元是世界清算货币、结算货币和主要的资本市场交易货币，如果不借给它，美国需要自己满足基础货币发行的话，它就会印钞，有可能引发美元贬值。这意味一方面，我们本身拥有的美元储备缩水，这是我们不愿意看到的，另一方面美元贬值意味着我们本币升值，对出口非常不利。所以，作为“贸易国家”的悲剧就在于，我们需要被动地维持美元汇率的稳定，尽量不让美元贬值。也就是说，世界上最大的债权国要维持世界上最大的债务国的货币稳定，这是商品美元还流机制迫使我们承担的被动责任，也是我们大量购买美国国债、公司债的原因。&lt;/p&gt;    &lt;p&gt;第二个机制是石油交易的美元计价机制。1971年尼克松关闭“黄金窗口”、美元与黄金脱钩之后，美元面临的最大问题是如何确保自身的储备货币地位。为此，美国迅速找到了石油这种工业血液，联合沙特等国建立了石油交易的美元计价机制。这就意味着其他国家若要进口石油必须用美元支付，因而就必须储备美元。这样，美元在与黄金脱钩之后依然牢固地保持着全球储备货币的地位。&lt;/p&gt;    &lt;p&gt;第三个是美国对外债务的本币计价机制。美国80%以上的对外债务是以自己可以印刷的美元计价的。就此大家不难想象，美国霸权或者说美元霸权达到一种什么样的程度！也就是说，在理论上和实践上讲，针对自己的对外负债美国是可以通过印刷美元解决的。当然，正是由于美元是美国控制世界的最主要工具，现实中美联储、财政部还是格外慎重的，轻易不会乱来。但事实上，美国在2008年危机之后已经搞了四次量化宽松，释放出大量流动性。我曾在课堂上说过，学习经济学或研究经济学的人不要轻言“美国衰落”。在我看来，“美国衰落”有一个重要标志，即当美国对外发债的大部分不用美元标价而是用欧元、英镑、日元或者人民币标价的时候，这个国家真的是衰落了。如果你看不到这一天，请不要轻言“美国衰落”。&lt;/p&gt;    &lt;p&gt;正是由于中国处在“美元体系”当中，不仅使得我们拥有大量的美国国债，而且基础货币发行也对其产生严重依赖。&lt;/p&gt;    &lt;p&gt;坦率地说，近十年来，中国M2的发行量几乎是世界第一。我们的M2对GDP之比为2.1：1，而美国为0.9：1。发了这么多货币，为什么大家感觉不到呢？有很多原因，但有两个原因最为重要。一是我们的基础货币发行很大程度是用外汇占款来实现的。也就是央行收购企业和公司个人手中的美元，按照市场汇率再释放出人民币，通过这种方式把流动性释放出来。外汇占款占到央行释放流动性的比例最高时达到80%以上，目前也在60%到左右。也就是说，美元储备是人民币发行的重要的信用基础，这在很大程度上确保了人民币汇率的稳定。当然还有一个重要原因就是房地产扩张，使得央行释放出来的相当大一部分流动性被房地产套住了。&lt;/p&gt;    &lt;p&gt;所以，贸易战果真打下去，接下来的影响就会涉及到货币金融领域。美国人非常清楚，如果我们的美元储备大幅度减少，那么人民币发行的信用基础就会出问题。还有一点，就是我们赚取外汇的能力也将受到影响。由于中国是典型的“贸易国家”，本币不是世界货币，不得不将货币信用寄托在其他货币比如美元身上，而且国内的经济发展、军队的现代化军队建设，包括大国外交、“一带一路”都需要大量资金，因而外汇储备规模对中国而言格外重要。就近几年外汇增长状况来看，2016年我们在投资领域的外汇净收益出现了440多亿美元的负值。2017年我们加强了外汇管制，勉强恢复到近130亿美元的正值。但是今年1—5月，我们在投资领域中的外汇收入不足50亿美元。在贸易领域的数据就更难看了。去年上半年全口径贸易顺差尚有540亿美元左右，但截止到今年五月全口径的贸易逆差将近250亿美元。六月份的统计还没出来，但一个月扭转不了大局。也就是说，今年上半年中国对外贸易的净逆差格局已定。更为重要的是，我们的外汇储备状况也不容乐观。有学者测算过，截止到今年五月份，我国的净外汇储备也就是外汇储备减去外币负债，约为1.9万亿美元，比2013年2.96万亿美元的峰值减少了近30%。关键问题是，这1.9万亿美元并不都是归我们所有。根据国家统计局的数据，到今年四月底，规模以上的外资企业（含港澳台）总资产为21.68万亿人民币，按照6.45的汇率计算，折合成美元资产的话约为1.55万亿美元。也就是说，在1.9万亿外汇储备净值中有80%以上是外资企业拥有的。我在授课时曾说过，由外资企业投资所形成的外汇储备相当于赌场的筹码。什么概念呢？赌客进赌场后会将各种货币换成筹码，无论在赌场中玩输了还是赢了，他所拥有的筹码可以再换成自己需要的货币拿走。也就是说，这些投资的所有权归外资企业，外资企业可以随时撤资或者在投资期限到期后撤资。虽然现阶段中美贸易战的爆发不会导致外资全部撤走，假如只撤资三成，也就是5000亿美元左右，1.9万亿再减去5000亿，我们还剩多少？我们还有那么多要做的事情需要钱。&lt;/p&gt;    &lt;p&gt;所以，特朗普发动贸易战的目的究竟是什么？我想恐怕不只在贸易领域，还在“中国制造2025”，更可能是通过贸易战的方式迫使我国做出更大让步，而且很可能是迫使中国在货币金融领域更大开放。我们知道，美国是一个地地道道的“金融国家”，我十几年来一直研究这个问题。表面上看，特朗普发动贸易战是在兑现自己的竞选承诺，为“铁锈地带”那几个州的蓝领工人争取更大利益，迄今为止他在这方面做得很不错。但由于美国经济结构的变化即日益高度金融化，华尔街金融资本的利益是其必须予以重视的。金融资本的目标是要赚取全球金融市场的收益，其前提条件就是世界各国货币金融市场的开放，但迄今为止中国这块骨头美国始终没有啃下来。我们的资本项目没有完全放开。特朗普的发动对华贸易战的核心目标有许多，我想在他的谋划中，不会没有迫使中国更大幅度开放货币金融市场的目标。&lt;/p&gt;    &lt;p&gt;当然，美国更为重大的国家战略利益就是遏制中国的崛起。对此我们不要抱有丝毫幻想，不要以为这是特朗普个人意愿。在最近的一次研讨会上，一位著名学者讲述了他的一位刚从美国回来的华人朋友在美国“美中关系委员会”的经历。这个委员会的宗旨是促进美中友好关系，在他此前的多次访问中，委员会工作人员都是热情接待，笑脸相迎，但这次却像躲瘟神一样回避他，他说自己感到了“麦卡锡主义的回潮。”现在，美国对中国的恐惧与敌视达到了我们难以想象的程度。所以，在特朗普对华采取强硬的贸易制裁措施之后，他的支持力不降反升，目前达到40%以上，而且美国共和党、民主党在这一问题上的政治共识高度一致。自特朗普上台以来，两党之争非常多，但唯独在“中国问题”上高度一致。今天，有很多学者试图把中美之间的冲突局限在贸易战范围，认定它只是场贸易冲突，主张不要把它扩大到其他领域中去；还有一些学者认定这场贸易战打下去美国必输，中国必赢。不论他们是怎么测算的，我认为这是一厢情愿或不符合常识的。对一般国家而言，贸易战在经济学上一定是双输的。但是对于大国而言，关键在于谁输得起。历史经验证明，大国之间特别是“老大”和“老二”之间的较量，更多的不是经济行为，不是以经济利益为目的，而是一种国际政治行为，是以国家利益为目标的。国际政治竞争不是“正和游戏”，而是“零和游戏”。经济学与政治学的逻辑有很多不同，一个主要的区别在于，经济学研究的是杀敌一万自损八千还是自损六千的问题，它的逻辑是如何让己方避免自损八千，尽量实现自损六千，即实现资源约束条件下以最小的成本达成最大绩效；与经济行为不同，政治的逻辑是只要我赢，战胜对手，牺牲多少无所谓，在所不惜。因此，两者的逻辑与行为规则是不一样的。刚才，大家合唱的国歌里有一句话：“中华民族到了最危险的时候”。现在，我不敢说是最危险的时候，但可以说，中华民族到了新的危险的时候。对于今天的中国而言，最大的危机不是贸易冲突，而是世界上最强大的霸权国家已经公开把中国当成了最主要的对手，在和平时期利用经济战的手段发起了对中国的全面遏制和攻击，同时还利用其超强的全球军事实力对中国进行越来越多的威慑，制造周边冲突乃至危机来干扰我们的和平发展进程。&lt;/p&gt;    &lt;p&gt;前不久，美国国务卿蓬佩奥有一个发言，赤裸裸地攻击中国是一个掠夺性的国家，是一个偷取知识产权、盗取别人技术、强迫转移技术、强迫地猎取别人资源的国家。这种攻击值得我们高度重视，他是在把美中冲突上升到一种新的意识形态高度。最近，美国通讯委员会发表公告，于今年6月11日废止了2015年奥巴马政府时期制定的网络中立法案。我们知道，互联网思维、原创技术与技术服务，所有这一切都以美国为核心。当年，美国为了促进国内网络运营商之间的公平竞争，同时也是为了让世界各国放心使用美国技术、拓展全球市场，搞了一个网络中立法案。但是现在这个网络中立法则没有了，意味着互联网服务提供商可以在提前告知消费者的情况下，屏蔽这些网站或者降低这些网站的访问速度，也就是断网。如果一旦对中国采取这种措施，我们银行、交通、商业、邮电等系统可能会瘫痪。最近有一则报道，美国网络军已经得到国会授权，可以对网络攻击和盗取美国知识产权行为作出攻击，锁定地址后利用美国的网络特权，即根服务器关闭攻击者网站。现在全球的根服务器有十三个，其中一个主根服务器和九个辅根服务器在美国，其余的三个分别在瑞典、荷兰和日本。所以，我们必须认识到，美国在正在做更多、更充分的准备。&lt;/p&gt;    &lt;p&gt;最近，大家都看到一张G7首脑会议上的照片，场面类似“最后的晚餐”，特朗普与德国总理默克尔等其他国家首脑冷峻对视，似乎不共戴天。但是要知道，正是在这次会议上特朗普提出了一个计划，叫G7国家经济一体化，主张七个发达国家相互之间实现零关税、零补贴、零壁垒，据说已经得到德国的同意。也许德国的这种首肯是表面的，由于涉及市场份额等复杂的因素，其他发达国家的立场很可能与美国不一致，因为美国市场份额太大，竞争力太强，所以七国间的经济一体化肯定不会顺利。但美国的这种行为意味着一个严峻趋势，即它已经下定决心废除WTO的全球多边贸易规则，也就是我们坚持倡导的全球多边贸易规则。这个规则曾经是美国人创立并坚持实施的。今天他们不想再按此规则再做下去了，要搞一套新的、更高标准的规则。在这方面，我们千万不要以为特朗普对欧盟、日本和其他发达国家的贸易保护主义行为将会促使这些国家同中国坚定地站在一起，抵制美国的逆全球化行动。事实上，这些国家在知识产权问题、强制性技术转让、企业并购等方面对中国的指责、攻击同美国并无二致，立场完全一致。&lt;/p&gt;    &lt;p&gt;所以，我们不能把中美贸易战仅仅局限于贸易领域，这本质上是一场国运之战。我们更不能将这一场争端视为短期内可以解决的。仅就贸易争端而言，从1960年代一直到1980年代末，美国和日本曾经发生过一场漫长的贸易争端，这场争端打了30年，结果是日本泡沫经济崩溃，陷入“失去的二十年”。中美之间的冲突作为一场大国博弈，恐怕需要至少50年甚至更长时间。今天的一切，不过是一场历史大戏的开幕。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;第二个问题，就迄今为止的中美贸易争端而言，我们需要吸取哪些教训？&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;我想从两个方面来谈。&lt;/p&gt;    &lt;p&gt;首先，就眼前的教训看，主要有两点：一是盲目自大的情绪。一百多年来我们被西方侵略、压迫的太久，心中的大国情怀不仅强烈也更为迫切。必须承认，改革开放40年来中国经济发展取得了非凡的成就，令世界瞩目，在某些领域的进步与发展甚至走到了世界前列。但也正因为如此，我们产生了一种举国的自豪感，同时也伴随着一些自大情结。中美贸易战，尤其是“中兴事件”不啻为一剂强烈的清醒剂，让我们意识到自己与美国之间存在的巨大技术差距。事实上，我们在许多核心技术领域与国外的差距十分巨大。马航370事件出现后，很多人才知道罗尔斯罗伊斯公司对自己生产的飞机发动机的运转状况，包括在什么地方运转、在哪个高度运转、在什么时间运转，是完全可以掌握的。前不久，一家汽车零配件公司的总经理跟我讲，世界上有两三家公司的汽车喷油技术做的最好，但是我们军车的喷油嘴一定不能用外国的，即便国产喷油嘴质量不高也要用自产的，因为国外厂家都可以进行喷油嘴控制，关键时刻可以进行停止发动机喷油的操纵。我们知道，网络技术有三个层次，最核心的是原发性的技术创新，其次是原发性的技术进步及其产业化，如芯片，再次才是利用互联网思维和互联网技术进行的规模经济的市场开发。我们经常搞“光棍节”购物狂欢，无论是阿里巴巴还是京东等都是利用中国巨大的市场经济规模实现的快速扩张，跟原发性的技术创新思维、原发性的技术进步及其产业化毫无关系，只不过是运用别人的技术思维、产业化的技术，利用中国的巨大市场规模迅速推广而成。二是这场争端使我们更加清醒地意识到，迄今为止中国的经济增长模式已经难以为继，必须在经济结构、经济运行机制等方面进行更为深刻的改革。以往，我们通过以市场换技术、以资金买技术、以挖人才造技术等方式取得了一些技术进步，但今后这些途径恐怕都难以行得通了。今后中国经济发展的核心动力唯有自主创新，既有技术领域的创新，更有体制和制度上的创新。&lt;/p&gt;    &lt;p&gt;其次，再来谈谈更深层次的教训，此次中美贸易战爆发值得我们深思的问题主要有三个。&lt;/p&gt;    &lt;p&gt;第一，中国忽视对美国整体性、综合性、系统性的深入研究。自2016年美国大选开始一直到今年三月份贸易争端，再到今天，我们对美国的判断屡屡失误。更为重要的是，面对着这样一场大国间的博弈，除了一些贸易专业、经济领域的专家纷纷出来发声以外，那些研究美国政治、社会、文化的专家少有声音。这是极不正常的。说明作为世界上第二大经济体，我们对自己必须直面的霸权国家的系统、深入研究是非常不够的，因而很少可以对美国做出可持续性的、理性的研判。这是非常危险的，不仅容易出现误判，甚至出现错判。其后果主要有两个：一是情感胜于理性，整体性的非理性思维经常占上风，本质上讲这是中国人典型的农耕民族根性。农民与商人的最大区别是什么？农民经常是情感强于理性，而商人则经常是理性胜于情感。中国从1992年邓小平“南巡讲话”和1993年社会主义市场经济是正式确立走到今天，不过二十几年的时间。这意味着我们中华民族从农耕民族走向商业民族的历程仅有二十几年，因而传统根性自然是很强烈的，使得我们很少能够理性地认识世界，更习惯基于情感来判断世界。当年，骆家辉被美国派驻中国大使，很多人欢欣鼓舞，甚至认为美国终于派了个“中国人”，中美关系因此将走得更好。骆家辉是华裔美国人。正因为如此，他更需要要证明自己更美国，所以对中国的态度、立场也更加强硬。在现阶段和今后的中美关系中，我们必须努力克服这种民族根性，更加理性地认知美国，处理好同美国的关系。二是相应地，我们出现了当年戴季陶先生所说的“智识上的义和团”的倾向。在目前的中美贸易战中，有些学者和专家提出我们“要不惜一切代价”！这种提法令人匪夷所思。在当今的经济全球化时代，在一个经济发展、改革不断深化的时代，何谓“要不惜一切代价”？难道要回到改革开放之前的时代？“智识上的义和团”的另一个表现，是我们很少认真地研究特朗普本人。特朗普自传的中文版早在2016年4月就在上海出版发行了。那本小册子很薄，中文标题叫《永不放弃》。我看了三遍，感受是特朗普这个人非同一般。迄今为止，我们对这位美国总统的认知主要有两个特点：一是我们经常小看他，当然全世界都小看了他，二是认为他“善变”，但事实上是因为我们自己看不懂，没有认真研究他。他是一个搞建筑出身的人，&lt;/p&gt;    &lt;p&gt;这类人的思维方式是，首先要基础夯实，其次是思维、设计缜密，逻辑清晰，否则大楼一定要盖歪的，卖不出去的。作为一个商人，他的特点是：当对手信心十足的时候，他特别善于抓住对方的漏洞并戳破对方的底线，为对手带来巨大威慑，进而达到目的；而当对手全力进攻的时候，他又突然能够化干戈为玉帛，实现自己利益最大化。在自己的书中，他曾提及自己咸鱼翻身的辉煌经历，其中也多次谈及他与不同对手之间的博弈经历。我建议在座各位同学看一看这本书。大致就会知晓，所谓的“特朗普善变”很大程度上是因为我们没有把他研究明白。&lt;/p&gt;    &lt;p&gt;我现在经常思考一个问题，这场冲突会给中国带来什么？理论上的挑战、实践上的挑战无疑是非常巨大的，甚至迄今为止致使我们获得成功的好多理论都需要做认真的反思。同时，我们的好多对策也需要认真反省。过去40年中国经济发展的辉煌成就，根本上讲是邓小平领导的改革开放实现的。开放的本质是什么？是我们对美国主导的全球市场经济体系开放，或者说是我们主动地加入到美国主导的全球政治、经济体系中去，并因此成为该体系的最大获益者。但是发展到今天，美国人认为这个体系让中国人占尽了便宜，自己却吃了很大的亏，不再愿意同我们玩下去了。因此，当今时代不存在什么“逆全球化”，全球化是不可逆的，所有问题的根源在于全球化进程出现了大分裂。全球化分裂的本质是什么？是世界主要大国之间关于全球化的共识破裂或没有了，这是当今世界最危险的一件事情，意味着今后美国不再愿意同我们分享他所主导的全球规则和制度安排，这必然对我们今后所有的经济理论及其研究带来巨大挑战。但是我认为，更为重要的挑战恐怕是思想上的，即在这场争端很可能演变成为旷日持久的大国冲突的过程中，我们是继续冷静地认识我们与美国的巨大差距，坚持虚心地向美国学习，还是由此坚定地走向民粹主义的反美道路甚至以一种“玉碎精神”抵制美国的一切。我们曾干过这种事情，所以我很担心。这些政治、经济、思想等领域的严峻挑战，关乎今后中国改革开放的进程、方向，是个大问题。&lt;/p&gt;    &lt;p&gt;第二，忽视对美国经济结构变化的研究，进而对美国社会结构的变化及其主流意识形态的变化研究很少，进而缺乏对美国国内政治结构变化的深入理解。特朗普为什么拿中国开刀？对华贸易逆差问题只是个借口。事实上，不是特朗普上台造成了美国分裂，而是美国社会分裂导致了特朗普上台。美国社会由于经济结构金融化被严重撕裂了，富人越来越富、穷人越来越多，中产阶级在破产。所以，美国“铁锈地带”主要的三个州过去全是支持民主党，支持希拉里的，但这次它们的反转是促使特朗普获胜的关键因素。特朗普上台后，必定要兑现竞选承诺。但事情并非仅仅如此，他上台后面临的一个重要挑战，就是如何利用自己的政治行为尽快弥合分裂的美国社会。迄今为止，他做得比较成功。因为他非常聪明地捕捉到了一个目标，这就是中国。“中国威胁”是美国近些年来的焦点话题，而且实际上也成为西方发达国家的共识。特朗普巧妙地利用了这样一个契机，“中国问题”或“中国威胁”成为特朗普手中的一张牌。所以，如果深入地研究美国经济结构、社会结构到政治结构的变化，我们可能不会出现很多误判。我认为，马克思在一百多年前的一些关于资本主义发展的具体结论有些时空的局限性，但马克思主义的基本原理是正确的，那就是生产力决定生产关系、经济基础决定上层建筑。美国经济结构的变化决定社会结构变化，也一定决定着美国政治利益、国家核心利益的变化。从这个意义上讲，即便特朗普两年或者六年后下台，美国也不会因为更换总统而在战略上改变对中国的基本立场。这是我的一个基本看法。&lt;/p&gt;    &lt;p&gt;第三，忽视对美国控制世界的手段也就是霸权方式、机制等问题的研究。这导致我们经常以工业化国家的视角去认识后工业化的美国，以“贸易国家”的立场去对待“金融国家”的美国；相应地，在此过程中又出现了以发展中国家制造业的成就来定义自身国际地位的一种幻想。我自己的多年研究得出一个结论：中国崛起的性质是“美元体系内的地位提升”。我认为这是很冷静、理性的一个结论。一些人认为人民币国际化的目标是为了取代美元，我反对这种观点。我的研究结论是，人民币国际化的目标不是取代美元，“美元体系”在短期内是无法被替代的，人民币国际化的目标是减少我们在“美元体系”中的风险和成本。说到这里，必须指出的是，我们的某些媒体是极其不负责任、不专业的，经常用一种狭隘的民族主义情绪来忽悠民众情感。40年来，正是因为我们加入到“美元体系”当中，我们成为该体系的主要获益者，自然成为该体系的最主要的支撑者（如购买大量的美国国债等），也自然会成为该体系风险、成本的主要承担者。这是一个正常的逻辑。正所谓福兮祸所伏，这可能是未来我们的问题所在。也就是说，特朗普的杀手锏正在这里，其实他早已露出了獠牙，如对伊朗、俄罗斯的金融制裁，包括前不久美国部分官员提出的对中国购买美国国债的冻结等，虽然是传闻，但这种信号意味着当两国纷争激化的时候难免不会出现这种状况。无论怎样，货币金融一定是美国最后的杀手锏、制胜的法宝，这是它的绝对优势所在。&lt;/p&gt;    &lt;p&gt;那么，我们的主动权在哪里呢？在国内。改革开放40年来，中国认清了斯密经济学原理指导下的市场经济的重要性，知晓了交易分工的作用，构建了中国特色社会主义市场经济体系；40年后的今天，我们终于开始意识到熊彼特式的创新对于经济、社会发展的重要性。习近平总书记在十九大报告中提出了构建创新性国家的宏伟蓝图，意义格外重大。&lt;/p&gt;    &lt;p&gt;围绕创新问题我们需要做些什么？我想从国家和个人两个层面谈谈自己的看法。在国家层面，我们必须改革、破除一切不利于创新的体制和制度安排。今天，倘若依旧沉迷于炫耀祖先的四大发明，一定是我们这些子孙的耻辱。我们应该更多地思考“李约瑟之谜”，这对我们意义更为重大。经济全球化时代国家间竞争的本质是什么？二十几年前我就提出是制度竞争，即看谁的制度安排更有利于经济增长和发展。因此，改革那些阻碍创新的制度安排，创建更加包容、可以自主经营、自主选择和自主流动的现代市场经济体系是至关重要的。这个问题过于宏大，在此暂且打住。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;第三个问题，就个人而言，围绕创新我们可以做些什么？我想借此机会对在座每一位毕业生同学谈谈对你们的希望，权当对你们的临行嘱托。&lt;/strong&gt;&lt;/p&gt;    &lt;p&gt;&lt;/p&gt;    &lt;p&gt;      &lt;img&gt;&lt;/img&gt;&lt;/p&gt;    &lt;p&gt;这里，我主要谈六个方面。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;第一，养成并保持学习的能力。&lt;/strong&gt;我在每一次开学典礼上都要谈一个话题：上大学是为了什么？我认为两件事情最为重要：一是掌握学习的能力，二是养成合作的习惯。掌握了学习的能力和拥有合作的习惯，才能事业顺利，缺一不成。在我看来，学习的能力不是指掌握知识和技能，而是指认知世界、理解世界的能力。我们已经知道“知识越多越反动”这句话是错误的，我还要说培根的“知识就力量”这句话也是有时代局限的。在今天信息爆炸的时代，信息和技能永远在过时的道路上。人的一生只有不断掌握并增强自身的学习能力才能不落后于时代。这也是真正的大学教育的宗旨。耶鲁大学的前校长理查德.莱文曾经说过一句话：如果一个学生从耶鲁大学毕业之后居然掌握了某种很专业的知识和技能，那是耶鲁教育的失败。学习的能力不仅仅来自阅读，更多的还有走出去看世界、观察世界、思考世界、品味世界，只有这样才能够拥有开阔的视野，体会、了解人类的诸多不同，这会使人更加宽容。宽容是人类最高的智慧之一，它会使人类增进幸福。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;第二，独立思考的能力。&lt;/strong&gt;没有独立思考的个人，不会产生创新性社会。我们都看过电影《阿凡达》，导演卡梅隆70多岁时拍了这部电影，我看后曾说过一句话：这是基于人类的想象达到了人类想象的边界。为什么他可以拍出这部片子？是由于他幼年时代的幻想、对世界的好奇心到了70多岁依然如故，没有被泯灭。好奇心、想象力在今天的中国，在座各位还剩下多少？我真的不敢恭维。大家从幼儿园走到今天，基本上是做着标准答案走过来的。在毕业典礼上，本应对大家说些鼓励的话，但是我还是想严肃地跟大家说，在各位今后的生活当中，如果没有好奇心和想象力的话，将是人生的悲剧。好奇心和想象力塑造着一个人的偏好和喜好，没有自身喜好的人生或者说有自己的喜好却被父母和其他人强行改变的人生是非常恐怖的。这样的人多了，这样的人组成的社会也一定是恐怖的。所以，学习能力加上独立思考，是形成创新性社会的基本条件。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;第三，自主选择的能力。&lt;/strong&gt;经济学是一门研究资源稀缺条件下行为主体如何选择的学问。在计划经济条件下，我们基本上是不需要选择的。我上小学、中学的时候，感到自己没有什么选择，因为组织上已经替我选好了，不是上山下乡，就是到工厂接班。其实那时也没有什么痛苦，想起来很快乐。今天，同学们的选择非常多。早晨起来你会选择是到A食堂还是B食堂或C食堂吃早餐，要选择上李老师的课、赵老师的课还是张老师的课。选择是有成本的，起码有机会成本，但不论怎样，市场经济条件下自主选择的成本再多也是必要的，市场经济就是由无数的选择组成的。今天，在应试教育体制下大家还有多少自主选择能力？近几年经常遇到大学同学、朋友打来电话，说我孩子或者亲属今年要高考了，请你跟我说说哪个专业更好？我问他们孩子自己喜欢什么？经常的回答是“不知道”。在座的各位家长，你们可能更清楚是不是这样。这是很悲哀的一件事情。在我上课提问时，很多同学不敢正视我的眼睛，目光所到之处他们基本上都是放下眼帘，好像他不看我我就看不到他一样。没有问题意识，提不出问题，也自然缺乏自主选择能力，这是个恶性循环。具有学习能力的人，能够独立思考的人，也一定是拥有自主选择能力的人，自然是创新能力很强的人。&lt;/p&gt;    &lt;p&gt;谈及自主选择能力，我想谈一点个人体会。现在大家都已基本上选择好了职业，未来还可能有许多新的选择，今天谈这些体会还不晚，也许对你们有参考。经济学强调发挥比较优势，但在做出人生选择的时候，应该注重自己的比较劣势。就是说，你要知道自己的缺点和不足。什么是理性？理性就是知道自己是无知的，或者说知道自己的不足。当你深入了解这些之后，比如在选择职业的时候，就要尽力回避因自身缺陷或不足难以胜任的领域。这样做，不仅避开了自己的不足，实际上也是选择了你的比较优势，而且会使自己更加快乐、宽容。你不会见到某同学去金融机构做的很好，便产生凭啥我不能去金融机构、大学时我金融学成绩比他好之类的不正常心态。冷静地了解自己的比较劣势会让你有一个健康心态，你会认为那个同学成功是因为他确实很优秀，而在他很优秀的那个方面，我却是不足的。所以，了解自己的不足却不回避，一味地同他人比较，盲目跟风，无异于人生的铤而走险。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;第四，审美能力。&lt;/strong&gt;如果展开一幅世界经济地图，你会发现每个国家都有自己的比较优势，如美国出口的是金融服务，日本出口的是制造业技术，中国人出口的是劳动力，欧洲人出口的是古老的贵族文明积淀下来的审美，几乎所有的奢侈品都来自欧洲。审美是一种历史积淀，前提是一个国家历史、文化的连续性。这个话题其实是很沉重的，在此我只想谈谈自己的体会。对个人而言，审美是一种品质和修养。一个审美能力低下的民族不仅素养、品格不高，道德水准也会有问题。迄今为止，大家的审美能力基本上都是从父母那里熏陶出来的，问题是在座的各位父母都是“文革”后的一代，这在很大程度上是问题所在。我非常高兴地看到，在今天的毕业典礼上，大家都穿着皮鞋，穿着带领子的正装，我跟赵勇书记提出过毕业典礼上同学们的着装要求。为什么？看看我们的校园里，许多男同学穿着一条大短裤，露着带毛的双腿，穿一双拖鞋，身披庄严的毕业礼服满校园逛。你们觉得美吗？今天，走在世界上任何地方，判断一个人是否是中国人的标准，基本上就是服饰与行为。针对个体，主要看服饰，相对于其他亚洲人，中国人的服装搭配比如衣裤、鞋帽、鞋袜等的搭配基本是不合体的，远远一看便知道是中国人，在亚洲人里韩国人喜欢穿着鲜艳，穿的素雅且搭配合理的多半是日本人。如果是团体，看到一个人在说，几乎所有人在听是日本人；一个人在讲，一半人在听，一半人乱乱哄哄的是韩国人；一个人在说，少数人在听，多数人各干各的，大多是中国人。审美是一种尊严意识，是一种自我尊重也是对别人的尊重。在庄重的场合，一个没有仪式感的人、着装随意的人既是对自己的贬低，也是对他人的极大不敬。在更大意义上讲，审美可以让人知晓世界上的美好与丑恶，它告诉每一个人，人类的行为应当是有底线的，知道有些事情是绝对不可以去碰的、不可以去做的，而不是为达目的不择手段。这样，我们社会的道德水准才会有所提升。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;第五，战胜困难的能力。&lt;/strong&gt;人生中困难是常态，幸福是短暂的，海明威说“勇气就是优雅地面对压力”，人的一生中能成为优雅的人太难了，这也是我自己经常苦恼的问题。有时候，我跟同事说话时会忘乎所以，事后会反思自己的不优雅。但是优雅地面对压力真的是很难的一件事情，一个人在压力面前如果能做到优雅的话，这本身就说明你真的能够把困境作为常态。这一点对大家未来的人生、工作非常重要，会增进你的幸福感。&lt;/p&gt;    &lt;p&gt;      &lt;strong&gt;最后一点，要做一个具有使命感的人。&lt;/strong&gt;我不想在这里空谈使命感，不要把它看作离我们很遥远的神圣之物。一个人做好自己每一个人生阶段中应该做好的事情，把自己喜欢做的事情尽可能地做到极致甚至像清教徒那样对待自己喜欢的职业并愿意为此努力一生，你就是一个具有使命感的人。所谓工匠精神，本质上与这种对职业的敬畏和使命感的理解与坚守密不可分。工匠精神与功利主义无缘。&lt;/p&gt;    &lt;p&gt;在此我还想强调的是，今天的中国已经不是国土沦丧、家破人亡的民族危亡状态，而是处在快速崛起的进程当中，过去的“为中华崛起而读书”不应当是现在大家读书、学习的目标。今天的中国面对着前所未有的经济全球化的大环境、面对着如何成为创新性国家的重任，只有我们每一个人、在座的每一位毕业生同学成为真正的人，即成为具有学习能力、独立思考能力、自主选择能力、审美能力、战胜困难能力和有使命感的人，你自己的一生才会幸福，我们这个社会才能不断进步，中华民族才真的有希望。&lt;/p&gt;    &lt;p&gt;最后，我祝愿大家健康、幸福、事业有成！但是我更想说的是，健康和幸福更为重要！&lt;/p&gt;    &lt;p&gt;谢谢各位！      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;&lt;/p&gt;    &lt;p&gt;      &lt;img&gt;&lt;/img&gt;&lt;/p&gt;    &lt;hr&gt;&lt;/hr&gt;    &lt;p&gt;录音整理：杨弋 张宇璇&lt;/p&gt;    &lt;p&gt;&lt;/p&gt;    &lt;p&gt;      &lt;img&gt;&lt;/img&gt;&lt;/p&gt;&lt;/div&gt;
    &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/58505-%E5%9B%BD%E5%AE%B6%E5%91%BD%E8%BF%90-%E4%B8%AA%E4%BA%BA-%E5%91%BD%E8%BF%90</guid>
      <pubDate>Sun, 08 Jul 2018 21:30:52 CST</pubDate>
    </item>
    <item>
      <title>看电影学英语 ‖ 十部经典电影中的十句经典台词</title>
      <link>https://itindex.net/detail/56155-%E7%9C%8B%E7%94%B5%E5%BD%B1-%E8%8B%B1%E8%AF%AD-%E5%8D%81%E9%83%A8</link>
      <description>&lt;div&gt;  &lt;h4&gt;1.《教父》&lt;/h4&gt;  &lt;blockquote&gt;   &lt;div&gt;    &lt;img src="http://upload-images.jianshu.io/upload_images/2826987-85d6dcc726c631a7.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240/format/jpg"&gt;&lt;/img&gt;    &lt;br /&gt;    &lt;div&gt;&lt;/div&gt;&lt;/div&gt;   &lt;p&gt;    &lt;em&gt;“Never hate your enemies. It affects your judgement.”&lt;/em&gt;&lt;/p&gt;   &lt;p&gt;永远不要恨你的敌人，那会影响你的判断力。&lt;/p&gt;&lt;/blockquote&gt;  &lt;h4&gt;2.《肖申克的救赎》&lt;/h4&gt;  &lt;blockquote&gt;   &lt;div&gt;    &lt;img src="http://upload-images.jianshu.io/upload_images/2826987-d0449225696609bb.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240/format/jpg"&gt;&lt;/img&gt;    &lt;br /&gt;    &lt;div&gt;&lt;/div&gt;&lt;/div&gt;   &lt;p&gt;    &lt;em&gt;&amp;quot;You know some birds are not meant to be caged, their feathers are just too bright.&amp;quot;&lt;/em&gt;&lt;/p&gt;   &lt;p&gt;你知道，有些鸟儿是注定不会被关在牢笼里的，它们的每一片羽毛都闪耀着自由的光辉。&lt;/p&gt;&lt;/blockquote&gt;  &lt;h4&gt;3.《阿甘正传》&lt;/h4&gt;  &lt;blockquote&gt;   &lt;div&gt;    &lt;img src="http://upload-images.jianshu.io/upload_images/2826987-47daa605e65cbc94.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240/format/jpg"&gt;&lt;/img&gt;    &lt;br /&gt;    &lt;div&gt;&lt;/div&gt;&lt;/div&gt;   &lt;p&gt;    &lt;em&gt;“Life was a box of chocolates, you never know what you&amp;apos;re gonna get.”&lt;/em&gt;&lt;/p&gt;   &lt;p&gt;生活就像一盒巧克力，你永远不知道下一块会是什么味道。&lt;/p&gt;&lt;/blockquote&gt;  &lt;h4&gt;4.《这个杀手不太冷》&lt;/h4&gt;  &lt;blockquote&gt;   &lt;div&gt;    &lt;img src="http://upload-images.jianshu.io/upload_images/2826987-e08f41c72ce34cd8.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240/format/jpg"&gt;&lt;/img&gt;    &lt;br /&gt;    &lt;div&gt;&lt;/div&gt;&lt;/div&gt;   &lt;p&gt;    &lt;em&gt;&amp;quot;It&amp;apos;s always the same thing. It&amp;apos;s when you start to become really afraid of death that you learn to appreciate life.&amp;quot;&lt;/em&gt;&lt;/p&gt;   &lt;p&gt;事情总是这样的，只有当你真正感受到对死亡的恐惧，你才会学到要珍惜生命。&lt;/p&gt;&lt;/blockquote&gt;  &lt;h4&gt;5.《廊桥遗梦》&lt;/h4&gt;  &lt;blockquote&gt;   &lt;div&gt;    &lt;img src="file:/storage/emulated/0/Tencent/QQfile_recv/3(1).jpg"&gt;&lt;/img&gt;    &lt;br /&gt;    &lt;div&gt;&lt;/div&gt;&lt;/div&gt;   &lt;p&gt;    &lt;em&gt;&amp;quot;This kind of certainty comes once in a lifetime.&amp;quot;&lt;/em&gt;&lt;/p&gt;   &lt;p&gt;这样确切的爱，一生只有一次。&lt;/p&gt;&lt;/blockquote&gt;  &lt;h4&gt;6.《少年派的奇幻漂流》&lt;/h4&gt;  &lt;blockquote&gt;   &lt;div&gt;    &lt;img src="http://upload-images.jianshu.io/upload_images/2826987-c18ef296ca8b7db3.PNG?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240/format/jpg"&gt;&lt;/img&gt;    &lt;br /&gt;    &lt;div&gt;&lt;/div&gt;&lt;/div&gt;   &lt;p&gt;    &lt;em&gt;&amp;quot;Have taken place, why must be meaningful?&amp;quot;&lt;/em&gt;&lt;/p&gt;   &lt;p&gt;发生了就发生了，为什么一定要有意义?&lt;/p&gt;&lt;/blockquote&gt;  &lt;h4&gt;7.《V字仇杀队》&lt;/h4&gt;  &lt;blockquote&gt;   &lt;div&gt;    &lt;img src="http://upload-images.jianshu.io/upload_images/2826987-f9aaf7b626841a94.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240/format/jpg"&gt;&lt;/img&gt;    &lt;br /&gt;    &lt;div&gt;&lt;/div&gt;&lt;/div&gt;   &lt;p&gt;    &lt;em&gt;&amp;quot;There is no certainty, only opportunity.&amp;quot;&lt;/em&gt;&lt;/p&gt;   &lt;p&gt;没有一定会怎样，只有可能会怎样。&lt;/p&gt;&lt;/blockquote&gt;  &lt;h4&gt;8.《勇敢的心》&lt;/h4&gt;  &lt;blockquote&gt;   &lt;div&gt;    &lt;img src="http://upload-images.jianshu.io/upload_images/2826987-28bd30ec17dfc02d.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240/format/jpg"&gt;&lt;/img&gt;    &lt;br /&gt;    &lt;div&gt;&lt;/div&gt;&lt;/div&gt;   &lt;p&gt;    &lt;em&gt;&amp;quot;Every man dies, not every man really lives.&amp;quot;&lt;/em&gt;&lt;/p&gt;   &lt;p&gt;每个人都会死，但并非每个人都曾真正活过。&lt;/p&gt;&lt;/blockquote&gt;  &lt;h4&gt;9.《罪恶之城》&lt;/h4&gt;  &lt;blockquote&gt;   &lt;div&gt;    &lt;img src="http://upload-images.jianshu.io/upload_images/2826987-e2733628cae38696.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240/format/jpg"&gt;&lt;/img&gt;    &lt;br /&gt;    &lt;div&gt;&lt;/div&gt;&lt;/div&gt;   &lt;p&gt;    &lt;em&gt;&amp;quot;Sometimes, the truth doesn&amp;apos;t matter like it ought. But you&amp;apos;ll always remember things right.&amp;quot;&lt;/em&gt;&lt;/p&gt;   &lt;p&gt;有时候事实并不重要，只要你永远知道真相就好。&lt;/p&gt;&lt;/blockquote&gt;  &lt;h4&gt;10.《灵异第六感》&lt;/h4&gt;  &lt;blockquote&gt;   &lt;div&gt;    &lt;img src="http://upload-images.jianshu.io/upload_images/2826987-61aaf052ed608e1a.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240/format/jpg"&gt;&lt;/img&gt;    &lt;br /&gt;    &lt;div&gt;&lt;/div&gt;&lt;/div&gt;   &lt;p&gt;&amp;quot;How can you help me if you don&amp;apos;t believe me！&amp;quot;&lt;/p&gt;   &lt;p&gt;如果你不相信我，怎么帮助我！&lt;/p&gt;&lt;/blockquote&gt;  &lt;p&gt;你最喜欢哪一句?欢迎在评论区留言哦~&lt;/p&gt;&lt;/div&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>jianshu</category>
      <guid isPermaLink="true">https://itindex.net/detail/56155-%E7%9C%8B%E7%94%B5%E5%BD%B1-%E8%8B%B1%E8%AF%AD-%E5%8D%81%E9%83%A8</guid>
      <pubDate>Tue, 08 Nov 2016 08:00:00 CST</pubDate>
    </item>
    <item>
      <title>海量数据处理：经典实例分析</title>
      <link>https://itindex.net/detail/55708-%E6%95%B0%E6%8D%AE-%E7%BB%8F%E5%85%B8-%E5%AE%9E%E4%BE%8B</link>
      <description>&lt;p&gt;有关海量数据处理的问题，主要有以下3类：top K问题、重复问题、排序问题&lt;/p&gt;

 &lt;p&gt;  &lt;div&gt;   &lt;div&gt;
    &lt;ul&gt;
     &lt;li&gt;      &lt;a href="http://blog.csdn.net#top-k-&amp;#38382;&amp;#39064;"&gt;top K 问题 &lt;/a&gt;      &lt;ul&gt;
       &lt;li&gt;        &lt;a href="http://blog.csdn.net#&amp;#20363;&amp;#23376;&amp;#26377;1&amp;#20159;&amp;#20010;&amp;#28014;&amp;#28857;&amp;#25968;&amp;#25214;&amp;#20986;&amp;#20854;&amp;#20013;&amp;#26368;&amp;#22823;&amp;#30340;10000&amp;#20010;"&gt;例子有1亿个浮点数找出其中最大的10000个&lt;/a&gt;&lt;/li&gt;
       &lt;li&gt;        &lt;a href="http://blog.csdn.net#&amp;#35299;&amp;#20915;&amp;#26041;&amp;#26696;"&gt;解决方案&lt;/a&gt;        &lt;ul&gt;
         &lt;li&gt;          &lt;a href="http://blog.csdn.net#&amp;#23558;&amp;#25968;&amp;#25454;&amp;#20840;&amp;#37096;&amp;#25490;&amp;#24207;"&gt;将数据全部排序&lt;/a&gt;&lt;/li&gt;
         &lt;li&gt;          &lt;a href="http://blog.csdn.net#&amp;#23616;&amp;#37096;&amp;#28120;&amp;#27760;&amp;#27861;"&gt;局部淘汰法&lt;/a&gt;&lt;/li&gt;
         &lt;li&gt;          &lt;a href="http://blog.csdn.net#&amp;#20998;&amp;#27835;&amp;#27861;"&gt;分治法&lt;/a&gt;&lt;/li&gt;
         &lt;li&gt;          &lt;a href="http://blog.csdn.net#hash&amp;#27861;"&gt;Hash法&lt;/a&gt;&lt;/li&gt;
         &lt;li&gt;          &lt;a href="http://blog.csdn.net#&amp;#26368;&amp;#23567;&amp;#22534;"&gt;最小堆&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
       &lt;li&gt;        &lt;a href="http://blog.csdn.net#&amp;#19981;&amp;#21516;&amp;#24212;&amp;#29992;&amp;#22330;&amp;#26223;&amp;#30340;&amp;#35299;&amp;#20915;&amp;#26041;&amp;#26696;"&gt;不同应用场景的解决方案&lt;/a&gt;        &lt;ul&gt;
         &lt;li&gt;          &lt;a href="http://blog.csdn.net#&amp;#21333;&amp;#26426;&amp;#21333;&amp;#26680;&amp;#36275;&amp;#22815;&amp;#22823;&amp;#20869;&amp;#23384;"&gt;单机单核足够大内存&lt;/a&gt;&lt;/li&gt;
         &lt;li&gt;          &lt;a href="http://blog.csdn.net#&amp;#21333;&amp;#26426;&amp;#22810;&amp;#26680;&amp;#36275;&amp;#22815;&amp;#22823;&amp;#20869;&amp;#23384;"&gt;单机多核足够大内存&lt;/a&gt;&lt;/li&gt;
         &lt;li&gt;          &lt;a href="http://blog.csdn.net#&amp;#21333;&amp;#26426;&amp;#21333;&amp;#26680;&amp;#21463;&amp;#38480;&amp;#20869;&amp;#23384;"&gt;单机单核受限内存&lt;/a&gt;&lt;/li&gt;
         &lt;li&gt;          &lt;a href="http://blog.csdn.net#&amp;#22810;&amp;#26426;&amp;#21463;&amp;#38480;&amp;#20869;&amp;#23384;"&gt;多机受限内存&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
       &lt;li&gt;        &lt;a href="http://blog.csdn.net#&amp;#23567;&amp;#32467;"&gt;小结&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
     &lt;li&gt;      &lt;a href="http://blog.csdn.net#&amp;#37325;&amp;#22797;&amp;#38382;&amp;#39064;"&gt;重复问题 &lt;/a&gt;&lt;/li&gt;
     &lt;li&gt;      &lt;a href="http://blog.csdn.net#&amp;#25490;&amp;#24207;&amp;#38382;&amp;#39064;"&gt;排序问题&lt;/a&gt;      &lt;ul&gt;
       &lt;li&gt;        &lt;a href="http://blog.csdn.net#&amp;#25968;&amp;#25454;&amp;#24211;&amp;#25490;&amp;#24207;&amp;#27861;"&gt;数据库排序法&lt;/a&gt;&lt;/li&gt;
       &lt;li&gt;        &lt;a href="http://blog.csdn.net#&amp;#20998;&amp;#27835;&amp;#27861;-1"&gt;分治法&lt;/a&gt;&lt;/li&gt;
       &lt;li&gt;        &lt;a href="http://blog.csdn.net#&amp;#20301;&amp;#22270;&amp;#27861;"&gt;位图法&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/p&gt;

 &lt;h1&gt;top K 问题 &lt;/h1&gt;

 &lt;p&gt;在大规模数据处理中，经常会遇到的一类问题：在海量数据中找出出现频率最高的前K个数，或者从海量数据中找出最大的前K个数，这类问题通常被称为top K问题。例如，在搜索引擎中，统计搜索最热门的10个查询词；在歌曲库中统计下载率最高的前10首歌等。&lt;/p&gt;

 &lt;p&gt;针对top k 类问题，通常比较好的方案是分治+Trie树+小顶堆，即现将数据集按照hash方法分解成多个小数据集，然后使用Trie树或者Hash统计每个小数据集中的query词频，之后用小顶堆求出每个数据集中出现频率最高的前K个数，最后在所有top K中求出最终的top K。&lt;/p&gt;

 &lt;h2&gt;例子：有1亿个浮点数，找出其中最大的10000个？&lt;/h2&gt;

 &lt;h2&gt;解决方案&lt;/h2&gt;

 &lt;h3&gt;将数据全部排序&lt;/h3&gt;

 &lt;p&gt;最容易想到的方法是将数据全部排序，然后在排序后的集合中进行查找，最快的排序算法的时间复杂度一般为O(nlogn)，如快速排序。而在32位机器上，每个float类型占4个字节，1亿个浮点数就要占用400MB的存储空间，对于一些可用内存小于400MB的计算机而言，很显然是不能一次将全部数据读入内存进行排序的。其实即使内存能够满足要求，该方法也并不高效，因为题目要求是寻找出最大的10000个数即可，而排序却是将所有的元素都排序了。&lt;/p&gt;

 &lt;h3&gt;局部淘汰法&lt;/h3&gt;

 &lt;p&gt;该方法与排序方法类似，用一个容器保存前10000个数，然后将剩余的所有数字一一与容器内的最小数字相比，如果所有后续的元素都比容器内的1000个数还小，那么容器内的这10000个数就是最大的10000个数。如果某一后续元素比容器内的最小数字大，则删掉容器内最小元素，并将该元素插入容器，最后遍历完这1亿个数，得到的结果容器中保存的数即为最终结果了。此时的时间复杂度为O(n+m^2)，其中m为容器的大小，即10000.&lt;/p&gt;

 &lt;h3&gt;分治法&lt;/h3&gt;

 &lt;p&gt;将1亿个数据分成100份，每份100万个数据，找出每份数据中最大的10000个，最后在剩下的100*10000个数据里面找出最大的10000个。如果100万数据选择足够理想，那么可以过滤掉1亿数据里面99%的数据。100万个数据里面查找最大的10000个数据的方法如下：   &lt;br /&gt;
用快速排序的方法，将数据分为2堆，如果大的那堆个数N大于10000个，继续对大堆快速排序一次分成2堆，如果大堆个数N小于10000，就在校的那堆里面快速排序一次，找第10000-n大的数字；递归以上过程，就可以找到第1w大的数。参考上面的找出的第1w大数字，就可以类似的方法找出前10000大数字了。此种方法每次需要的内存空间为10^6*4=4MB，一共需要101此这样的比较&lt;/p&gt;

 &lt;h3&gt;Hash法&lt;/h3&gt;

 &lt;p&gt;如果这1亿个数里面有很多重复的数，先通过Hash法，把着1亿个数字去重复，这样如果重复率很高的话，会减少很大的内存用量，从而缩小运算空间，然后通过分治法或最小堆法查找最大的10000个数。&lt;/p&gt;

 &lt;h3&gt;最小堆&lt;/h3&gt;

 &lt;p&gt;首先读入前10000个数来创建大小为10000的小顶堆，建堆的时间复杂度为O(mlogm）（m为数组的大小即为10000），然后遍历后续的数字，并与堆顶（最小）数字进行比较。如果比最小的数小，则继续读取后续数字；如果比堆顶数字大，则替换对顶元素并重新调整堆为小顶堆。整个过程直至1亿个数全都遍历完为止。然后按照中序遍历的方式输出当前堆中的所有10000个数字。该算法的时间复杂度为O(nmlogm），空间复杂度是10000（常数）。&lt;/p&gt;

 &lt;p&gt;实际上，最优的解决方案应该是最腹黑实际设计需求的方案，在实际应用中，可能有足够大的内存，那么直接将数据扔到内存中一次性处理即可，也可能机器有多个核，这样可以采用多线程处理整个数据集。&lt;/p&gt;

 &lt;h2&gt;不同应用场景的解决方案&lt;/h2&gt;

 &lt;h3&gt;单机+单核+足够大内存&lt;/h3&gt;

 &lt;p&gt;如果需要查找10亿个查询词（每个占8B）中出现频率最高的10个，考虑到每个查询词占8B，则10亿个查询词所需的内存大约是10^9*8B = 8GB 内存。如果有这么大的内存，直接在内存中对查询词进行排序，顺序遍历找出10个出现频率最大的即可。这种方法简单快速，更加实用。当然，也可以先用HashMap求出每个词出现的频率，然后求出频率最大的10个词。&lt;/p&gt;

 &lt;h3&gt;单机+多核+足够大内存&lt;/h3&gt;

 &lt;p&gt;这时可以直接在内存中使用Hash方法将数据划分成n个partition，每个partition交给一个线程处理，线程的处理逻辑是同（1）类似，最后一个线程将结果归并。   &lt;br /&gt;
该方法存在一个瓶颈会明显影响效率，即数据倾斜。每个线程的处理速度可能不同，快的线程需要等待慢的线程，最终的处理速度取决于慢的线程。而针对此问题，解决方法是，将数据划分成c*n个partition（c&amp;gt;1），每个线程处理完当前partition后主动取下一个partition继续处理，直到所有数据处理完毕，最后由一个线程进行归并&lt;/p&gt;

 &lt;h3&gt;单机+单核+受限内存&lt;/h3&gt;

 &lt;p&gt;这种情况下，需要将原数据文件切割成一个一个小文件，如采用hash(x)%M，将源文件中的数据切割成M小文件，如果小文件仍大于内存大小，继续采用Hash的方法对数据文件进行切割，直到每个小文件小于内存大小，这样每个文件可放到内存中处理。采用（1）的方法依次处理每个小文件。&lt;/p&gt;

 &lt;h3&gt;多机+受限内存&lt;/h3&gt;

 &lt;p&gt;这种情况下，为了合理利用多台机器的资源，可将数据分发到多台机器上，每台机器采用（3）节中的策略解决本地的数据。可采用hash+socket方法进行数据分发。&lt;/p&gt;

 &lt;h2&gt;小结&lt;/h2&gt;

 &lt;p&gt;从实际应用考虑，上述的不同场景的解决方案并不可行，因为在大规模数据处理环境下，作业效率并不是首要考虑的问题，算法的扩展性和容错性才是首要考虑的。算法应该具有良好的扩展性，以便数据量进一步加大（随着业务的发展，数据量加大是必然的）时，在不修改算法框架的前提下，可达到近似的线性比；算法应该具有容错性，即当前某个文件处理失败后，能自动将其交给另外一个线程继续处理，而不是从头开始处理。&lt;/p&gt;

 &lt;p&gt;TOP K问题很适合采用MapReduce框架解决，用户只需编写一个Map函数和两个Reduce函数，然后提交到Hadoop（采用Mapchain和Reducechain）上即可解决该问题。具体而言，就是首先根据数据值或者把数据hash（MD5）后的值按照范围划分到不同的机器上，最好可以让数据划分后依次读入内存，这样不同的机器赋值处理不同的数值范围，实际上就是Map。得到结果后，各个机器只需拿出各自出现次数最多的前N个数据，然后汇总，选出所有的数据中出现次数最多的前N个数据，这实际上就是Reduce的过程。对于Map函数，采用Hash算法，将Hash值相同的数据交给同一个Reduce task；对于第一个Reduce函数，采用HashMap统计出每个词出现的频率，对于第二个Reduce函数，统计所有Reduce task，输出数据中的top K 即可。&lt;/p&gt;

 &lt;p&gt;直接将数据均分到不同的机器上进行处理时无法得到正确的结果的。因为一个数据可能被均分到不同的机器上，而另一个则可能完全聚集到一个机器上，同时还可能存在具有相同数目的数据。&lt;/p&gt;

 &lt;p&gt;Top K问题还有很多应用场景，尤其是在程序媛面试笔试中有很多实例，它们都可以采用上述方法解决。以下是一些历年来经常被各大互联网公司提及的该类问题。   &lt;br /&gt;
（1）有1亿个记录，这些查询串的重复度比较高，如果除去重复后，不超过3百万个。一个查询串的重复度过高，说明查询它的用户越多，也就是越热门。请统计最热门的10个查询串，要求使用的内存不能超过1GB   &lt;br /&gt;
（2）有10个文件，每个文件1GB，每个文件的每一行存放的都是用户的query，每个文件的query都可能重复。按照query的频度排序。   &lt;br /&gt;
（3）有一个1GB大小的文件，里面的每一行是一个词，词的大小不超过16个字节，内存限制大小是1MB。返回频数最高的100个词   &lt;br /&gt;
（4）提取某日访问网站次数最多的那个IP   &lt;br /&gt;
（5）10亿个整数找出重复次数最多的100个整数   &lt;br /&gt;
（6）搜索的输入信息是一个字符串，统计300万条输入信息中最热门的前10条，每次输入的一个字符串为不超过255B，内存使用只有1GB   &lt;br /&gt;
（7）有1000万个身份证号以及它们对应的数据，身份证号可能重复，找出出现次数最多的身份证号。&lt;/p&gt;

 &lt;h1&gt;重复问题 &lt;/h1&gt;

 &lt;p&gt;海量数据中查找出重复出现的元素或者去除重复出现的元素   &lt;br /&gt;
针对此类问题，一般可以通过位图法实现。&lt;/p&gt;

 &lt;p&gt;例如，已知某个文件内包含一些电话号码，每个号码为8位数字，统计不同号码的个数。&lt;/p&gt;

 &lt;p&gt;本题最好的解决方法是通过使用位图法来实现。8位整数可以表示的最大十进制数值为99999999.如果每个数字对应于位图中一个bit位，那么存储8位整数大约需要99MB。因为1B=8bit，所以99Mbit折合成内存为 99/8 = 12.375MB的内存表示所有的8位数电话号码的内容。&lt;/p&gt;



 &lt;pre&gt;  &lt;code&gt;#include&amp;lt;iostream&amp;gt;
#include&amp;lt;stdlib.h&amp;gt;
#include&amp;lt;time.h&amp;gt;

using namespace std;

#define BITWORD 32
#define ARRNUM 100
int mmin = 10000000;
int mmax = 99999999;

int N = (mmax-mmin+1);
#define BITS_PER_WORD 32
#define WORD_OFFSET(b) ( (b)/BITS_PER_WORD )
#define BIT_OFFSET(b) ((b)%BITS_PER_WORD )

void SetBit( int *words, int n )
{
    n -= mmin;
    words[WORD_OFFSET(n)] |= ( 1&amp;lt;&amp;lt; BIT_OFFSET(n));
}

void ClearBit( int *words, int n )
{
    words[WORD_OFFSET(n)] &amp;amp;= ~( 1&amp;lt;&amp;lt; BIT_OFFSET(n));
}
int GetBit( int *words, int n )
{
    int bit = words[WORD_OFFSET(n)] &amp;amp; ( 1&amp;lt;&amp;lt; BIT_OFFSET(n));
    return bit != 0 ;
}


int main()
{
    int arr[ ARRNUM ];
    int *words = new int[ 1+N/BITS_PER_WORD ];
    if( words == NULL )
    {
        cout &amp;lt;&amp;lt; &amp;quot; new error \n &amp;quot; &amp;lt;&amp;lt; endl;
        exit(0);
    }

    int count = 0;
    for(int i=0; i&amp;lt;N; i++ )
        ClearBit( words,i);
    srand( (unsigned)time(NULL));
    cout &amp;lt;&amp;lt; &amp;quot; the size of the array : &amp;quot; &amp;lt;&amp;lt; ARRNUM &amp;lt;&amp;lt; endl;

    for(int j=0; j&amp;lt;ARRNUM; j++ )
    {
        arr[j] = rand() % N;
        arr[j] += mmin;
        cout &amp;lt;&amp;lt; arr[j] &amp;lt;&amp;lt; &amp;quot;\t&amp;quot;;
    }

    for(int j=0; j&amp;lt;ARRNUM; j++ )
        SetBit( words, arr[j]);

    cout &amp;lt;&amp;lt; &amp;quot;after sort, a : &amp;quot; &amp;lt;&amp;lt; endl;
    for( int i=0; i&amp;lt;N; i++ )
        if( GetBit( words,i) )
        {
            cout &amp;lt;&amp;lt; i+mmin &amp;lt;&amp;lt; &amp;quot;\t&amp;quot;;
            count++;
        }
    cout &amp;lt;&amp;lt; &amp;quot; sum is : &amp;quot; &amp;lt;&amp;lt; count &amp;lt;&amp;lt; endl;
    delete[] words;
    words = NULL;

    return 0;
}&lt;/code&gt;&lt;/pre&gt;

 &lt;p&gt;上例中，采用时间作为种子，产生了100个随机数，对这100个数进行位图法排序，进而找出其中重复的数据。与此问题相似的面试笔试题还有：   &lt;br /&gt;
（1）10亿个正整数，只有1个数重复出现过，要求在O(n)的时间里找出这个数   &lt;br /&gt;
（2）给定a、b两个文件，各存放50亿个url，每个url各占用64B，要求在O(n)的时间里找出a、b文件共同的url   &lt;br /&gt;
（3）给40亿个不重复的unsigned int的整数，没拍过序的，然后再给一个数，如何快速判断这个数是否在那40亿个数中？&lt;/p&gt;

 &lt;h1&gt;排序问题&lt;/h1&gt;

 &lt;p&gt;海量数据处理中一类常见的问题就是排序问题，即对海量数据中的数据进行排序。例如，一个文件中有9亿条不重复的9位整数，对这个文件中的数字进行排序。&lt;/p&gt;

 &lt;p&gt;针对这个问题，最容易想到的方法是将所有数据导入到内存中，然后使用常规的排序方法，如插入排序、快速排序、归并排序等各种排序方法对数据进行排序，最后将排序好的数据存入文件。但这些方法却不能在此适用，由于数据量巨大，在32位机器中，一个整数占用4个字节，而9亿条数据共占用9*10^8*4B，大约需要占用3.6GB内存，对于32位机器而言，很难将这么多数据一次载入到内存，所以，需要考虑其他方法。&lt;/p&gt;

 &lt;h2&gt;数据库排序法&lt;/h2&gt;

 &lt;p&gt;将文本文件导入到数据库中，让数据库进行索引排序操作后提取数据到文件。该种方法虽然操作简单、方便，但是运算速度较慢，而且对数据库设备要求比较高。&lt;/p&gt;

 &lt;h2&gt;分治法&lt;/h2&gt;

 &lt;p&gt;通过hash将9亿条数据分为20段，每段大约5000万条，大约占用5*10^6*4B=200MB空间，在文件中依次搜索0~5000万，50000001~1亿。。。将排序的结果存入文件。该方法要装满9位整数，一共需要20此，所以一共要进行20次排序，需要对文件进行20次读操作。该方法虽然缩小了每次使用的内存空间大小，但是编码复杂，速度也慢。&lt;/p&gt;

 &lt;h2&gt;位图法&lt;/h2&gt;

 &lt;p&gt;考虑到最大的9位整数为 999999999，由于9亿条数据是不重复的，可以把这些数据组成一个队列或数组，让它有0~999999999（一共10亿个数）个元素数组下标表示数值，结点中用0表示没有这个数，1表示存在这个数，判断0或1只用一个bit存储就够了，而声明一个可以包含9位整数的bit数组，一共需要10亿/8，大约120MB内存，把内存中的数据全部初始化为0，读取文件中的数据，并将数据放入内存。比如读到一个数据为341245909，那就先在内存中找到341245909这个bit，并将bit值置为1，遍历整个bit数组，将bit为1的数组下标存入文件，最终得到排序后的内容。&lt;/p&gt;

 &lt;p&gt;此类排序问题的求解方法一般都是采用上述方法。海量数据处理中与此类似的问题还有以下几种：   &lt;br /&gt;
（1）一年的全国高考考生人数为500万，分数使用标准分，最低100分，最高900分，不存在成绩为小数的情况，把这500万考生的分数排序   &lt;br /&gt;
（2）一个包含n个正整数的文件，每个正整数小于n，n等于1000万，并且文件内的正整数没有重复和关联数据u，输出整数的升序排列。&lt;/p&gt;
 &lt;div&gt;
    作者：oMengLiShuiXiang1234 发表于2016/6/21 16:06:31   &lt;a href="http://blog.csdn.net/omenglishuixiang1234/article/details/51724734"&gt;原文链接&lt;/a&gt;
&lt;/div&gt;
 &lt;div&gt;
    阅读：253 评论：0   &lt;a href="http://blog.csdn.net/omenglishuixiang1234/article/details/51724734#comments" target="_blank"&gt;查看评论&lt;/a&gt;
&lt;/div&gt;

&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/55708-%E6%95%B0%E6%8D%AE-%E7%BB%8F%E5%85%B8-%E5%AE%9E%E4%BE%8B</guid>
      <pubDate>Wed, 22 Jun 2016 00:06:31 CST</pubDate>
    </item>
    <item>
      <title>无损压缩经典算法</title>
      <link>https://itindex.net/detail/56100-%E6%97%A0%E6%8D%9F%E5%8E%8B%E7%BC%A9-%E7%BB%8F%E5%85%B8-%E7%AE%97%E6%B3%95</link>
      <description>&lt;h3&gt;@前言&lt;/h3&gt;

 &lt;p&gt;总结经典的文件压缩算法原理，主要包括：哈夫曼压缩算法及其延伸，LZ77算法及其演变算法，LZ78算法及其演变算法，几何编码算法Arithmetic Coding。&lt;/p&gt;

 &lt;p&gt;  &lt;strong&gt;   &lt;em&gt;内容部分摘录翻译自港大‘多媒体技术’硕士课程&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

 &lt;hr&gt;&lt;/hr&gt;



 &lt;h3&gt;1.进行文件压缩的必要性&lt;/h3&gt;

 &lt;p&gt;像图片、声音、视频这些类型的多媒体数据要比文本数据占用多得多的内存空间，尤其是视频文件，文件传输时占用带宽大，存储又占用大量的硬盘空间。&lt;/p&gt;

 &lt;p&gt;举个例子：  &lt;strong&gt;   &lt;em&gt;一个1080p分辨率格式下90分钟的无压缩视频要多大？&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

 &lt;p&gt;  &lt;strong&gt;   &lt;em&gt;1帧大小 = 1920 x 1080 x 3 = 6220800 bytes&lt;/em&gt;&lt;/strong&gt; (1920x1080是每一帧的像素数，3指的是每个像素红绿蓝三个通道各占一个字节0~256)&lt;/p&gt;

 &lt;p&gt;  &lt;strong&gt;   &lt;em&gt;每秒大小 = 6220800 x 25 = 155.52MB!&lt;/em&gt;&lt;/strong&gt;(假设帧率为每秒25帧，很小了！)&lt;/p&gt;

 &lt;p&gt;  &lt;strong&gt;   &lt;em&gt;每分钟大小 = 155.52MB x 60 = 9.3312GB！&lt;/em&gt;&lt;/strong&gt;（呵呵）&lt;/p&gt;

 &lt;p&gt;  &lt;strong&gt;   &lt;em&gt;90分钟：大约839.81GB&lt;/em&gt;&lt;/strong&gt;（呵呵呵Orz…）&lt;/p&gt;

 &lt;p&gt;存储高清视频的蓝光光碟容量不过只有大约50GB，所以视频如果不压缩根本没法存储，更不用说互相传送了。&lt;/p&gt;



 &lt;h3&gt;2.简单黑白图像的压缩&lt;/h3&gt;

 &lt;p&gt;假设黑白图像的数据如下图，黑色像素用1编码，白色图像用0编码：&lt;/p&gt;

 &lt;p&gt;  &lt;img alt="&amp;#36825;&amp;#37324;&amp;#20889;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="http://img.blog.csdn.net/20161017202125261" title=""&gt;&lt;/img&gt;&lt;/p&gt;

 &lt;p&gt;黑白图像的尺寸为16x8 = 128,因此需要128bits来表示它。&lt;/p&gt;

 &lt;p&gt;如果我们从0开始算起，只保存一些列0和1的个数，那么上面的图像信息可以表示为：&lt;/p&gt;

 &lt;p&gt;  &lt;strong&gt;21 6 9 1 5 2 8 1 3 2 1 1 8 1 2 2 2 1 8 6 21&lt;/strong&gt;&lt;/p&gt;

 &lt;p&gt;其中最大的数字是21，所以可以统一使用5bits(2^5=32)来表示每一个数字,那么现在的存储空间变为5x21=105bits，节省了23bits。&lt;/p&gt;



 &lt;h3&gt;3.字符串行程编码&lt;/h3&gt;

 &lt;p&gt;和上面黑白图像压缩一样的道理，这里压缩一段字符串：  &lt;strong&gt;RRRRRGGGBBBBBRRRRGB&lt;/strong&gt;&lt;/p&gt;

 &lt;p&gt;压缩的结果为：  &lt;strong&gt;5R3G5B4R1G1B&lt;/strong&gt;&lt;/p&gt;

 &lt;p&gt;这种方法叫做  &lt;strong&gt;行程编码run-ength encoding(RLE）&lt;/strong&gt;，应用于像BMP，TIFF格式的图像文件中。&lt;/p&gt;

 &lt;p&gt;但这种压缩编码方式很有局限性，我们无法继续用相同的方法进一步压缩压缩后的数据，比如上面的压缩结果无法继续用这种方法压缩，这种压缩基于数据的重复性。&lt;/p&gt;



 &lt;h3&gt;4.信息的可压缩性-信息熵&lt;/h3&gt;

 &lt;p&gt;数据的压缩实际是用更短的数据来表示反复出现的数据实现压缩，因此数据重复率越高可压缩性就越高，不同数据可压缩的程度不一样，信息熵是用来衡量数据可压缩的程度的一个参数，计算信息最短的长度的期望，关于信息熵：  &lt;a href="http://www.ruanyifeng.com/blog/2014/09/information-entropy.html"&gt;http://www.ruanyifeng.com/blog/2014/09/information-entropy.html&lt;/a&gt;&lt;/p&gt;



 &lt;h3&gt;5.对编码算法的要求&lt;/h3&gt;

 &lt;ol&gt;
  &lt;li&gt;通过编码后的编码必须可以准确解码，编码必须确定地对应一种原码；&lt;/li&gt;
  &lt;li&gt;编码算法得到的编码要容易解码，可以很容易的找到信息的末尾，可以在线解码，可以直接对编码进行解码而不用知道完整的编码信息；&lt;/li&gt;
  &lt;li&gt;编码必须是压缩的，否则失去了编码的意义；&lt;/li&gt;
&lt;/ol&gt;



 &lt;h3&gt;6.哈夫曼编码&lt;/h3&gt;

 &lt;p&gt;哈夫曼编码是David A. Huffman于1952年发明的一种满足上面对编码算法要求的一种编码算法。&lt;/p&gt;

 &lt;p&gt;举一个例子：知道一段字符串全部由a,b,c,d,e五个字母组成，已知了每个字母出现的频率：&lt;/p&gt;

 &lt;p&gt;  &lt;strong&gt;   &lt;em&gt;a(0.25),b(0.25),c(0.2),d(0.15),e(0.15)&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

 &lt;p&gt;【如果不考虑编码算法，使用定长的编码来区别五个字母，不利用频率这些信息，那么五个字母每个字母需要用3bits表示(2^2=4,2^3=8).】&lt;/p&gt;

 &lt;p&gt;哈夫曼算法是利用频率信息构造一棵二叉树，频率高的离根节点近（编码长度短），频率高的离根节点远（编码长度长），手动构造方法是先将字母按照频率从小到大排序，然后不断选择当前还没有父节点的节点中权值最小的两个，构造新的父节点，父节点的值为这两个节点值的和，直到构造成一棵二叉树，上面的例子构造的Y一棵哈弗曼树如下（由于构造过程中叶子节点的值以及新节点的值可能会相同，所以哈弗曼树的结构不唯一）：&lt;/p&gt;

 &lt;p&gt;  &lt;img alt="&amp;#36825;&amp;#37324;&amp;#20889;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="http://img.blog.csdn.net/20161020163414129" title=""&gt;&lt;/img&gt;&lt;/p&gt;

 &lt;p&gt;哈夫曼算法C++实现，使用线性数组存储节点的方式实现，输入上面每个字母的权值可以得到哈弗曼树结构：&lt;/p&gt;



 &lt;pre&gt;  &lt;code&gt;#include &amp;lt;iostream&amp;gt;
using namespace std;

#define n 5         // 字符个数（叶子个数）
#define m 2*(n)-1   // 总节点数：1+2+4+8+...+n

typedef struct{
    double weight;   // 节点权重
    int lchild;      // 左子树
    int rchild;      // 右子树
    int parent;      // 父节点
}HTNODE;

typedef HTNODE HuffmanT[m];  // 一棵线性结构存储的哈弗曼树

/**
 * 哈弗曼树初始化
 */
void InitHT(HuffmanT T)
{
    for(int i=0; i&amp;lt;m; i++)
    {
        T[i].lchild=-1;
        T[i].rchild=-1;
        T[i].parent=-1;
    }
    // 依次输入每个节点的权重
    for(int i=0; i&amp;lt;n; i++)
        std::cin&amp;gt;&amp;gt;T[i].weight;
}

/**
 * 找出还没有父节点的节点中权值最小的两个,p1和p2是要选出的权值最小的两个节点的下标，n1是新父节点的下标
 */
void SelectMin(HuffmanT T, int n1, int &amp;amp;p1, int &amp;amp;p2)
{
    int i, j;
    // 先任意找两个没有父节点的节点
    for(i=0; i&amp;lt;n1; i++)
        if(T[i].parent==-1)
        {
            p1=i;
            break;
        }
    for(j=i+1; j&amp;lt;n1;j++)
        if(T[j].parent==-1)
        {
            p2=j;
            break;
        }
    // 搜索替换成权值最小的节点
    for(i=0; i&amp;lt;n1; i++)
        if((T[p1].weight&amp;gt;T[i].weight) &amp;amp;&amp;amp; (T[i].parent==-1) &amp;amp;&amp;amp; (p2!=i))
            p1=i;
    for(i=0; i&amp;lt;n1; i++)
        if((T[p2].weight&amp;gt;T[i].weight) &amp;amp;&amp;amp; (T[i].parent==-1) &amp;amp;&amp;amp; (p1!=i))
            p2=i;

}
/**
 * 构造哈弗曼树
 */
void CreatHT(HuffmanT T)
{
    int i, p1, p2;
    InitHT(T);
    // 非叶子节点
    for(i=n; i&amp;lt;m; i++)
    {
        // 找出还没有父节点的节点中权值最小的两个
        SelectMin(T, i, p1, p2);
        T[p1].parent=T[p2].parent=i;
        T[i].lchild=p1;
        T[i].rchild=p2;
        T[i].weight=T[p1].weight+T[p2].weight;
    }
}

/**
 * 打印哈弗曼树
 */
void printHT(HuffmanT T)
{
    for(int i=0; i&amp;lt;m; i++)
    {
        std::cout&amp;lt;&amp;lt;T[i].weight&amp;lt;&amp;lt;&amp;apos;\t&amp;apos;&amp;lt;&amp;lt;T[i].parent&amp;lt;&amp;lt;&amp;apos;\t&amp;apos;&amp;lt;&amp;lt;T[i].rchild&amp;lt;&amp;lt;&amp;apos;\t&amp;apos;&amp;lt;&amp;lt;T[i].lchild&amp;lt;&amp;lt;std::endl;
    }
}

/**
 * 前台测试
 */
int main(){
    HuffmanT T;
    CreatHT(T);
    printHT(T);
    return 0;
}&lt;/code&gt;&lt;/pre&gt;

 &lt;p&gt;  &lt;strong&gt;缩减的哈夫曼算法&lt;/strong&gt;&lt;/p&gt;

 &lt;p&gt;哈夫曼编码的缩减实质是对编码字符分组继续进行子分组内编码。先将所有字符按照出现的概率排序，将概率相近的字符作为一个整体参与上一级的编码，这样上一级的编码数量大大减少，分组内继续进行内部哈夫曼编码，同时在上一级中本组的编码作为组内编码的一个固定的前缀。&lt;/p&gt;

 &lt;p&gt;  &lt;img alt="&amp;#36825;&amp;#37324;&amp;#20889;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="http://img.blog.csdn.net/20161022231633622" title=""&gt;&lt;/img&gt;&lt;/p&gt;

 &lt;p&gt;  &lt;strong&gt;Shift Coding&lt;/strong&gt;&lt;/p&gt;

 &lt;p&gt;和缩减的思想类似，将字符按照频率8个一组分块，每到下一块在前面加111进行区分后继续进行3bit的编码。&lt;/p&gt;

 &lt;p&gt;  &lt;img alt="&amp;#36825;&amp;#37324;&amp;#20889;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="http://img.blog.csdn.net/20161022231829312" title=""&gt;&lt;/img&gt;&lt;/p&gt;



 &lt;h3&gt;7.Lempel-Ziv压缩算法&lt;/h3&gt;

 &lt;p&gt;LZ算法及其衍生变形算法是压缩算法的一个系列。LZ77和LZ78算法分别在1977年和1978年被创造出来。虽然他们名字差不多，但是算法方法完全不同。这一系列算法主要适用于字母数量有限的信息，比如文字、源码等。流行的GIF和PNG格式的图像，使用颜色数量有限的颜色空间，其压缩就采用了两种算法的灵活变形应用。&lt;/p&gt;



 &lt;h4&gt;  &lt;strong&gt;   &lt;em&gt;LZ77：&lt;/em&gt;&lt;/strong&gt;&lt;/h4&gt;

 &lt;p&gt;推荐阅读文章：&lt;/p&gt;

 &lt;p&gt;  &lt;a href="http://www.cnblogs.com/junyuhuang/p/4138376.html?utm_source=tuicool&amp;utm_medium=referral"&gt;LZ77压缩算法编码原理详解(结合图片和简单代码)&lt;/a&gt;&lt;/p&gt;

 &lt;p&gt;  &lt;a href="http://www.cnblogs.com/en-heng/p/4992916.html"&gt;LZ77算法原理及实现&lt;/a&gt;&lt;/p&gt;

 &lt;p&gt;LZ77算法的思想是在编码解码过程中，使用之前刚结束编解码的部分数据的位置索引来代替当前要编解码的数据，压缩的实现靠的是之前编解码结束的部分数据和当前数据的重复性。&lt;/p&gt;

 &lt;p&gt;算法中几个重要的对象概念：&lt;/p&gt;

 &lt;p&gt;  &lt;strong&gt;LAB(look-ahead-buffer)&lt;/strong&gt;:将要编码的固定长度的数据缓冲；&lt;/p&gt;

 &lt;p&gt;  &lt;strong&gt;SB(search-buffer)&lt;/strong&gt;:刚过去的固定长度的数据缓冲，搜索缓冲区，也就是临时的数据字典，要从这里面搜索重复数据获得压缩索引；&lt;/p&gt;

 &lt;p&gt;  &lt;strong&gt;Cursor&lt;/strong&gt;:一个指针，指的是SB和LAB缓冲之间的边界处&lt;/p&gt;

 &lt;p&gt;  &lt;strong&gt;Token（p,l,c）&lt;/strong&gt;编码的结果：&lt;/p&gt;

 &lt;ul&gt;
  &lt;li&gt;p: 第一个数字指的是   &lt;strong&gt;SB&lt;/strong&gt;中开始匹配的位置，注意是   &lt;strong&gt;从Cursor往前倒着数，从1开始数&lt;/strong&gt;；&lt;/li&gt;
  &lt;li&gt;l: 第二个数字指的是匹配成功的字符个数;&lt;/li&gt;
  &lt;li&gt;c: 第三个指的是   &lt;strong&gt;LAB&lt;/strong&gt;中匹配结束的下一个字符;&lt;/li&gt;
&lt;/ul&gt;

 &lt;p&gt;  &lt;strong&gt;   &lt;em&gt;示例：&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

 &lt;p&gt;字符串“aacaacabcabaaac”的一个LZ77编码示例，其中缓冲长度分别为：LAB=4,SB=6&lt;/p&gt;

 &lt;p&gt;  &lt;img alt="&amp;#36825;&amp;#37324;&amp;#20889;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="http://images2015.cnblogs.com/blog/399159/201511/399159-20151124220144781-1512450659.png" title=""&gt;&lt;/img&gt;&lt;/p&gt;



 &lt;h4&gt;  &lt;strong&gt;   &lt;em&gt;LZ77的变形&lt;/em&gt;&lt;/strong&gt;&lt;/h4&gt;

 &lt;p&gt;  &lt;strong&gt;   &lt;em&gt;LZR：&lt;/em&gt;&lt;/strong&gt;就是SB搜索缓冲的长度不固定了，算法输出的token位长度也是可变的。&lt;/p&gt;

 &lt;p&gt;  &lt;strong&gt;   &lt;em&gt;LZH：&lt;/em&gt;&lt;/strong&gt;算法的输出结果又进行了哈夫曼编压缩。&lt;/p&gt;

 &lt;p&gt;  &lt;strong&gt;   &lt;em&gt;DEFLATE:&lt;/em&gt;&lt;/strong&gt;当前最流行的基于LZ77的压缩算法，是很多通用的Unix压缩项目‘gzip’的一部分。&lt;/p&gt;



 &lt;h4&gt;  &lt;strong&gt;   &lt;em&gt;LZ78:&lt;/em&gt;&lt;/strong&gt;&lt;/h4&gt;

 &lt;p&gt;算法是将编码过程中之前编码过的所有字符作为了一个索引字典，之前的每一次编码是一个字典元素，之后的编码如果包含之前字典的元素则用该元素的索引代替实现压缩（注意是从之前的字典元素中找那个匹配最长的字典元素），同时记录不匹配的那个字符。可以想到，不断更新的字典中最长的字典元素很可能会越来越长且每次长一个字符。&lt;/p&gt;

 &lt;p&gt;  &lt;strong&gt;   &lt;em&gt;示例：&lt;/em&gt;&lt;/strong&gt;对字符串“abacbabaccbabbaca“进行LZ78编码。   &lt;br /&gt;
  &lt;img alt="&amp;#36825;&amp;#37324;&amp;#20889;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="http://img.blog.csdn.net/20161025221558364" title=""&gt;&lt;/img&gt;&lt;/p&gt;



 &lt;h4&gt;  &lt;strong&gt;   &lt;em&gt;LZ78的变形算法&lt;/em&gt;&lt;/strong&gt;&lt;/h4&gt;

 &lt;p&gt;上面说到LZ78的最长的字典元素只会越来越长不受限制，那么就要使用变长的bit空间来保存字典索引，当前字典的需要保存索引的空间大小为  &lt;code&gt;$log2 (i)$&lt;/code&gt; bits,   &lt;code&gt;$i$&lt;/code&gt;为目前字典中最长字典元素的长度。&lt;/p&gt;

 &lt;p&gt;  &lt;strong&gt;   &lt;em&gt;LZC&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

 &lt;p&gt;算法给字典元素的长度设置一个最大值，如果匹配的结果超出最大值时就选择上一个相对较短的匹配的字典元素，防止字典元素变得太长。如果编码压缩率受限制变得太小，就清空之前的字典，比如重新开始压缩算法。&lt;/p&gt;

 &lt;p&gt;  &lt;strong&gt;   &lt;em&gt;LZW&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

 &lt;p&gt;和LZ78不同的是，算法开始不是空的字典，一开始就把可能的所有单一字符作为最开始的字典，另外不是和LZ78那样记录字典索引和不匹配字符，而是只记录匹配的字典索引（不可能出现不匹配的情况，至少匹配一个字符了）。&lt;/p&gt;

 &lt;p&gt;  &lt;strong&gt;   &lt;em&gt;示例：&lt;/em&gt;&lt;/strong&gt;对字符串“abacbabaccbabbaca”进行LZW编码：   &lt;br /&gt;
  &lt;img alt="&amp;#36825;&amp;#37324;&amp;#20889;&amp;#22270;&amp;#29255;&amp;#25551;&amp;#36848;" src="http://img.blog.csdn.net/20161025223541441" title=""&gt;&lt;/img&gt;&lt;/p&gt;



 &lt;h4&gt;  &lt;strong&gt;   &lt;em&gt;算术编码&lt;/em&gt;&lt;/strong&gt;&lt;/h4&gt;

 &lt;p&gt;算数编码是考虑到解决哈夫曼编码的一个限制：对于信息的编码，要对每一个字符都要使用一个几个二进制的bit数区别表示，收到整体的影响，平均每个字符可能都要用不少的bit数空间来表示。   &lt;br /&gt;
算术编码是将编码的消息表示成实数0和1之间的一个间隔，消息越长，编码表示它的间隔就越小，形成结合越来越紧密的编码，同时需要表示的二进制位数就越多，导致算数编码的最大问题就是计算机的精度问题，精度有限，正常情况下无法进行大量数据的编码，事实上只能编码很短的数据。后来有了其他的先进方法才使算术编码得到应用，具体参考算数编码文章链接。&lt;/p&gt;

 &lt;p&gt;推荐阅读：  &lt;a href="http://blog.csdn.net/adam_tu/article/details/7696455"&gt;算术编码&lt;/a&gt;&lt;/p&gt;
 &lt;div&gt;
    作者：cordova 发表于2016/10/25 22:54:04   &lt;a href="http://blog.csdn.net/cordova/article/details/52928432"&gt;原文链接&lt;/a&gt;
&lt;/div&gt;
 &lt;div&gt;
    阅读：14 评论：0   &lt;a href="http://blog.csdn.net/cordova/article/details/52928432#comments" target="_blank"&gt;查看评论&lt;/a&gt;
&lt;/div&gt;

&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/56100-%E6%97%A0%E6%8D%9F%E5%8E%8B%E7%BC%A9-%E7%BB%8F%E5%85%B8-%E7%AE%97%E6%B3%95</guid>
      <pubDate>Wed, 26 Oct 2016 06:54:04 CST</pubDate>
    </item>
    <item>
      <title>一个经典例子让你彻彻底底理解java回调机制</title>
      <link>https://itindex.net/detail/56080-%E7%BB%8F%E5%85%B8-%E7%90%86%E8%A7%A3-java</link>
      <description>&lt;p&gt;以前不理解什么叫回调，天天听人家说加一个回调方法啥的，心里想我草，什么叫回调方法啊？然后自己就在网上找啊找啊找，找了很多也不是很明白，现在知道了，所谓回调：就是A类中调用B类中的某个方法C，然后B类中反过来调用A类中的方法D，D这个方法就叫回调方法，这样子说你是不是有点晕晕的，其实我刚开始也是这样不理解，看了人家说比较经典的回调方式：&lt;/p&gt;
 &lt;ul&gt;
  &lt;li&gt;Class A实现接口CallBack callback——   &lt;strong&gt;背景1&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;class A中包含一个class B的引用b ——   &lt;strong&gt;背景2&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;class B有一个参数为callback的方法f(CallBack callback) ——   &lt;strong&gt;背景3&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;A的对象a调用B的方法 f(CallBack callback) ——A类调用B类的某个方法 C&lt;/li&gt;
  &lt;li&gt;然后b就可以在f(CallBack callback)方法中调用A的方法 ——B类调用A类的某个方法D&lt;/li&gt;
&lt;/ul&gt;
 &lt;p&gt;大家都喜欢用打电话的例子，好吧，为了跟上时代，我也用这个例子好了，我这个例子采用异步加回调&lt;/p&gt;
 &lt;p&gt;有一天小王遇到一个很难的问题，问题是“1 + 1 = ?”，就打电话问小李，小李一下子也不知道，就跟小王说，等我办完手上的事情，就去想想答案，小王也不会傻傻的拿着电话去等小李的答案吧，于是小王就对小李说，我还要去逛街，你知道了答案就打我电话告诉我，于是挂了电话，自己办自己的事情，过了一个小时，小李打了小王的电话，告诉他答案是2&lt;/p&gt;
 &lt;div&gt;
  &lt;pre&gt;/** 
 * 这是一个回调接口 
 * @author xiaanming 
 * 
 */  
public interface CallBack {  
    /** 
     * 这个是小李知道答案时要调用的函数告诉小王，也就是回调函数 
     * @param result 是答案 
     */  
    public void solve(String result);  
}&lt;/pre&gt;
&lt;/div&gt;
 &lt;div&gt;
  &lt;pre&gt;/** 
 * 这个是小王 
 * @author xiaanming 
 * 实现了一个回调接口CallBack，相当于-----&amp;gt;背景一 
 */  
public class Wang implements CallBack {  
    /** 
     * 小李对象的引用 
     * 相当于-----&amp;gt;背景二 
     */  
    private Li li;   

    /** 
     * 小王的构造方法，持有小李的引用 
     * @param li 
     */  
    public Wang(Li li){  
        this.li = li;  
    }  

    /** 
     * 小王通过这个方法去问小李的问题 
     * @param question  就是小王要问的问题,1 + 1 = ? 
     */  
    public void askQuestion(final String question){  
        //这里用一个线程就是异步，  
        new Thread(new Runnable() {  
            @Override  
            public void run() {  
                /** 
                 * 小王调用小李中的方法，在这里注册回调接口 
                 * 这就相当于A类调用B的方法C 
                 */  
                li.executeMessage(Wang.this, question);   
            }  
        }).start();  

        //小网问完问题挂掉电话就去干其他的事情了，诳街去了  
        play();  
    }  

    public void play(){  
        System.out.println(&amp;quot;我要逛街去了&amp;quot;);  
    }  

    /** 
     * 小李知道答案后调用此方法告诉小王，就是所谓的小王的回调方法 
     */  
    @Override  
    public void solve(String result) {  
        System.out.println(&amp;quot;小李告诉小王的答案是---&amp;gt;&amp;quot; + result);  
    }  

}&lt;/pre&gt;
&lt;/div&gt;
 &lt;div&gt;
  &lt;pre&gt;/** 
 * 这个就是小李啦 
 * @author xiaanming 
 * 
 */  
public class Li {  
    /** 
     * 相当于B类有参数为CallBack callBack的f()----&amp;gt;背景三 
     * @param callBack   
     * @param question  小王问的问题 
     */  
    public void executeMessage(CallBack callBack, String question){  
        System.out.println(&amp;quot;小王问的问题---&amp;gt;&amp;quot; + question);  

        //模拟小李办自己的事情需要很长时间  
        for(int i=0; i&amp;lt;10000;i++){  

        }  

        /** 
         * 小李办完自己的事情之后想到了答案是2 
         */  
        String result = &amp;quot;答案是2&amp;quot;;  

        /** 
         * 于是就打电话告诉小王，调用小王中的方法 
         * 这就相当于B类反过来调用A的方法D 
         */  
        callBack.solve(result);   

    }  

}&lt;/pre&gt;
&lt;/div&gt;
 &lt;div&gt;
  &lt;pre&gt;/** 
 * 测试类 
 * @author xiaanming 
 * 
 */  
public class Test {  
    public static void main(String[]args){  
        /** 
         * new 一个小李 
         */  
        Li li = new Li();  

        /** 
         * new 一个小王 
         */  
        Wang wang = new Wang(li);  

        /** 
         * 小王问小李问题 
         */  
        wang.askQuestion(&amp;quot;1 + 1 = ?&amp;quot;);  
    }  
}&lt;/pre&gt;
&lt;/div&gt;
 &lt;p&gt;通过上面的那个例子你是不是差不多明白了回调机制呢，上面是一个异步回调，我们看看同步回调吧，onClick（）方法&lt;/p&gt;
 &lt;p&gt;现在来分析分析下  &lt;a href="http://lib.csdn.net/base/android" target="_blank" title="Android&amp;#30693;&amp;#35782;&amp;#24211;"&gt;Android&lt;/a&gt; View的点击方法onclick（）;我们知道onclick()是一个回调方法，当用户点击View就执行这个方法，我们用Button来举例好了&lt;/p&gt;
 &lt;div&gt;
  &lt;div&gt;
   &lt;div&gt;
    &lt;pre&gt;//这个是View的一个回调接口  
/** 
 * Interface definition for a callback to be invoked when a view is clicked. 
 */  
public interface OnClickListener {  
    /** 
     * Called when a view has been clicked. 
     * 
     * @param v The view that was clicked. 
     */  
    void onClick(View v);  
}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
 &lt;div&gt;
  &lt;div&gt;
   &lt;div&gt;
    &lt;pre&gt;package com.example.demoactivity;  

import android.app.Activity;  
import android.os.Bundle;  
import android.view.View;  
import android.view.View.OnClickListener;  
import android.widget.Button;  
import android.widget.Toast;  

/** 
 * 这个就相当于Class A 
 * @author xiaanming 
 * 实现了 OnClickListener接口----&amp;gt;背景一 
 */  
public class MainActivity extends Activity implements OnClickListener{  
    /** 
     * Class A 包含Class B的引用-----&amp;gt;背景二 
     */  
    private Button button;  

    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        button = (Button)findViewById(R.id.button1);  

        /** 
         * Class A 调用View的方法,而Button extends View-----&amp;gt;A类调用B类的某个方法 C 
         */  
        button.setOnClickListener(this);  
    }  

    /** 
     * 用户点击Button时调用的回调函数，你可以做你要做的事 
     * 这里我做的是用Toast提示OnClick 
     */  
    @Override  
    public void onClick(View v) {  
        Toast.makeText(getApplication(), &amp;quot;OnClick&amp;quot;, Toast.LENGTH_LONG).show();  
    }  

}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
 &lt;p&gt;下面是View类的setOnClickListener方法，就相当于B类咯，只把关键代码贴出来&lt;/p&gt;
 &lt;div&gt;
  &lt;pre&gt;/** 
 * 这个View就相当于B类 
 * @author xiaanming 
 * 
 */  
public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource {  
    /** 
     * Listener used to dispatch click events. 
     * This field should be made private, so it is hidden from the SDK. 
     * {@hide} 
     */  
    protected OnClickListener mOnClickListener;  

    /** 
     * setOnClickListener()的参数是OnClickListener接口------&amp;gt;背景三 
     * Register a callback to be invoked when this view is clicked. If this view is not 
     * clickable, it becomes clickable. 
     * 
     * @param l The callback that will run 
     * 
     * @see #setClickable(boolean) 
     */  

    public void setOnClickListener(OnClickListener l) {  
        if (!isClickable()) {  
            setClickable(true);  
        }  
        mOnClickListener = l;  
    }  

    /** 
     * Call this view&amp;apos;s OnClickListener, if it is defined. 
     * 
     * @return True there was an assigned OnClickListener that was called, false 
     *         otherwise is returned. 
     */  
    public boolean performClick() {  
        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);  

        if (mOnClickListener != null) {  
            playSoundEffect(SoundEffectConstants.CLICK);  

            //这个不就是相当于B类调用A类的某个方法D，这个D就是所谓的回调方法咯  
            mOnClickListener.onClick(this);  
            return true;  
        }  

        return false;  
    }  
}&lt;/pre&gt;
&lt;/div&gt;
 &lt;p&gt;这个例子就是Android典型的回调机制，看完这个你是不是更进一步的理解了回调机制呢？ 线程run()也是一个回调方法，当执行Thread的start（）方法就会回调这个run()方法，还有处理消息都比较经典等等  &lt;br /&gt;
&lt;/p&gt;
 &lt;h3&gt;相关文章&lt;/h3&gt;
 &lt;ul&gt;
  &lt;li&gt;   &lt;a href="http://www.importnew.com/20877.html"&gt;Java中实现CallBack功能&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://www.importnew.com/1068.html"&gt;如何增强JAVA的I/O性能&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://www.importnew.com/14506.html"&gt;Java并发的四种风味：Thread、Executor、ForkJoin和Actor&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://www.importnew.com/15656.html"&gt;Netty实现原理浅析&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://www.importnew.com/15845.html"&gt;ConcurrentHashmap 解析&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://www.importnew.com/15937.html"&gt;泛型方法的反模式&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://www.importnew.com/16266.html"&gt;Java常用排序算法/程序员必须掌握的8大排序算法&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://www.importnew.com/17570.html"&gt;跟我学Spring3（3.1）:DI的配置使用&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://www.importnew.com/18591.html"&gt;跟我学Spring3（12.3）：零配置之注解实现Bean定义&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://www.importnew.com/19363.html"&gt;Java Web前端到后台常用框架介绍&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>基础技术 CallBack</category>
      <guid isPermaLink="true">https://itindex.net/detail/56080-%E7%BB%8F%E5%85%B8-%E7%90%86%E8%A7%A3-java</guid>
      <pubDate>Thu, 20 Oct 2016 07:59:54 CST</pubDate>
    </item>
    <item>
      <title>map和reduce 个数的设定 （Hive优化）经典</title>
      <link>https://itindex.net/detail/53710-map-reduce-%E8%AE%BE%E5%AE%9A</link>
      <description>&lt;div&gt;
  &lt;p&gt;   &lt;strong&gt;一、    控制hive任务中的map数: &lt;/strong&gt;   &lt;br /&gt;   &lt;br /&gt;1.    通常情况下，作业会通过input的目录产生一个或者多个map任务。    &lt;br /&gt;主要的决定因素有： input的文件总个数，input的文件大小，集群设置的文件块大小(目前为128M, 可在hive中通过set dfs.block.size;命令查看到，该参数不能自定义修改)；   &lt;br /&gt;   &lt;br /&gt;2.    举例：    &lt;br /&gt;a)    假设input目录下有1个文件a,大小为780M,那么hadoop会将该文件a分隔成7个块（6个128m的块和1个12m的块），从而产生7个map数   &lt;br /&gt;b)    假设input目录下有3个文件a,b,c,大小分别为10m，20m，130m，那么hadoop会分隔成4个块（10m,20m,128m,2m）,从而产生4个map数   &lt;br /&gt;即，如果文件大于块大小(128m),那么会拆分，如果小于块大小，则把该文件当成一个块。   &lt;br /&gt;   &lt;br /&gt;3.    是不是map数越多越好？    &lt;br /&gt;答案是否定的。如果一个任务有很多小文件（远远小于块大小128m）,则每个小文件也会被当做一个块，用一个map任务来完成，   &lt;br /&gt;而一个map任务启动和初始化的时间远远大于逻辑处理的时间，就会造成很大的资源浪费。   &lt;br /&gt;而且，同时可执行的map数是受限的。&lt;/p&gt;
  &lt;p&gt; &lt;/p&gt;
  &lt;p&gt;4.    是不是保证每个map处理接近128m的文件块，就高枕无忧了？    &lt;br /&gt;答案也是不一定。比如有一个127m的文件，正常会用一个map去完成，但这个文件只有一个或者两个小字段，却有几千万的记录，   &lt;br /&gt;如果map处理的逻辑比较复杂，用一个map任务去做，肯定也比较耗时。   &lt;br /&gt;   &lt;br /&gt;针对上面的问题3和4，我们需要采取两种方式来解决：即减少map数和增加map数；   &lt;br /&gt;   &lt;br /&gt;   &lt;strong&gt;如何合并小文件，减少map数？ &lt;/strong&gt;   &lt;br /&gt;    假设一个SQL任务：   &lt;br /&gt;         Select count(1) from popt_tbaccountcopy_mes where pt = ‘2012-07-04’;   &lt;br /&gt;         该任务的inputdir  /group/p_sdo_data/p_sdo_data_etl/pt/popt_tbaccountcopy_mes/pt=2012-07-04   &lt;br /&gt;         共有194个文件，其中很多是远远小于128m的小文件，总大小9G，正常执行会用194个map任务。   &lt;br /&gt;         Map总共消耗的计算资源： SLOTS_MILLIS_MAPS= 623,020   &lt;br /&gt;   &lt;br /&gt;         我通过以下方法来在map执行前合并小文件，减少map数：   &lt;br /&gt;         set mapred.max.split.size=100000000;   &lt;br /&gt;                    set mapred.min.split.size.per.node=100000000;   &lt;br /&gt;                    set mapred.min.split.size.per.rack=100000000;   &lt;br /&gt;                    set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;   &lt;br /&gt;                 再执行上面的语句，用了74个map任务，map消耗的计算资源：SLOTS_MILLIS_MAPS= 333,500   &lt;br /&gt;         对于这个简单SQL任务，执行时间上可能差不多，但节省了一半的计算资源。   &lt;br /&gt;         大概解释一下，100000000表示100M, set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;这个参数表示执行前进行小文件合并，   &lt;br /&gt;         前面三个参数确定合并文件块的大小，大于文件块大小128m的，按照128m来分隔，小于128m,大于100m的，按照100m来分隔，把那些小于100m的（包括小文件和分隔大文件剩下的），   &lt;br /&gt;         进行合并,最终生成了74个块。   &lt;br /&gt;            &lt;br /&gt;   &lt;strong&gt;如何适当的增加map数？ &lt;/strong&gt;   &lt;br /&gt;   &lt;br /&gt;         当input的文件都很大，任务逻辑复杂，map执行非常慢的时候，可以考虑增加Map数，来使得每个map处理的数据量减少，从而提高任务的执行效率。   &lt;br /&gt;         假设有这样一个任务：   &lt;br /&gt;         Select data_desc,   &lt;br /&gt;                count(1),   &lt;br /&gt;                count(distinct id),   &lt;br /&gt;                sum(case when …),   &lt;br /&gt;                sum(case when ...),   &lt;br /&gt;                sum(…)   &lt;br /&gt;        from a group by data_desc   &lt;br /&gt;                   如果表a只有一个文件，大小为120M，但包含几千万的记录，如果用1个map去完成这个任务，肯定是比较耗时的，这种情况下，我们要考虑将这一个文件合理的拆分成多个，   &lt;br /&gt;                   这样就可以用多个map任务去完成。   &lt;br /&gt;                   set mapred.reduce.tasks=10;   &lt;br /&gt;                   create table a_1 as    &lt;br /&gt;                   select * from a    &lt;br /&gt;                   distribute by rand(123);    &lt;br /&gt;                      &lt;br /&gt;                   这样会将a表的记录，随机的分散到包含10个文件的a_1表中，再用a_1代替上面sql中的a表，则会用10个map任务去完成。   &lt;br /&gt;                   每个map任务处理大于12M（几百万记录）的数据，效率肯定会好很多。   &lt;br /&gt;       &lt;br /&gt;   看上去，貌似这两种有些矛盾，一个是要合并小文件，一个是要把大文件拆成小文件，这点正是重点需要关注的地方，   &lt;br /&gt;   根据实际情况，控制map数量需要遵循两个原则：使大数据量利用合适的map数；使单个map任务处理合适的数据量；&lt;/p&gt;
  &lt;p&gt; &lt;/p&gt;
  &lt;p&gt;   &lt;strong&gt;二、    控制hive任务的reduce数： &lt;/strong&gt;   &lt;br /&gt;   &lt;br /&gt;1.    Hive自己如何确定reduce数：    &lt;br /&gt;reduce个数的设定极大影响任务执行效率，不指定reduce个数的情况下，Hive会猜测确定一个reduce个数，基于以下两个设定：   &lt;br /&gt;hive.exec.reducers.bytes.per.reducer（每个reduce任务处理的数据量，默认为1000^3=1G）    &lt;br /&gt;hive.exec.reducers.max（每个任务最大的reduce数，默认为999）   &lt;br /&gt;计算reducer数的公式很简单N=min(参数2，总输入数据量/参数1)   &lt;br /&gt;即，如果reduce的输入（map的输出）总大小不超过1G,那么只会有一个reduce任务；   &lt;br /&gt;如：select pt,count(1) from popt_tbaccountcopy_mes where pt = &amp;apos;2012-07-04&amp;apos; group by pt;    &lt;br /&gt;            /group/p_sdo_data/p_sdo_data_etl/pt/popt_tbaccountcopy_mes/pt=2012-07-04 总大小为9G多，因此这句有10个reduce   &lt;br /&gt;   &lt;br /&gt;2.    调整reduce个数方法一：    &lt;br /&gt;调整hive.exec.reducers.bytes.per.reducer参数的值；   &lt;br /&gt;set hive.exec.reducers.bytes.per.reducer=500000000; （500M）   &lt;br /&gt;select pt,count(1) from popt_tbaccountcopy_mes where pt = &amp;apos;2012-07-04&amp;apos; group by pt; 这次有20个reduce   &lt;br /&gt;            &lt;br /&gt;3.    调整reduce个数方法二；    &lt;br /&gt;set mapred.reduce.tasks = 15;   &lt;br /&gt;select pt,count(1) from popt_tbaccountcopy_mes where pt = &amp;apos;2012-07-04&amp;apos; group by pt;这次有15个reduce   &lt;br /&gt;   &lt;br /&gt;4.    reduce个数并不是越多越好；    &lt;br /&gt;同map一样，启动和初始化reduce也会消耗时间和资源；   &lt;br /&gt;另外，有多少个reduce,就会有多少个输出文件，如果生成了很多个小文件，那么如果这些小文件作为下一个任务的输入，则也会出现小文件过多的问题；   &lt;br /&gt;   &lt;br /&gt;5.    什么情况下只有一个reduce；    &lt;br /&gt;很多时候你会发现任务中不管数据量多大，不管你有没有设置调整reduce个数的参数，任务中一直都只有一个reduce任务；   &lt;br /&gt;   &lt;strong&gt;其实只有一个reduce任务的情况，除了数据量小于hive.exec.reducers.bytes.per.reducer参数值的情况外，还有以下原因&lt;/strong&gt;：   &lt;br /&gt;a)    没有group by的汇总，比如把select pt,count(1) from popt_tbaccountcopy_mes where pt = &amp;apos;2012-07-04&amp;apos; group by pt; 写成 select count(1) from popt_tbaccountcopy_mes where pt = &amp;apos;2012-07-04&amp;apos;;   &lt;br /&gt;这点非常常见，希望大家尽量改写。   &lt;br /&gt;b)    用了Order by   &lt;br /&gt;c)    有笛卡尔积   &lt;br /&gt;通常这些情况下，除了找办法来变通和避免，我暂时没有什么好的办法，因为这些操作都是全局的，所以hadoop不得不用一个reduce去完成；   &lt;br /&gt;   &lt;br /&gt;    同样的，在设置reduce个数的时候也需要考虑这两个原则：使大数据量利用合适的reduce数；使单个reduce任务处理合适的数据量；&lt;/p&gt;
&lt;/div&gt;
          
           &lt;br /&gt; &lt;br /&gt;
          
             &lt;a href="http://wangshuxing123-126-com.iteye.com/blog/2220355#comments"&gt;已有   &lt;strong&gt;0&lt;/strong&gt; 人发表留言，猛击-&amp;gt;&amp;gt;  &lt;strong&gt;这里&lt;/strong&gt;&amp;lt;&amp;lt;-参与讨论&lt;/a&gt;
          
           &lt;br /&gt; &lt;br /&gt; &lt;br /&gt;
ITeye推荐
 &lt;br /&gt;
 &lt;ul&gt;  &lt;li&gt;   &lt;a href="http://www.iteye.com/clicks/433" target="_blank"&gt;—软件人才免语言低担保 赴美带薪读研！— &lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;
 &lt;br /&gt; &lt;br /&gt; &lt;br /&gt;
          
        &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/53710-map-reduce-%E8%AE%BE%E5%AE%9A</guid>
      <pubDate>Wed, 17 Jun 2015 14:34:09 CST</pubDate>
    </item>
    <item>
      <title>经典个人职业规划</title>
      <link>https://itindex.net/detail/53073-%E7%BB%8F%E5%85%B8-%E4%B8%AA%E4%BA%BA-%E8%81%8C%E4%B8%9A</link>
      <description>&lt;div&gt;
  &lt;p&gt;JAVA工程师个人职业规划应该要怎么规划比较好?以下是JAVA工程师个人职业规划范文供大家参考。   &lt;br /&gt;   &lt;br /&gt;“选择重于努力，方向重于能力。”很多职场人都缺乏借助职业导师的职业智慧和职场经验为自己拨开职场迷雾，导航职业方向的意识。钟总监建议，有好像王敏这种职业困惑的职场人，最好向具有同行业职场经验的职场导师寻求职业指导，借助导师们的职业智慧和职场经验让自己少走弯路。   &lt;br /&gt;   &lt;br /&gt;JAVA工程师有前途吗？经典个人职业规划   &lt;br /&gt;   &lt;br /&gt;   &lt;strong&gt;1、选择比能力重要&lt;/strong&gt;   &lt;br /&gt;   &lt;br /&gt;通常，作为开发工程师，一般会有以下几种职业走向。   &lt;br /&gt;   &lt;br /&gt;①走技术路线：技术高手、技术专家、软件架构师。   &lt;br /&gt;   &lt;br /&gt;②走管理路线：项目经理、部门经理、技术总监。   &lt;br /&gt;   &lt;br /&gt;甚至，从事销售顾问、培训讲师、自己创业都是一种可能。   &lt;br /&gt;   &lt;br /&gt;其实，这些职业当中的每一种，都有一条非常宽敞的职业发展之路，关键在于作为还是一个开发工程师的你，将会做出什么样的选择，哪怕我们想从事软件产品的市场和销售工作，带着对技术的理解，也必将做出自己独特的一面。   &lt;br /&gt;   &lt;br /&gt;但无论如何，我们都要做出一个选择，给自己定一个目标。目标对人生有着巨大的导向作用。成功，在事业起步的时候仅仅是一种选择，你选择什么样的目标，就会有什么样的人生。不少朋友最大的痛苦就是不知道自己适合做什么，该干什么，该走什么路，不满足于现状又不得不沉沦于现实。   &lt;br /&gt;   &lt;br /&gt;所以，先认清“正确的结果”，根据正确的结果去设计你的过程。当一个人具有明确的职业目标时，就会对有助于实现目标的蛛丝马迹都特别敏感，做事情相应也就会很有目的性，而不是稀里糊涂的。所以，就容易到达自己的目的。如果没有职业目标，就算是天上真有神仙，神仙也不知道该给你什么。   &lt;br /&gt;   &lt;br /&gt;“做正确的事情，永远比正确地做事更重要!”   &lt;br /&gt;   &lt;br /&gt;   &lt;strong&gt;2、做自己喜欢与最擅长的工作&lt;/strong&gt;   &lt;br /&gt;   &lt;br /&gt;既然必须做出选择，如何选择就是关键。总不能写几个纸条，靠抓阄来决定自己以后的命运。从众多成功者的经历来看，成功的一个关键因素就是做自己感兴趣的和最擅长的事情。如果没有兴趣，就没有百分之百的激情与动力，如果不擅长，就不可能把一件事情做到最好。   &lt;br /&gt;   &lt;br /&gt;刘翔是短跑冠军，王励勤是乒乓球冠军，乔丹是飞人，巴菲特是股神……他们之所以成为英雄，正在于他们都是在做自己最擅长的事情，都是在拿自己的长处和别人的短处较量。他们本来是普通的常人，但因为在某一点上超过了所有的人，因而获得了成功。   &lt;br /&gt;   &lt;br /&gt;职业规划的目的，不是要你变成另外一个人，而是要你变成最好的自己。搞清楚自己的优势在什么地方。做自己喜欢和最擅长的工作。不要羡慕别人的长处，不要绞尽脑汁地琢磨怎样才能像别人那样擅长某方面，不要幻想成为别人——做最好的自己!   &lt;br /&gt;   &lt;br /&gt;   &lt;strong&gt;3、成为行业职场专家&lt;/strong&gt;   &lt;br /&gt;   &lt;br /&gt;    通常说到开发工程师的发展前景，一般是指如项目经理、软件架构师之类的，这种规划主要是在IT行业内就业发展的规划，更像一个职位的规划。所以，无论是就职资源还是职业前景都包含一定的局限性。随着IT行业的竞争加剧和其他传统行业的信息化进程，如今的开发工程师职业规划发展目标应该超越本职业概念的“行业专家”，这里所指的行业，并不是指编程的语言，而是比如电信、互联网、银行、电子商务之类的行业，成为一个领域在行业中应用的专家。&lt;/p&gt;
  &lt;p&gt;    现实招聘的需求中也大量地体现了这方面的要求，具有某一行业多年从业经验的开发人员一直是众多企业苦苦追寻的香饽饽。   &lt;br /&gt;   &lt;br /&gt;   &lt;strong&gt;4、坚持到底&lt;/strong&gt;   &lt;br /&gt;   &lt;br /&gt;除了选择，最终要想获得成功，唯一的办法就是“专注”。技术是层出不穷的，而人的精力却是有限的，怎样把有限的精力用到刀口上去，那就得认准了某个领域和某个行业坚持不懈地做下去，不但要成为这个领域的技术专家，还要成为这些行业的业务专家，你能熟知这个领域的点点滴滴，并能在这个领域的行业应用上发展创新，这样的人才，我职 业 规 划 案 例想才是目前最需要的人才。我的一个同学，毕业的时候被公认为是编程水平最高的，但3年来他换了6次工作，他总是对这个感兴趣，对那个感兴趣，做过很多，每换一个工作几乎都是做的全新的东西，总在抱怨工作不如意，其实他换来换去，却始终是在起点上转。而另一个非常坚持的朋友，10年只跳了三次槽，第一个是开发工程师，第二个是部门经理，第三个是技术总监，不为什么，就因为他是专家，10年来他只做一个行业。用10年来做一件事情，不成功都难。   &lt;br /&gt;   &lt;br /&gt;世界上没有完美的公司，重要的是，你要有自己的目标。知道你自己要的是什么。有些人习惯不满意就跳槽，跳槽可能会增加你的收入，但这种个人收入的增长，与一家企业由小到大而给员工带来的成长是无法相提并论的。职业规划就是要搞清楚自己的优势在什么地方，自己最适合做什么。当有了自己坚定的目标和定位，打工就不再是为别人卖命，而是为了自己的目标在奋斗!用这样的标准来衡量自己的成长和进步，那样的人生也会变得轻松而快乐。   &lt;br /&gt;   &lt;br /&gt;职场发展，需要仙人指路;职业成长，需要名师开悟……其实每个人在不同的阶段都需要职业指导。   &lt;br /&gt;   &lt;br /&gt;只要对专业及个人发展有兴趣、乐意接受别人的建议与辅导、勇于接受挑战、拥有时间管理智慧、以及渴求成就感的人，都需要自己的职业导师、职场导师。   &lt;br /&gt;   &lt;br /&gt;“职业导师”在西方已经有相当长的发展历史，“Mentor”这个词有良师、优秀领导者、好顾问等含义。企业建立“职业导师”制度的初衷，是要建立一种在职管理人才开发的良好机制，让新员工或者职位较低的员工，以一对一的方式向管理经验丰富的老员工，或者高位者进行学习。这个概念发展到今天，已经从企业管理的学习，扩展到一些专业技术和技巧的学习，而受训人也有可能比培训人职位更高。&lt;/p&gt;
  &lt;p&gt;   &lt;br /&gt;转自：   &lt;br /&gt;JAVA工程师有前途吗？经典个人职业规划 - 51CTO.COM   &lt;br /&gt;http://developer.51cto.com/art/201503/469311_all.htm&lt;/p&gt;
&lt;/div&gt;
          
           &lt;br /&gt; &lt;br /&gt;
          
             &lt;a href="http://shellfish.iteye.com/blog/2196746#comments"&gt;已有   &lt;strong&gt;0&lt;/strong&gt; 人发表留言，猛击-&amp;gt;&amp;gt;  &lt;strong&gt;这里&lt;/strong&gt;&amp;lt;&amp;lt;-参与讨论&lt;/a&gt;
          
           &lt;br /&gt; &lt;br /&gt; &lt;br /&gt;
ITeye推荐
 &lt;br /&gt;
 &lt;ul&gt;  &lt;li&gt;   &lt;a href="http://www.iteye.com/clicks/433" target="_blank"&gt;—软件人才免语言低担保 赴美带薪读研！— &lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;
 &lt;br /&gt; &lt;br /&gt; &lt;br /&gt;
          
        &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/53073-%E7%BB%8F%E5%85%B8-%E4%B8%AA%E4%BA%BA-%E8%81%8C%E4%B8%9A</guid>
      <pubDate>Sat, 28 Mar 2015 15:13:14 CST</pubDate>
    </item>
    <item>
      <title>Photoshop技能167个经典的Photoshop技巧大全</title>
      <link>https://itindex.net/detail/51225-photoshop-%E6%8A%80%E8%83%BD-%E7%BB%8F%E5%85%B8</link>
      <description>&lt;div&gt;
  &lt;p&gt;经典的Photoshop技巧大全，如果你是初级阶段的水平，熟读此文并掌握，马上进阶为中级水平。绝对不是广告噢。 ­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;1.&lt;/strong&gt; 快速打开文件­&lt;/p&gt;
  &lt;p&gt;　　双击Photoshop的背景空白处(默认为灰色显示区域)即可打开选择文件的浏览窗口。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;2.&lt;/strong&gt; 随意更换画布颜色­&lt;/p&gt;
  &lt;p&gt;　　选择油漆桶工具并按住Shift点击画布边缘，即可设置画布底色为当前选择的前景色。如果要还原到默认的颜色，设置前景色为25％灰度 (R192，G192，B192)再次按住Shift点击画布边缘。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;3.&lt;/strong&gt; 选择工具的快捷键­&lt;/p&gt;
  &lt;p&gt;　　可以通过按快捷键来快速选择工具箱中的某一工具，各个工具的字母快捷键如下：­&lt;/p&gt;
  &lt;p&gt;　　选框-M， 移动-V， 套索-L ， 魔棒-W­&lt;/p&gt;
  &lt;p&gt;　　喷枪-J， 画笔-B， 铅笔-N， 橡皮图章-S­&lt;/p&gt;
  &lt;p&gt;　　历史记录画笔-Y， 橡皮擦-E， 模糊-R ， 减淡-O­&lt;/p&gt;
  &lt;p&gt;　　钢笔-P， 文字-T， 度量-U， 渐变-G­&lt;/p&gt;
  &lt;p&gt;　　油漆桶-K， 吸管-I， 抓手-H， 缩放-Z­&lt;/p&gt;
  &lt;p&gt;　　默认前景和背景色-D， 切换前景和背景色-X­&lt;/p&gt;
  &lt;p&gt;　　编辑模式切换-Q， 显示模式切换-F­&lt;/p&gt;
  &lt;p&gt;　　另外，如果我们按住Alt键后再单击显示的工具图标，或者按住Shift键并重复按字母快捷键则可以循环选择隐藏的工具。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;4.&lt;/strong&gt; 获得精确光标­&lt;/p&gt;
  &lt;p&gt;　　按Caps Lock键可以使画笔和磁性工具的光标显示为精确十字线，再按一次可恢复原状。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;5.&lt;/strong&gt; 显示/隐藏控制板­&lt;/p&gt;
  &lt;p&gt;　　按Tab键可切换显示或隐藏所有的控制板(包括工具箱)，如果按Shift+Tab则工具箱不受影响，只显示或隐藏其他的控制板。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;6.&lt;/strong&gt; 快速恢复默认值­&lt;/p&gt;
  &lt;p&gt;　　有些不擅长Photoshop的朋友为了调整出满意的效果真是几经周折，结果发现还是原来的默认效果最好，这下傻了眼，后悔不该当初呀！怎么恢复到默认值呀？试着轻轻点按选项栏上的工具图标，然后从上下文菜单中选取“复位工具”或者“复位所有工具”。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;7.&lt;/strong&gt; 自由控制大小­&lt;/p&gt;
  &lt;p&gt;　　缩放工具的快捷键为“Z”，此外“Ctrl＋空格键”为放大工具，“Alt＋空格键”为缩小工具，但是要配合鼠标点击才可以缩放；相同按 Ctrl+“+”键以及“－”键分别也可为放大和缩小图像；Ctrl+Alt+“+”和Ctrl+Alt+“－” 可以自动调整窗口以满屏缩放显示，使用此工具你就可以无论图片以多少百份比来显示的情况下都能全屏浏览！如果想要在使用缩放工具时按图片的大小自动调整窗口，可以在缩放工 具的属性条中点击“满画布显示”选项。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;8.&lt;/strong&gt; 使用非Hand Tool(手形工具)时，按住空格键后可转换成手形工具，即可移动视窗内图像的可见范围。在手形工具上双击鼠标可以使图像以最适合的窗口大小显示，在缩放工具上双击鼠标可使图像以1:1的比例显示。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;9.&lt;/strong&gt; 在使用Erase Tool(橡皮擦工具)时，按住Alt 键即可将橡皮擦功能切换成恢复到指定的步骤记录状态。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;10.&lt;/strong&gt; 使用Smudge Tool(指尖工具)时，按住Alt键可由纯粹涂抹变成用前景色涂抹。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;11.&lt;/strong&gt; 要移动使用Type Mask Tool(文字蒙版工具)打出的字形选取范围时，可先切换成快速蒙版模式（用快捷键Q切换），然后再进行移动，完成后只要再切换回标准模式即可。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;12.&lt;/strong&gt; 按住Alt键后，使用Rubber Stamp Tool(橡皮图章工具)在任意打开的图像视窗内单击鼠标，即可在该视窗内设定取样位置，但不会改变 作用视窗。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;13.&lt;/strong&gt; 在使用Move Tool(移动工具)时，可按键盘上的方向键直接以1 pixel的距离移动图层上的图像，如果先按住Shift键后再按方向键则以每次10 pixel的距离移动图像。而按Alt键拖动选区将会移动选区的拷贝。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;14.&lt;/strong&gt; 使用磁性套索工具或磁性钢笔工具时，按“[”或“]”键可以实时增加或减少采样宽度(选项调板中)。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;15.&lt;/strong&gt; 度量工具在测量距离上十分便利(特别是在斜线上)，你同样可以用它来量角度(就像一只量角器)。在信息面板可视的前提下，选择度量工具点击并拖出一条直线，按住Alt键从第一条线的节点上再拖出第二条直线，这样两条线间的夹角和线的长度都显示在信息面板上。用测量工具拖动可以移动测量线(也可以只单独移动测量线的一个节点)，把测量线拖到画布以外就可以把它删除。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;16.&lt;/strong&gt; 使用绘画工具如(如画笔，向笔等)，按住Shift键单击鼠标，可将两次单击点以直线连接。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;17.&lt;/strong&gt; 按住Alt键用吸管工具选取颜色即可定义当前背景色。通过结合颜色取样器工具(Shift+I)和信息面板监视当前图片的颜色变化。变化前后的颜色值显示在信息面板上其取样点编号的旁边。通过信息面板上的弹出菜单可以定义取样点的色彩模式。要增加新取样点只需在画布上用颜色取样器工具随便什么地方再点一下，按住Alt键点击可以除去取样点。但一张图上最多只能放置四个颜色取样点。当Photoshop中有对话框(例如：色阶命令、曲线命令等等)弹出时，要增加新的取样点必须按住Shift键再点击，按住Alt+Shift点击可以减去一个取样点。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;18.&lt;/strong&gt; 裁切工具大家都一定用过，这种情况你也一定遇到过；在你调整裁切握、而裁切框又比较接近图像边界的时候，裁减框会自动地贴到图像的边上，令你无法精确的裁切图像。不过只要在调整裁切边框的时候接下“Ctrl”键，那么裁切框就会服服帖帖，让你精确裁切。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;复制技巧­&lt;/strong&gt;&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;19.&lt;/strong&gt; 按住Ctrl+Alt键拖动鼠标可以复制当前层或选区内容。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;20.&lt;/strong&gt; 如果你最近拷贝了一张图片存在剪贴板里，Photoshop在新建文件(Ctrl+N)的时候会以剪贴板中图片的尺寸作为新建图的默认大小。要略过这个特性而使用上一次的设置，在打开的时候按住Alt键(Ctrl+Alt+N)。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;21.&lt;/strong&gt; 如果创作一幅新作品，需要与一幅已打开的图片有一样的尺寸、解析度、格式的文件。选取“文件”→“New”，点Photoshop菜单栏的Windows选项，在弹出菜单的最下面一栏点击已开启的图片名称，是的，就是这么简单!­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;22.&lt;/strong&gt; 在使用自由变换工具(Ctrl+T)时按住Alt键(Ctrl+Alt+T)即可先复制原图层(在当前的选区)后在复制层上进行变换；Ctrl+Shift+T为再次执行上次的变换，Ctrl+Alt+Shift+T为复制原图后再执行变换。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;23.&lt;/strong&gt; 使用“通过复制新建层(Ctrl+J)”或“通过剪切新建层(Ctrl+J)”命令可以在一步之间完成拷贝到粘贴和剪切到粘贴的工作；通过复制(剪切)新建层命令粘贴时仍会放在它们原来的地方，然而通过拷贝(剪切)再粘贴，就会贴到图片(或选区)的中心。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;24.&lt;/strong&gt; 若要直接复制图像而不希望出现命名对话框，可先按住Alt键，再执行“图像”→“副本”命令。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;25.&lt;/strong&gt; Photoshop的剪贴板很好用，但你更希望直接使用Windows系统剪贴板，直接处理从屏幕上截取的图像。好的，按下Ctrl＋K，在弹出的面板上将“输出到剪贴板”点中吧！­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;26.&lt;/strong&gt; 在Photoshop内实现有规律复制­&lt;/p&gt;
  &lt;p&gt;　　在做版面设计的时候我们会经常把某些元素有规律地摆放以寻求一种形式的美感，在Photoshop内通过四个快捷键的组合就可以轻易得出。­&lt;/p&gt;
  &lt;p&gt;　　(1)圈选出你要复制的物体；­&lt;/p&gt;
  &lt;p&gt;　　(2)按Ctrl+J产生一个浮动 Layer；­&lt;/p&gt;
  &lt;p&gt;　　(3)按旋转并移动到适当位置后确认；­&lt;/p&gt;
  &lt;p&gt;　　(4)现在可以按住Ctrl+Alt+Shift 后连续按“T”就可以有规律地复制出连续的物体。(只按住Ctrl+Shift则只是有规律移动)­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;27.&lt;/strong&gt; 当我们要复制文件中的选择对象时，要使用编辑菜单中的复制命令。复制一次你也许觉不出麻烦，但要多次复制，一次一次的点击就相当不便了。这时你可以先用选择工具选定对象，而后点击移动工具，再按住“Alt”键不放。当光标变成一黑一白重叠在一起的两个箭头时，拖动鼠标到所需位置即可。若要多次复制，只要重复的放松鼠标就行了。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;28.&lt;/strong&gt; 可以用选框工具或套索工具，把选区从一个文档拖到另一个上。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;29.&lt;/strong&gt; 要为当前历史状态或快照建立一个复制文档可以：­&lt;/p&gt;
  &lt;p&gt;　　(1)点击“从当前状态创建新文档”按钮；­&lt;/p&gt;
  &lt;p&gt;　　(2)从历史面板菜单中选择新文档；­&lt;/p&gt;
  &lt;p&gt;　　(3)拖动当前状态(或快照)到“从当前状态创建新文档”按钮上；­&lt;/p&gt;
  &lt;p&gt;　　(4)右键点击所要的状态(或快照)从弹出菜单中选择新文档把历史状态中当前图片的某一历史状态拖到另一个图片的窗口可改变目的图片的内容。按住Alt键点击任一历史状态(除了当前的、最近的状态)可以复制它。而后被复制的状态就变为当前(最近的)状态。按住Alt拖动动作中的步骤可以把它复制到另一个动作中。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;选择技巧­&lt;/strong&gt;&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;30.&lt;/strong&gt; 把选择区域或层从一个文档拖向另一个时，按住Shift键可以使其在目的文档上居中。如果源文档和目的文档的大小(尺寸)相同，被拖动的元素会被放置在与源文档位置相同的地方(而不是放在画布的中心)。如果目的文档包含选区，所拖动的元素会被放置在选区的中心。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;31.&lt;/strong&gt; 在动作调板中单击右上角的三角形按钮，从弹出的菜单中选择载入动作，进入PhotoshopGoodiesActions目录下，其下有按钮、规格、命令、图像效果，文字效果、纹理、帧六个动作集，包含了很多实用的东西哟!另外，在该目录下还有一个ACTIONS.PDF文件，可用 Adobe Acrobat软件打开，里面详细介绍了这些动作的使用方法和产生的效果。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;32.&lt;/strong&gt; 单击工具条中的画笔类工具，在随后显示的属性条中单击画笔标签右边的小三角，在弹出的菜单中再点击小箭头选择“载入画笔…”。 到Photoshop目录的Brushes文件夹中选择*.abr。原来这里还有这么多可爱的东西。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;33.&lt;/strong&gt; 画出一个漂亮的标记，想在作品中重复使用？好办，用套索工具选好它，在Brushes的弹出菜单中选“储存画笔…”，然后用画笔工具选中这个新笔头……朋友，想做居室喷涂吗?­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;34.&lt;/strong&gt; 如果想选择两个选择区域之间的部分，在已有的任意一个选择区域的旁边同时按住Shift和Alt键进行拖动，画第二个选择区域(鼠标十字形旁出现一个乘号，表示重合的该区域将被保留)。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;35.&lt;/strong&gt; 在选择区域中删除正方形或圆形，首先增加任意一个选择区域，然后在该选择区域内，按Alt键拖动矩形或椭圆的面罩工具。然后松开Alt键，按住Shift键，拖动到你满意为止。然后先松开鼠标按钮再松开Shift键。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;36.&lt;/strong&gt; 从中心向外删除一个选择区域，在任意一个选择区域内，先按Alt键拖动矩形或椭圆的面罩工具，然后松开Alt键后再一次按住Alt键，最后松开鼠标按钮再松开Alt键。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;37.&lt;/strong&gt; 在快速蒙版模式下要迅速切换蒙版区域或选取区域选项时，先按住Alt键后将光标移到快速遮色片模式图标上单击鼠标就可以了。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;38.&lt;/strong&gt; 使用选框工具的时候，按住Shift键可以划出正方形和正圆的选区；按住Alt键将从起始点为中心勾划选区。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;39.&lt;/strong&gt; 使用“重新选择”命令(Ctrl+Shift+D)来载入/恢复之前的选区。­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;40.&lt;/strong&gt; 在使用套索工具勾画选区的时候按Alt键可以在套索工具和多边形套索工具间切换。勾画选区的时候按住空格键可以移动正在勾画的选区。­­&lt;/p&gt;
  &lt;p&gt;　　   &lt;strong&gt;例子：&lt;/strong&gt;&lt;/p&gt;
  &lt;p&gt; &lt;/p&gt;
  &lt;p&gt;   &lt;a href="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409240405.jpg" target="_blank"&gt;    &lt;img alt="" border="0" height="408" src="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409240405.jpg" width="600"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;1.复制图层，混合模式为滤色；&lt;/p&gt;
  &lt;p&gt;2.涂层2蒙板反向擦出眼睛；&lt;/p&gt;
  &lt;p&gt;3.盖印（alt+ctrl+shift+E）；&lt;/p&gt;
  &lt;p&gt; &lt;/p&gt;
  &lt;p&gt;4.通道混合气，选中单色，红色+54，绿色+54，蓝色+32；&lt;/p&gt;
  &lt;p&gt;6.混合模式-正叠；&lt;/p&gt;
  &lt;p&gt;7.对盖印层调整，图像-调整-暗影/高光-暗影：50，50，144 高光：0，50，30 中间调：20.0， 0.01，0.01；&lt;/p&gt;
  &lt;p&gt;8.再次盖印；&lt;/p&gt;
  &lt;p&gt;9.用图章擦去右腮的阳光；&lt;/p&gt;
  &lt;p&gt;10.用减淡工具-范围为高光，强度50%，擦出眼球反光，只擦眼黑；&lt;/p&gt;
  &lt;p&gt;11.再次盖印，滤镜-其他-高反差，参数80；&lt;/p&gt;
  &lt;p&gt;12.改高反差那一层模式为柔光，加强对比；&lt;/p&gt;
  &lt;p&gt;13.用自己喜欢的方法锐化；&lt;/p&gt;
  &lt;p&gt;14.长时间少色相饱和的红色，或别的微调试试。&lt;/p&gt;
  &lt;p&gt; &lt;/p&gt;
  &lt;p&gt; &lt;/p&gt;
  &lt;p&gt; &lt;/p&gt;
  &lt;p&gt;   &lt;a href="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409250082.jpg" target="_blank"&gt;    &lt;img alt="" border="0" height="657" src="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409250082.jpg" width="443"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;1、选择素材图。&lt;/p&gt;
  &lt;p&gt;2、创建新画布，背景填充黑色，并将人物素材拖到画布中，使用橡皮擦工具将脸部之外的部分擦除。&lt;/p&gt;
  &lt;p&gt; 3、创建新透明画布（20 x 20px），将前景色设为白色，使用1px的铅笔工具对画布左侧和下侧描边。&lt;/p&gt;
  &lt;p&gt;4、编辑 &amp;gt;&amp;gt; 变换 &amp;gt;&amp;gt; 变形，按下图调整网格层节点。&lt;/p&gt;
  &lt;p&gt;5、将图层不透明度设为20%。双击网格层打开图层样式窗口，选择外发光，混合模式为“颜色减淡”，不透明度100%，颜色为白色，扩展0，大小5。&lt;/p&gt;
  &lt;p&gt;6、创建新图层，使用钢笔工具沿网格选出若干方块，并用黑色填充。&lt;/p&gt;
  &lt;p&gt;7、按住Ctrl 键并点击上述黑色方块层获得选区，选择人像层，剪切并粘贴（粘贴后的图层命名为“碎片”），并通过自由变换（Ctrl + T）将其缩小一点后移动到如下位置。&lt;/p&gt;
  &lt;p&gt;8、选择碎片层，按住 Alt 键，并同时点击键盘向右方向键（点9次），得到类似立体效果。此时看到图层面板中出现10个碎片层，将除了顶层外的其他碎片层合并，并将合并后的图层命名为“侧边”。双击侧边层，打开图层样式窗口，选择渐变叠加，将不透明度设为80%，角度180，使用#000000 到 #D58761渐变，其他属性取默认值。&lt;/p&gt;
  &lt;p&gt;9、利用画笔工具为侧边添加一些纹理效果。&lt;/p&gt;
  &lt;p&gt;10、重复执行步骤 6-步骤 9，得到如下效果。&lt;/p&gt;
  &lt;p&gt;11、将所有的黑色方块层合并，双击打开图层样式窗口，选择斜面与浮雕，样式为“内斜面”，深度“75%”，大小5px，软化0px，角度0，高度50。高光模式为“滤色”，高光颜色#DCA57E，不透明度100%。阴影模式“正片叠底”，阴影颜色#000000，不透明度75%。&lt;/p&gt;
  &lt;p&gt;12、在碎片层下方创建新图层，使用烟雾笔刷添加烟雾效果。选择碎片层，使用黑色柔角笔刷描绘画布右侧，得到如下渐隐效果。&lt;/p&gt;
  &lt;p&gt;13、在人物层上方创建新图层，再次使用钢笔工具随意选出若干方块，并用黑色填充。将图层混合模式设为“柔光”。&lt;/p&gt;
  &lt;p&gt; &lt;/p&gt;
  &lt;p&gt;14、操作与步骤 13相同，只是填充颜色换成白色。&lt;/p&gt;
  &lt;p&gt;15、选择人物层，滤镜 &amp;gt;&amp;gt; 模糊 &amp;gt;&amp;gt; 表面模糊，半径5px，阀值15。在所有图层上方创建调整图层，图层 &amp;gt;&amp;gt; 创建调整图层 &amp;gt;&amp;gt; 色阶，属性设为10，1.25，244。&lt;/p&gt;
  &lt;p&gt;16、为了得到酷酷的感觉，可以在胳膊上添加条形码纹身。&lt;/p&gt;
  &lt;p&gt; &lt;/p&gt;
  &lt;p&gt; &lt;/p&gt;
  &lt;p&gt; &lt;/p&gt;
  &lt;p&gt;   &lt;a href="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409251918.jpg" target="_blank"&gt;    &lt;img alt="" border="0" height="399" src="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409251918.jpg" width="600"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;1.新建灰色涂层，用曲线调整亮度，152，124。   &lt;br /&gt;2.抠出眼睛和嘴，做个强调。   &lt;br /&gt;3.降低整体饱和度，饱和度-56。   &lt;br /&gt;4.用颜色叠加给整体颜色倾向。   &lt;br /&gt;5.隐藏色相和颜色叠加两层，，打开通道面板，复制R通道。   &lt;br /&gt;6.新建图层粘贴，并用滤色模式调整透明度。   &lt;a href="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409254047.jpg" target="_blank"&gt;    &lt;img alt="" border="0" height="378" src="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409254047.jpg" width="600"&gt;&lt;/img&gt;&lt;/a&gt;   &lt;br /&gt;   &lt;br /&gt; &lt;/p&gt;
  &lt;p&gt;1.复制图层,新建通道混合调整图层,灰色通道，红色+64%，绿色+2%，蓝色+10%，单色。   &lt;br /&gt;2.新建纯色混合图层，选择575046颜色，混合模式为颜色。   &lt;br /&gt;3.新建曲线调整图层，①-输入68，输出32，②-输入114，输出68，③-输入208，输出197。   &lt;br /&gt;4.新建一纯色图层，选择443B25颜色，混合模式为颜色，按住Alt单击蒙板。    &lt;br /&gt;5.Ctrl+D恢复默认的背景颜色，Ctrl+Delete给蒙版填充黑色的背景色。   &lt;br /&gt;6.改变画面，中高光与暗部过渡部分的色调，以丰富画面的色彩，用画笔在蒙板。   &lt;br /&gt;插出需要上色的部分，300像素，不透明度10%，流量100%。   &lt;br /&gt;7.字体的安排与设计。   &lt;br /&gt;8.为了使人物与画面的色调有个呼应，给人物的嘴唇上点唇彩，新建一个图层，选择线性减淡混合模式，添上90753D颜色，选择适合上唇彩的画笔，散点的画笔，像素39。   &lt;br /&gt;9.放大 ，在唇的反光部位画出唇彩，注意观察，不断的调整，画好唇彩之后看下总体，这个时候画面已经有个呼应了，色彩变得丰富，又不喧宾夺主，正好衬托出了产品。   &lt;br /&gt;10.如果产品直接带在模特身上了，在给人物调好色之后，在给产品上色或者用蒙板把产品直接给插出来都可以。   &lt;br /&gt; &lt;/p&gt;
  &lt;p&gt;   &lt;a href="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409255881.jpg" target="_blank"&gt;    &lt;img alt="" border="0" height="419" src="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409255881.jpg" width="600"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;1.打开文件，复制一个图层副本。   &lt;br /&gt;2.选中复制的图层按自由变换快捷键ctrl+t改变人物的脸形使更修长。   &lt;br /&gt;3.按合并图层（ctrl+e）后，用载剪工具使画面从新构图，裁去多出的部份。   &lt;br /&gt;4.图像-调整-可选颜色：红色--70，-20，-20，-50.黄色--40，-20，-30，-80.白色-0，0，0，-50.中间色-0，-5，-5，-5 。   &lt;br /&gt;5.按曲线（ctrl+m）调整整体颜色，RGB全通道-输出214，输入174，蓝通道-输出131，输入124。   &lt;br /&gt;6.图像-调整-色彩平衡（ctrl+b），阴影-10，0，+15。高光--10，0，+2.。   &lt;br /&gt;7.用图章工具将嘴周围皮肤盖均匀。   &lt;br /&gt;8.用钢笔把眼袋和脸部暗部圈起，羽化60，曲线把选区调亮使减淡眼袋和减小脸部肌肉不放松的表情，   &lt;br /&gt;9.继续选区羽化60，曲线调亮，使脸部饱满点，输出146，输入113。   &lt;br /&gt;10.把高光部份圈出来，羽化60。   &lt;br /&gt;11.曲线调亮，使脸部饱满点，输出138，输入118。   &lt;br /&gt;12.修眉，把眉毛顶部连皮肤用套索工具圈起，羽化5，复制一层，把复制图层往下移，以达到修眉作用，图章修眉，这个要很仔细。   &lt;br /&gt;13.开始调整眼睛，选把眼球部份圈出来，复制一层。   &lt;br /&gt;14.钢笔圈出要做眼影的区域，复制一层后，曲线压暗，颜色要调整好。   &lt;br /&gt;15.再把眼影颜色统一，色彩平衡（中间调）：+50，0，0。（阴影）：+20，0，0。   &lt;br /&gt;16.细节颜色调整，上眼睑1/3部分,色相饱和度：0，-40，0。   &lt;br /&gt;17.圈出细节，上眼睑睫毛根处，下眼睑前眼角1/3处，按DELETE键删除选区，使露出高光位。   &lt;br /&gt;18.删除多出的眼影部份，羽化40。   &lt;br /&gt;19.圈出细节，内眼角到上眼睑1/2处，按DELETE键删除选区，使露出高光位。   &lt;br /&gt;20.把眼珠圈出来，复制一层，羽化1，眼白部份减饱和度，退杂色，色相饱和度：0，-50，0。   &lt;br /&gt;21.眼白细节调整，曲线调整调高光。   &lt;br /&gt;22.眼珠复制一层后曲线调亮，用笔刷刷退左眼上半部份，显示些阴影。   &lt;br /&gt;23.删除瞳孔部份。   &lt;br /&gt;24.用曲线调整眼部色彩，使一致。   &lt;br /&gt;25.加眼神高光。   &lt;br /&gt;26.圈出嘴唇，羽化2，曲线调整嘴唇高光，调整嘴唇颜色。   &lt;br /&gt;27.调整鼻梁高光，调整眼影高光。   &lt;br /&gt;28.用可选颜色作整体调色，中间色-0，0，-2，2。   &lt;br /&gt;29.用色颜平衡微调，（高光）：0，2，-2。   &lt;br /&gt;30.液化把头发拉顺，加上镜头光晕，亮度182，35毫米聚焦。   &lt;br /&gt;31.最后在适当的地方加上闪光笔刷完成。   &lt;a href="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409261937.jpg" target="_blank"&gt;    &lt;img alt="" border="0" height="218" src="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409261937.jpg" width="600"&gt;&lt;/img&gt;    &lt;br /&gt;    &lt;br /&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;1.建立色相饱和度调整图层，饱和度-49。   &lt;br /&gt;2.建立可选颜色图层，红色：-49，0，+7，-41.黄色：0，0，0，-23。   &lt;br /&gt;3.建立色相/饱和度图层，明度-49。   &lt;br /&gt;4.可选颜色。黄色：0，0，0，-26.白色：0，0，+46，0。中间色：0，0，-6，0。   &lt;br /&gt;5.可选颜色。红色：0，0，0，-48.黑色：0，0，-47，+5.透明度降低到37%。   &lt;br /&gt;6.盖印，降噪，锐化，用涂抹和简单工具修复膝盖附近的光斑。   &lt;br /&gt;7.加暗角，制作一个心形选区，羽化，用曲线提亮。   &lt;br /&gt; &lt;/p&gt;
  &lt;p&gt;   &lt;a href="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409263215.jpg" target="_blank"&gt;    &lt;img alt="" border="0" height="88" src="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409263215.jpg" width="126"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;1.打开原图，复制图层，填充纯黑色，叠加模式。   &lt;br /&gt;2.新建色相饱和度图层：饱和度-85。   &lt;br /&gt;3.新建亮度对比度图层：对比度+10，。   &lt;br /&gt;4.新建可选颜色，红色：0，+30，0，+100。黄色：0，-15，-100，0.中间色：0，0，0，+5。   &lt;br /&gt;5.盖印，滤镜-渲染-光照效果：点光，强度21，聚焦24，光泽0，材料69，曝光度0，环境8。   &lt;br /&gt;6.盖印，加文字装饰。&lt;/p&gt;
  &lt;p&gt;   &lt;a href="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409272583.jpg" target="_blank"&gt;    &lt;img alt="" border="0" height="199" src="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409272583.jpg" width="600"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;   &lt;br /&gt;   &lt;br /&gt;&lt;/p&gt;
  &lt;p&gt;1.复制图层，滤镜-模糊-径向模糊：数量71，模糊方法-缩放，品质-好。   &lt;br /&gt;2.建立模板，擦出汽车，再用涂抹擦出轮子的动感。   &lt;br /&gt;3.色阶-可选颜色。加素材，渲染整体气氛，同减淡做细节调整，主直径5之内，硬度最小。    &lt;br /&gt; &lt;/p&gt;
  &lt;p&gt;   &lt;a href="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409274046.jpg" target="_blank"&gt;    &lt;img alt="" border="0" height="426" src="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409274046.jpg" width="600"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;1.稍微调整一下偏色，调出一个大致的色调，建立色阶调整层，色阶全通道：0，1.35，255。色阶红通道：0，0.85，255.色阶绿通道：0，1，10，255色阶：0，0.95，255。   &lt;br /&gt;2.建立色相/饱和度调整层降低原图的饱和度，全图饱和度-30。   &lt;br /&gt;3.建立一个照片滤镜调整层，第一步中青色已经出来了，这一步把深黄色加上，浓度25%，模式“柔光”，在“柔光”模式下，原先暗的地方会更暗，选择通道面板，按住ctrl点红通道，得到选区回到照片滤镜的蒙板中填充黑色。   &lt;br /&gt;4.建立可选颜色调整层，红色：100，-33，100，-40。黄色：0，0，-40，0。白色：+15，0，+20，+20。   &lt;br /&gt;5.把窗户提亮些，建立色相/饱和度调整层，把“着色”勾上，模式“柔光”，设置好后在蒙板中把窗户以外的部分擦掉。色相260，饱和度25，明度+75。   &lt;br /&gt;6.建立一个色彩平衡调整层，把人物和周围环境区分开来，设置好后在在蒙板中用黑色大号柔角画笔以人物为中心擦一下就可以了。色阶+20，+20，+40，选中间调。&lt;/p&gt;
  &lt;p&gt;   &lt;a href="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409275594.jpg" target="_blank"&gt;    &lt;img alt="" border="0" height="88" src="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409275594.jpg" width="126"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;   &lt;br /&gt;   &lt;br /&gt;&lt;/p&gt;
  &lt;p&gt;1.建立新图层，填充淡黄色，叠加模式，数值247，240，197 。   &lt;br /&gt;2.复制刚才的黄色图层，线性加深模式，蒙版擦出黄色小车，避免小车颜色过黄。   &lt;br /&gt;3.调亮度对比度，以高光部分的色彩和曝光正常为准，亮度-20，对比度+64，新建饱和度调整图层，饱和度-31.确定明处的最终亮度，以高光处色彩和细节为准，暗处可以先忽略。   &lt;br /&gt;4.复制背景图层调节暗影高光，以暗部细节最到位为基准，阴影：数量100，色调宽度33，半径102，高光：数量0，色调宽度50，半径30，调整：颜色校正+20，中间调对比度0，修建黑色0.01%，修建白色0.01%。   &lt;br /&gt;5.复制背景图层调整天空亮度，用该层弥补天空过曝的不足。   &lt;br /&gt;6.调整细节，把天上的电线擦掉，修复画笔仿制图章都行。   &lt;br /&gt;7.拼合图像，微调细节，锐化 。   &lt;br /&gt;   &lt;br /&gt;    &lt;a href="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409282276.jpg" target="_blank"&gt;    &lt;img alt="" border="0" height="212" src="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409282276.jpg" width="600"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;1.打开图片复制图层，Ctrl+Alt+~，得到选区，羽化3-5.曲线提亮，18，0左右。   &lt;br /&gt;2.调整色阶：25，1，20，245.蒙版擦出人物主体及细节部分。   &lt;br /&gt;3.盖印，对人物进行磨皮修饰提亮边缘锐化。   &lt;br /&gt;4.对盖印图层进行色彩平衡，中间调：-12，-10，-13.高光：+8，0，-19。   &lt;br /&gt;5.盖印图层，进入LAB模式。   &lt;br /&gt;6.新建图层，Shift+Ctrl+N，柔光模式，透明度30-40%。   &lt;br /&gt;7.在新建图层上进行应用图像，图层：合并图层，柔光模式，透明度100%。   &lt;br /&gt;8.调整图层，对明度通道进行曲线调整，5，0。   &lt;br /&gt;9.对图像进行LAB颜色的色相饱和度进行调整，全图：0，+10，0.黄色：0，+35，0.绿色：0，+15，0.红色：0，-20，0.蓝色：+10，+30，0。   &lt;br /&gt;10.进入色阶：20，1.20，245.对明度通道进行调整，在蒙板处用圆渐变拉出人物主体，再用画笔擦出细节。   &lt;br /&gt;11.盖印，返回RGB颜色，对图像进行可选颜色选项，红通道：0，0，0，-30在蒙板上擦出花瓣。    &lt;br /&gt;12.盖印，新建空白层，用白色画笔增加洒水效果，钢笔压力。硬度100%，间距+54%。   &lt;a href="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409284750.jpg" target="_blank"&gt;    &lt;img alt="" border="0" height="88" src="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409284750.jpg" width="126"&gt;&lt;/img&gt;&lt;/a&gt;   &lt;br /&gt;   &lt;br /&gt; &lt;/p&gt;
  &lt;p&gt;1.弄个帅点的眼珠，增加视觉并且吸引人，复制眼球出来，把眼球图层改成滤色模式，这种效果老外比较容易做到，亚洲人要么最好带个美瞳或是换个“眼睛”。   &lt;br /&gt;2.提亮脸部，突出脸部，用套索工具套住脸，羽化后提亮，不需要太亮。   &lt;br /&gt;3.用套索工具拉出头发，拉到脸也没关系，之后可以用橡皮擦擦干净，羽化后提亮。   &lt;br /&gt;4.体谅整体，看起来统一点，头发部分可以用橡皮擦擦掉一点点。   &lt;br /&gt;5.覆盖得到新图层（Ctral+Alt+Shift+E），用图章工具伏在脸上的痣，在色彩平衡力稍微减少点色，而增加点情色，看起来白点。   &lt;br /&gt;6.新建一个透明层，图层模式为柔光，用深色眼影在上下眼线处添加，颜色是从眼睛内部发出，由深到浅，层次感，用柔光度最高的笔刷。   &lt;br /&gt;7.新建一个透明层，柔光模式，用紫色画一圈眼影当底色，如果怕效果不好可以常使用模糊调整颜色，知道觉得均匀为止。   &lt;br /&gt;8.调整皮肤的高光区域，添加一个新的透明层，叠加模式，同笔刷涂上鼻尖的颜色，找到根照片最贴切的颜色并且增加高光，好处就是可以提高反差来增加视觉。   &lt;br /&gt;9.做整体调整，增加新的透明层，柔光模式，增加高光地区颜色，颜色不变，在额头跟头发之间那里添加暗红色，增加阴影，脸蛋的红色饱和度不要太高，也不要太低，感觉涂到脸上看起来真实就好。   &lt;br /&gt;10.新建透明层，柔光模式，在鼻子级高光部分添加高光颜色，让鼻子跟轮廓看起来更加的深，更高挑，能把脸上脏的地方擦掉，或者说有暗黑的区域。   &lt;br /&gt;11.新建透明层，叠加模式，给嘴唇上色，涂上紫红色，透明度为70% 。   &lt;br /&gt;12.新建透明层，正片叠加模式，透明度40%，在鼻子，额头，脸部那里增加黑红色，增加阴影跟层次感。   &lt;br /&gt;13.新建透明层，叠加模式，是、眼影要化两层，一层是外面浅一点的，里面的要深紫色，最好高斯迷糊一下直到均匀。   &lt;br /&gt;14.新建透明层，柔光模式，增加黑紫色，要把这部分化黑，看起来更妖艳。   &lt;br /&gt;15.新建透明层，叠加模式，在内眼角到鼻侧一直到脸处，人中，两唇之间画上淡，深红色，增加轮廓的层次感，调整透明度画好后，可能会深些。   &lt;br /&gt;16.侧额头及脸狭加深颜色，叠加模式，颜色是红色系的。   &lt;br /&gt;17.给嘴唇下面那里加阴影，不然嘴看起来很假。   &lt;br /&gt;18.用相同颜色遮住脸上脏的地方，用吸管吸取旁边相同的颜色，可能会遮住部分头发，一会画上即可。    &lt;br /&gt;19.新建透明层，柔光模式，家上绿色下眼影。   &lt;br /&gt;20.嘴巴跟脸部脏的地方用吸管吸取相同颜色，新建图层补到脏的地方。   &lt;br /&gt;21.新建图层，正片叠底模式，透明度20%，涂上黑红色补上。   &lt;br /&gt;22.脸部的头发是深棕色，在黑色头发里面头发更是浅一点颜色的灰色了，画好头发部分。   &lt;br /&gt;23.新建图层，填补接近色来遮住额头皮肤，棉的看起来那么粗糙。   &lt;br /&gt;24.脸部补色，看起来更红，更夸赞，更吸引为止。   &lt;br /&gt;25.新建透明层，正片叠底模式，透明度50%，在额头上棕色，压暗皮肤的颜色，以提升对比度。   &lt;br /&gt;26.新建透明层，叠加模式，透明度50%，在腮部画上橘红色，老外的妆面比较夸张，红点没关系。   &lt;br /&gt;27.在调整下整体颜色，锐化一下。   &lt;br /&gt;   &lt;br /&gt; &lt;/p&gt;
  &lt;p&gt;   &lt;a href="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409291140.jpg" target="_blank"&gt;    &lt;img alt="" border="0" height="398" src="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409291140.jpg" width="600"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;1.打开原文件，根据自己的感觉通过色彩调整将片子调整，然后磨皮，磨皮值不要太大，（Neat image插件）。   &lt;br /&gt;2.新建图层，颜色为FEE7D6，（根据片子人物的肤色来设置），图层模式为叠加25%，用画笔20%在脸部和脖子处皮肤轻涂。   &lt;br /&gt;3.五官的细化工作，抠出嘴部，进行羽化复制（Ctrl+J），用涂抹工具对唇部进行涂抹，使唇部皮肤变得柔和细腻（强度不要太大）。   &lt;br /&gt;4.新建图层，给唇部和脸部上色，颜色为FDC1D6，图层模式为颜色，用画笔在唇部和脸侧进行涂抹。   &lt;br /&gt;5.用减淡工具，范围是高光，曝光度25%画出唇部的高光部分，用加深工具，范围是中间，曝光度20%，加强唇部对比。   &lt;br /&gt;6.新建图层，颜色为8E1A25，画笔像素为3，画出内侧内线，然后像素为2画出唇部外侧线条，（高光部分线条建蒙板减淡些）。   &lt;br /&gt;7.对鼻子进行圈选羽化，复制，用涂抹工具对鼻子周围进行柔和细化，接着用减淡工具范围是高光，曝光度20%，加强下鼻子的高光部分，然后用颜色422B2D，笔刷为2像素画出鼻子的轮廓线（线条如果淡了用加深工具来弥补下）。   &lt;br /&gt;8.对眼睛眉毛圈选羽化复制，用涂抹工具对眼睛眉毛周围皮肤进行柔和细化，接着用减淡工具范围是高光，曝光度15%，加强下眼眶的高光部分，用加深工具范围是中间，加深眼睛周边的线条。   &lt;br /&gt;9.用涂抹工具对眼珠部分进行涂抹细化，看起来更柔和些，用加深工具对黑眼珠部分加深，用减淡工具范围是高光，曝光度20%加强眼珠的高光部分，使看起来眼睛更明亮。   &lt;br /&gt;10.颜色080101，画笔像素3，画出睫毛部分，（线条颜色深浅可用加深减淡工具来弥补）睫毛线条也可以用路径等一些方法勾出。   &lt;br /&gt;11.用涂抹工具把眉形涂抹的漂亮些，眉头粗点颜色稍深一点，后面顺着涂抹淡化下去，然后用画笔2个像素在眉前端画出眉毛线条，使眉毛更有层次。   &lt;br /&gt;12.涂抹工具选择适合头发的画笔，（根据头发的纹理设置画笔形状），涂抹过程中要顺着头发的纹理涂抹，不要太过力，涂抹的要均匀。   &lt;br /&gt;13.发梢部分用正常的画笔涂抹来衔接上，（涂抹头发一定要细心）。   &lt;br /&gt;14.画出头发的质感来，新建图层，图层模式为叠加，选择铅笔像素为1，（数值根据人物图片大小来定），颜色为DFDFDF顺着头发的纹理画出流畅的线条。   &lt;br /&gt;15.马尾部分可选择画笔工具，带分叉的一些笔刷淡淡顺着纹理画上，颜色图层模式同上。   &lt;br /&gt;16.新建图层，正常模式，选择画笔工具，像素为1，不透明度60%，流量80%，颜色为白色，画出前额动感发丝。   &lt;br /&gt;17.衣服项链部分用涂抹工具涂抹的柔和些，然后选择用减淡工具，范围是高光，曝光20%，加强衣服和项链的高光部分。   &lt;br /&gt;18.合成，对图片整体进行锐化，锐化值为8，用减淡工具对高光部分进行稍微加工下，整体颜色校正下，（可以添加一些背景灯修饰，突出主题）。   &lt;a href="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409293252.jpg" target="_blank"&gt;    &lt;img alt="" border="0" height="395" src="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409293252.jpg" width="600"&gt;&lt;/img&gt;    &lt;br /&gt;    &lt;br /&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;1.打开原图，复制一层，图像-调整-去色。   &lt;br /&gt;2.滤镜-艺术效果-塑料包装，根据原图降低透明度。   &lt;br /&gt;3.调整黑色层的色阶，是图片黑白分明，色阶：88，0.27，192。   &lt;br /&gt;4.Ctrl+Alt+~,提取黑白层的高光选区，点钱变得小眼睛，隐藏起来，回到背景图层。   &lt;br /&gt;5.把前面得到的高光选取调整曲线，把曲线拉到顶端，效果就出来了。   &lt;br /&gt;6.调整背景图层的亮度对比度，加大，或者适当调一下颜色，亮度+4，对比度+7 。   &lt;br /&gt; &lt;/p&gt;
  &lt;p&gt;   &lt;a href="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409295030.jpg" target="_blank"&gt;    &lt;img alt="" border="0" height="443" src="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409295030.jpg" width="600"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;1、打开荷花照片，复制背景图层。   &lt;br /&gt;2、去色并调整色阶以增加黑白对比。色阶：15，1.0，200。   &lt;br /&gt;3、反相后执行高斯模糊，半径1，再执行滤镜—画笔描边—喷溅。喷色半径1，平滑度3。   &lt;br /&gt;4、新建图层，设置图层混合模式为颜色，用粉红色的画笔给荷花涂上颜色。   &lt;br /&gt;5、再随意加点文字，加盖印章，完成。   &lt;br /&gt; &lt;/p&gt;
  &lt;p&gt;   &lt;a href="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409300422.jpg" target="_blank"&gt;    &lt;img alt="" border="0" height="232" src="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409300422.jpg" width="600"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;1.进入通道面版，接着用“运用通道”，对三个RGB通道进行运用。    &lt;br /&gt;图像-应用图像-图层：背景-通道蓝-混合正片叠底，不透明度50% 。   &lt;br /&gt;通道绿-混合正片叠底，不透明度20%。   &lt;br /&gt;通道红-混合变暗，不透明度100%。   &lt;br /&gt;2.调整-色彩平衡-高光-色阶：-8，+13，+11 。   &lt;br /&gt;3.蓝通道在进行一次应用图像，图层：背景-混合：正片叠底，不透明度50%。   &lt;br /&gt;4.用曲线调亮度，红通道右上方动一点点。   &lt;br /&gt;全通道6，0 蓝通道4，15。   &lt;br /&gt;5.复制一个图层副本出来，再次进行蓝通道的运算，混合正片叠底，不透明度50%。   &lt;br /&gt;6.最后要做的就是突出人物了，用橡皮擦，擦出人物部份，注意适当的降低透明度。   &lt;a href="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409301989.jpg" target="_blank"&gt;    &lt;img alt="" border="0" height="404" src="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409301989.jpg" width="600"&gt;&lt;/img&gt;&lt;/a&gt;   &lt;br /&gt;   &lt;br /&gt; &lt;/p&gt;
  &lt;p&gt;1.复制一个新层。   &lt;br /&gt;2.用印章工具把痘痘修掉。   &lt;br /&gt;3.把修痘结果记录快照。   &lt;br /&gt;4.做一个高斯模糊，力度以皮肤肌理消失为准，半径4.0 。   &lt;br /&gt;5.记录快照，起名【高斯模糊】。   &lt;br /&gt;6.按【修痘痘】使图片回到刚修完痘时候的状态，并点【高斯模糊】左边的小框，使小图标切换过来，这是为了给马上要用的历史记录画笔作为目标指向。   &lt;br /&gt;7.历史记录画笔，用它在脸上需要光滑处涂抹，注意避开轮廓线和头发眉毛等处，你可以使用 [ 键和 ] 键随时改变笔刷的大小，以修改细微的部分，如果不小心刷错，没有关系，你只要在历史记录面板里，把左边的小图标点按到【修痘痘】，然后再刷，即可刷回去，就是开头所说的过程可逆。   &lt;br /&gt;8.可以改变笔刷的不透明度，来控制你涂抹的力度，画笔20，不透明度55%。   &lt;br /&gt;9.磨光滑后的效果，很光滑，但是没有皮肤质感，还需要下一步的加工。   &lt;br /&gt;10.记录快照为【磨光滑】，每一阶段完成，我们都最好记录下来，随时可以回去。   &lt;br /&gt;11.继续做下去，Ctrl+A来个全选，再来个Ctrl+C，copy下磨光的效果。然后，点按历史记录面板上的【修痘痘】，使文件回到磨光前的状态。   &lt;br /&gt;12.Ctrl+V把刚才copy下来的磨光效果释放到新的一层，并改变透明度，使下层能透出一些，不透明度70%    &lt;br /&gt;13.点按下层，也就是没磨过的那层，来个大大的锐化，数量140，半径0.7。   &lt;br /&gt;14.这样的叠加，使皮肤细腻又不失去纹理质感，皮肤磨光步骤完成了，记得保存快照【皮肤完成】。   &lt;br /&gt;15.把图层1拉到下边小图标，复制新层，设置为“柔光”模式，透明度25左右，其他数值也可以，看你偏好。   &lt;br /&gt;16.校色，去掉点肤色里的黄，调整高光色，色阶-5，0，+15，保持亮度。   &lt;br /&gt;   &lt;br /&gt; &lt;/p&gt;
  &lt;p&gt;   &lt;a href="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409303021.jpg" target="_blank"&gt;    &lt;img alt="" border="0" height="214" src="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409303021.jpg" width="600"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;1.选蓝色通道“应用图像”，勾上“反相”，混合“正片叠底”，回到RGB图层，混合模式“柔光”。   &lt;br /&gt;2.通道混合器，勾上“单色”；图层混合模式“正片叠底”。   &lt;br /&gt;3.磨皮，美化人物形体。   &lt;br /&gt;4.给人物皮肤和衣服加上“油光”的效果，《摸索出来的塑料油光教程》，   &lt;br /&gt;5.有了“电影效果滤镜AGEDFILM”，这一步可以节省一点时间，所有参数默认；使用完后的效果是蓝色的，还需要再用“色相/饱和度”调整一下颜色。   &lt;br /&gt;6.把步骤6得到的效果混合模式改成“柔光”，适当调整图层透明度。   &lt;br /&gt;7.调整一下“色彩平衡”。   &lt;br /&gt;8..“锐化”一下人物。   &lt;br /&gt;9.细调一下人物面部肤色、亮度对比度和一些细节问题。   &lt;br /&gt;10.制作如图所示的“光芒”效果。   &lt;br /&gt;11.“高斯模糊”，“半径”65。   &lt;br /&gt;12.给“光芒”加上“外发光”，“大小”20。   &lt;br /&gt;13。把“光芒”图层的混合模式改成“柔光”，不透明度“25%”。   &lt;a href="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409304336.jpg" target="_blank"&gt;    &lt;img alt="" border="0" height="252" src="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409304336.jpg" width="600"&gt;&lt;/img&gt;&lt;/a&gt;   &lt;br /&gt;   &lt;br /&gt; &lt;/p&gt;
  &lt;p&gt;1.复制图层，调整-去色。   &lt;br /&gt;2.曲线调节，加大明暗对比，输入114，输出186。   &lt;br /&gt;3.复制图层，滤镜-画笔描边-墨水轮廓，描边长度5，神色强度10，光照强度10，降图层改成柔光模式，调整不透明度。   &lt;br /&gt;4.滤镜-高斯模糊，半径2.0像素。   &lt;br /&gt;5.滤镜-画笔描边-喷溅，喷色半径1，平滑度3。   &lt;br /&gt;6.添加浅棕色纯色层，，图岑附魔师为颜色，调整不透明度，不透明度尽量小些。   &lt;br /&gt;7.点掉纯色层及图层前边的眼睛将其隐藏，新建图层用笔刷在灯笼，树，瓦片等处用适当颜色图层。   &lt;br /&gt;8.将隐藏图层重新恢复，修改图层模式为叠加，看效果来调细节。   &lt;br /&gt;9.对画面整体效果进行细调，直到达到满意的效果，没有具体步骤，因人而异。   &lt;br /&gt; &lt;/p&gt;
  &lt;p&gt;   &lt;a href="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409305759.jpg" target="_blank"&gt;    &lt;img alt="" border="0" height="243" src="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409305759.jpg" width="600"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;1.照一张带白边的图片风景图，有白边为做边缘溢出效果。   &lt;br /&gt;2.色相饱和度：饱和度+80，调整出印象派的效果。   &lt;br /&gt;3.编辑-定义图案。    &lt;br /&gt;4.建白色填充层，不透明度50%，再建一个透明图层。   &lt;br /&gt;5.图案图章工具，画笔主直径200，画笔选自带湿介质画笔45，模式正常，不透明度100%，印象派效果前面打勾。   &lt;br /&gt;6.在透明图层图案图章画画，远景次景笔触大，反之笔触小细节多，调不透明度查看上面图层的笔触。   &lt;br /&gt;7.复制背景层去色，滤镜-喷溅，不透明度71%，图层模式为叠加。   &lt;br /&gt;8.滤镜-纹理-纹理化，不透明度100%。   &lt;br /&gt;9.滤镜-扭曲-扩散光亮37% 。   &lt;a href="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409311720.jpg" target="_blank"&gt;    &lt;img alt="" border="0" height="434" src="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409311720.jpg" width="600"&gt;&lt;/img&gt;&lt;/a&gt;   &lt;br /&gt;   &lt;br /&gt; &lt;/p&gt;
  &lt;p&gt;1.在RAW中调整亮度，对比等，为之后的调整打基础。   &lt;br /&gt;2.加入天空素材，简单透明度，让天空融入到图层中。   &lt;br /&gt;3.新建调整层，可选颜色-中间色：+20，+6，+7，-4，绝对，稍微统一海水颜色。   &lt;br /&gt;4.颜色填充土黄色，不透明度54%，颜色填充藏蓝色，不透明度61%，填充深紫色，不透明度76%。   &lt;br /&gt;5.细致调整，高光与中间调的选择方法与所得到的蒙版，高光的选择方法：计算-源1：图层合并图层，灰色通道，源2：图层合并图层，灰色通道，正片叠底混合，不透明度100%。   &lt;br /&gt;6.中间调的选择方法：源1：合并图层，灰色通道，源2：合并图层，灰色通道，正片叠底混合，不透明度100%。   &lt;br /&gt;7.RGB通道里得到的蒙版，用曲线调整，高光的调整：黑色线在倒数第二格左边中间线，蓝色线向下调一点，中间调的调整：向上调整一些。   &lt;br /&gt;8.反射光的蒙版，套索选出选区，羽化，整体提亮。   &lt;br /&gt;9.船上的杂物降低饱和度，饱和度：-36。   &lt;br /&gt;10.锐化整体。   &lt;br /&gt; &lt;/p&gt;
  &lt;p&gt;   &lt;a href="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409313084.jpg" target="_blank"&gt;    &lt;img alt="" border="0" height="210" src="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409313084.jpg" width="600"&gt;&lt;/img&gt;&lt;/a&gt;1.复制图层，调整亮度对比度，向下合并。   &lt;br /&gt;2.进入LAB模式，选择图像中的应用图像，进行计算。   &lt;br /&gt;3.将图层模式改成颜色，盖印图层。   &lt;br /&gt;4.进入RGB通道，将蓝通道填充黑色，提取绿通道选区，将选区填充白色。   &lt;br /&gt;5.色相饱和度，红色：+20，+1，0.青色：-7，+26，0.其他数据不动，将该图层模式改成颜色。   &lt;br /&gt;6.进入RGB通道，选取绿通道选区，进行反选，调整层中的色彩平衡，选择中间调，数值：-10，-6，+16.阴影：+4，+5，-2.高光：-19，-26，-40 。   &lt;br /&gt;7.盖印图层，进入RGB通道，选取红通道选区，复制，回到RGB模式粘贴，图层模式改成颜色，选取调整层中的曲线，红通道：173，193。红通道：58，56.绿通道：180，201.绿通道：53，58.蓝通道：55，62。   &lt;br /&gt;8.将图层模式改成颜色，复制该图层，在复制该图层，图层模式改成亮度，透明度20%。   &lt;br /&gt;9.选取调整层中的色相饱和度，青色：+5，-49，-2。   &lt;br /&gt;10.调整调整层中的色彩平衡，中间调：-6，0，+3.阴影：-7，+3，-1。   &lt;br /&gt;11.色彩平衡，阴影：+4，+5，-2。阴影：+4，+5，-2.高光：-19，-26，-40。   &lt;br /&gt;12.加上闪电效果。   &lt;br /&gt; &lt;/p&gt;
  &lt;p&gt;   &lt;a href="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409315908.jpg" target="_blank"&gt;    &lt;img alt="" border="0" height="436" src="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409315908.jpg" width="600"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;1.复制一层转换为智能滤镜，目的可以对滤镜进行效果调整。   &lt;br /&gt;2.滤镜-渲染-光照效果,全光源，负片17，杂边-25，塑料效果100，曝光不足32，负片28。   &lt;br /&gt;3.新建可选颜色调整图层，红色：-100，-3，03，0.黄色：-59，-6，-23，+1.绿色：+9，+5，-100，+27.青色：+8，-76，-3，-100。白色：+1，-40，-73，-10.中间色：+16，-18，-18，-3.黑色：0，0，0，+28 。   &lt;a href="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409321236.jpg" target="_blank"&gt;    &lt;img alt="" border="0" height="407" src="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409321236.jpg" width="600"&gt;&lt;/img&gt;&lt;/a&gt;   &lt;br /&gt;   &lt;br /&gt; &lt;/p&gt;
  &lt;p&gt;1 首先拿出事先拍好的图片。   &lt;br /&gt;2 用蒙板遮罩天空部分。   &lt;br /&gt;3 添加天空部分，并放置于底层，可根据画面适当调整。   &lt;br /&gt;4 新建一层为第三层，主要是调整画面色调。   &lt;br /&gt;5 根据需求修改不透明度，修改图层属性为柔光。   &lt;br /&gt;6 为了寻求油画中的肌理效果，在色调层上面再添加了一个素材层。   &lt;br /&gt;7 修改图层属性为柔光，根据需求修改不透明度。这里不透明度为86%。   &lt;br /&gt;8 添加蒙板，根据画面需要适当取舍内容。   &lt;br /&gt;9 为了加强肌理感，再新建一层，填充灰色。   &lt;br /&gt;10 在滤镜中添加杂色为高斯分布并勾选单色，数量自定。   &lt;br /&gt;11 图层改为柔光。   &lt;br /&gt;12 根据画面需要用蒙板适当加以调整。   &lt;br /&gt;13 噪点，添加杂色-数量400，高斯分布   &lt;br /&gt; &lt;/p&gt;
  &lt;p&gt;   &lt;a href="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409322539.jpg" target="_blank"&gt;    &lt;img alt="" border="0" height="401" src="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409322539.jpg" width="600"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;1.打开原图，取色，用修复工具把大面积破坏区修好。   &lt;br /&gt;2.复制图层一副本，滤镜-杂色-蒙尘与划痕，半径10，阈值6。   &lt;br /&gt;3.给图层一副本增加蒙版，点击蒙版，用画笔工具在人物边缘以外的地方涂抹。   &lt;br /&gt;4.给图层一进行滤镜-杂色-蒙尘与划痕，半径10，阈值6。   &lt;br /&gt;5.图层一回到历史记录面板，蒙尘与划痕的上面一层，用画笔擦涂有斑点的地方，眼睛面部阴影的要小心些。   &lt;br /&gt;6.如果要求高点的就做点高反差保留或用点色阶改变点精神。   &lt;br /&gt;7.修复中的有些参数全做参考你自己的细致调整会更好。   &lt;a href="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409323639.jpg" target="_blank"&gt;    &lt;img alt="" border="0" height="216" src="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409323639.jpg" width="600"&gt;&lt;/img&gt;&lt;/a&gt;   &lt;br /&gt;   &lt;br /&gt; &lt;/p&gt;
  &lt;p&gt;1.用Photoshop打开原图。生活照由于大多出自低端的数码相机，黑白场都不能很好地被定位，所以照片往往都会像这张一样发灰。   &lt;br /&gt;2.先复制一层背景，USM锐化，数量50，半径0.5。   &lt;br /&gt;3.调整色阶，右边为高光数量，左边为暗调数量，中间为中间调，增加脸部的亮度，0，1.0，200。   &lt;br /&gt;4.调节色彩平衡，让照片整体偏青色，比较衬托脸部。阴影：-30，0，0。   &lt;br /&gt;5.新建一个黑白层，加强对比度，选择“高对比度红色滤镜”。   &lt;br /&gt;6.把混合模式改成“柔光”，不透明度降低到70%。   &lt;br /&gt;7.这时候的照片显得非常苍白，再加一个色相/饱和度调节层，+15的饱和度。   &lt;br /&gt; &lt;/p&gt;
  &lt;p&gt;   &lt;a href="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409324721.jpg" target="_blank"&gt;    &lt;img alt="" border="0" height="593" src="http://ce.sysu.edu.cn/hope2011/UploadFiles/beautydesign_UploadFiles_6635/201004/2010040409324721.jpg" width="439"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt; &lt;/p&gt;
  &lt;p&gt;1 打开一张图片。   &lt;br /&gt;2 按d键(默认前景色)。   &lt;br /&gt;3 窗口--动作--创建新动作,名称 --下雨。   &lt;br /&gt;4 复制图层,在新图层上,滤镜--像素化--点状化单元格大小--3 点状化越大雨就越大，点状化越小雨就越小。   &lt;br /&gt;5 图象--调整--阈值 255.将图层模式改为 滤色。   &lt;br /&gt;6 滤镜--模糊--动感模糊, 角度76,距离22,确定.距离越大雨夜就越大，距离越小雨就越小。   &lt;br /&gt;7 滤镜--锐化--在执行一次滤镜--锐化。   &lt;br /&gt;8 点窗口--动作--点停止播放;然后点播放选定动作(实际是复制了图层)3次(这样就有了4个下雨图层)。   &lt;br /&gt;9 打开动画,在第一桢上关闭上面3个层的眼睛,只留背景和图层1的眼睛;第2桢关闭图层1的眼睛,打开图层1副本的眼睛;第3桢关闭图层1副本的眼睛,打开图层1副本2的眼睛;第4桢关闭图层1副本2的眼睛,打开图层1副本3的眼睛.在选择全部帧，设时间为0.2秒。   &lt;br /&gt;10 最后保存GIF动画格式.&lt;/p&gt;
&lt;/div&gt;
          
           &lt;br /&gt; &lt;br /&gt;
          
             &lt;a href="http://liuguofeng.iteye.com/blog/2122850#comments"&gt;已有   &lt;strong&gt;0&lt;/strong&gt; 人发表留言，猛击-&amp;gt;&amp;gt;  &lt;strong&gt;这里&lt;/strong&gt;&amp;lt;&amp;lt;-参与讨论&lt;/a&gt;
          
           &lt;br /&gt; &lt;br /&gt; &lt;br /&gt;
ITeye推荐
 &lt;br /&gt;
 &lt;ul&gt;  &lt;li&gt;   &lt;a href="http://www.iteye.com/clicks/433" target="_blank"&gt;—软件人才免语言低担保 赴美带薪读研！— &lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;
 &lt;br /&gt; &lt;br /&gt; &lt;br /&gt;
          
        &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/51225-photoshop-%E6%8A%80%E8%83%BD-%E7%BB%8F%E5%85%B8</guid>
      <pubDate>Fri, 26 Sep 2014 22:03:21 CST</pubDate>
    </item>
    <item>
      <title>Redis入门经典——The Little Redis Book （翻译）</title>
      <link>https://itindex.net/detail/51611-redis-%E7%BB%8F%E5%85%B8-the</link>
      <description>&lt;p&gt;The Little Redis Book &lt;/p&gt;
 &lt;p&gt;                By Karl Seguin&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;关于本书&lt;/strong&gt;：本书完全免费下载。你可以随意转载，复制，但请你注明作者，Karl Seguin。译者,WY。以及不要用于商业用途。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;关于作者&lt;/strong&gt;：Karl 同志是广大屌丝IT码农中的一员。但经验丰富，不仅活好而且跨领域甚广。闲暇之余，跟笔者一样闲的蛋疼，写了几本小书。没想到还挺受欢迎，特别是The Little MongoDb Book，风靡码农界。更多资讯看他的个人博客http://openmymind.net 。&lt;/p&gt;
 &lt;p&gt;本书最新版本：   &lt;a href="http://github.com/karlseguin/the-little-redis-book" target="_blank"&gt;
http://github.com/karlseguin/the-little-redis-book&lt;/a&gt;&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;简介：&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;最近几年，用于数据持久化查询的的技术和工具到一个突飞猛进的地步。但可以打包票的说，关系型数据也就那样了，同时，围绕数据的那套系统却肯定会是大不一样的。&lt;/p&gt;
 &lt;p&gt;在所有的工具和技术解决方案中，Redis 是最令我虎躯一震的。第一是因为它太TM容易上手了。你只需花费几小时的时间就可以上手使用了。第二，它用一种非常通用的方法解决了一系列特殊问题。为什么呢？因为他并非所有的东西都是有关数据的。你了解的越多，对这句话的理解就会越深刻。&lt;/p&gt;
 &lt;p&gt;当你能仅用Redis 完成一个系统时，我想你已经找到它提供的最普遍的解决方案——不管该系统是传统的关系型数据库，还是一个基于文档的系统。在这方面，它有点像是一个索引引擎，不过你无须将所有应用构建在Lucene（由apache发布的著名的全文检索引擎工具包）上。当然，也就这一点相似而已。&lt;/p&gt;
 &lt;p&gt;本书的目的是介绍Redis 的一些基础。我们会把重点放在Redis 的五种数据结构以及不同的数据建模方法。当然还会接触一些关键的管理方法以及调试技巧。&lt;/p&gt;
 &lt;p&gt;    &lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;开始：&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;     学习的方法不同，有人喜欢上手，有人喜欢看视频，也有人喜欢看书。不过最有效的方法不过直接试用一下了。在学习以下内容时，最好先安装一个Redis，灰常简单的哦。&lt;/p&gt;
 &lt;p&gt; Redis是不支持Widows的，但这妨碍不了万能的码农们如果只是玩票的话，用  &lt;a href="https://github.com/MSOpenTech/redis" target="_blank"&gt;https://github.com/MSOpenTech/redis&lt;/a&gt;。&lt;/p&gt;
 &lt;p&gt;*nix下的安装就自行谷歌下吧。&lt;/p&gt;
 &lt;p&gt; 安装完成后，以Linux 下为例，运行./redis-server.启动服务器，然后运行./redis-cli，将以默认接口（6379）连接本地服务.你可以在命令行下输入info 测试服务器的状态。&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;第一章   基础&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;  &lt;/strong&gt;在研究Redis的时候首先我们要知道Redis是什么，他是为解决什么样的问题而出现的。&lt;/p&gt;
 &lt;p&gt;   Redis常被描述为一种常驻内存的的持续性的key_value存储。我认为这样描述有失精准，Redis的确是将所有数据存储在内存中，它也的确持续性的写入磁盘，但他绝不仅是简单的key_value存储。认识到这个偏见非常重要，否则你用它解决的问题就会大大变少。&lt;/p&gt;
 &lt;p&gt;事实上Redis发布了五种不同的数据结构，只有一种是典型的key_value结构。理解这五种结构，他们如何工作，相应的内嵌方法，以及根据他们如何建模才是重中之重。首先，&lt;/p&gt;
 &lt;p&gt;让我们理清数据结构的用途吧。&lt;/p&gt;
 &lt;p&gt;如果我们打算使用数据结构的概念到这个关联世界中，我们首先想到的就是数据库的一种简单数据结构——表（tables）.表是一种既复杂又很灵活的结构。几乎所有的东西都可以用表来模拟，存储。然而他也并非没有缺点。因为并非所有的东西都像我们想的那样简单。如果我们用到的结构就是这种特殊的，无法用普遍方法解决的话怎么办呐？&lt;/p&gt;
 &lt;p&gt;对特殊的问题应用特殊的数据结构。我们编码不就是这样吗？你不会为每一条数据使用哈希表，你自然也不会用一个标量变量。对我来说，这就是Redis的用途。如果你是跟scalars,lists,hashes,或者sets打交道，为什么不把他们存储为这种形式呢。&lt;/p&gt;
 &lt;p&gt;基本模块:&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;1，数据库&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;Redis也有你所熟悉的数据库的概念，一个数据库包含一系列数据。数据库的经典用途就是将一个应用的所有数据组合在一起，将它与其他的应用分离开。&lt;/p&gt;
 &lt;p&gt;在Redis里，数据库被简单地用一个数字来识别，比如用0来表示默认的数据库。你过你想换一个不同的数据库，可以在命令行里使用  &lt;em&gt;select&lt;/em&gt;命令。比如：  &lt;em&gt;select1.
&lt;/em&gt;Redis会回复OK 。表示你修改成功。如果想换回来，只需要输入  &lt;em&gt;select0&lt;/em&gt; 即可。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;2,命令行，Keys 和 Values&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;   因为Redis不仅仅是key_value存储服务，而且Redis的五种数据结构至少有一个key和一个value.这样我们理解key_value就显得尤为重要了。&lt;/p&gt;
 &lt;p&gt;Keys是你识别一段数据的依据。我们以后会经常跟keys打交道，但现在，你只需了解一个key大概是长这样就可以了：  &lt;em&gt;user：leto&lt;/em&gt; .我们可以猜测这是一个用户名为leto的用户信息。冒号没有任何特殊意义，只是作为一个分隔符。&lt;/p&gt;
 &lt;p&gt;Values 代表与keys相关联的实际信息。他们可以是任何东西。可以是字符串，整数，甚至序列化对象（JSON,XML等）。对Redis来说，不管他们是什么格式，不过是一系列的字节而已。注意不同的驱动会处理不同格式的对象，所以本书我们只讨论字符串，整数以及JSON。&lt;/p&gt;
 &lt;p&gt;好了，现在开始动手。输入以下命令：&lt;/p&gt;
 &lt;p&gt;  &lt;em&gt;set  users:leto ‘{“name”:”leto”,”planet”:”dune”,”likes”:[“spice”]}’&lt;/em&gt;&lt;/p&gt;
 &lt;p&gt;这是Redis最基本的操作。首先是set 命令，后边是两个参数。第一个是要设定的keys参数，第二个是values参数。许多命令（并非全部）是只有一个key参数。那如何获取数据呢，如下：&lt;/p&gt;
 &lt;p&gt;  &lt;em&gt;get users:leto   &lt;br /&gt;
&lt;/em&gt;    现在可以自己尝试下其他的组合。Keys和values是最基本的概念，而get和set是操作他们最简单的方式。&lt;/p&gt;
 &lt;p&gt;    &lt;strong&gt;       3，查询&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;由上文我们可以看到，对于Redis而言，keys代表一切，而values无法查询到任何东西。比如：上文中，我们无法通过属性planet 的dune 值查询到任何东西。&lt;/p&gt;
 &lt;p&gt;许多人认为这将导致很多不便。因为我们知道数据查询要求灵活，强大，而Redis的方法显得有些原始，不切实际。不要为这点耿耿于怀。记住，Redis不是一种万能的方法。查询的限制是Redis本身具有的。&lt;/p&gt;
 &lt;p&gt;       &lt;strong&gt;4，内存和持久化&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;我们之前提过Redis是常驻内存的持久化存储。Redis会依据有多少keys改变而将相应的数据库输出到磁盘。默认配置，如果有超过1000个keys改变，Redis每60秒做一次存储。&lt;/p&gt;
 &lt;p&gt;同时，Redis还有append模式。当一个key改变时，磁盘上的append_only_file会相应更新。有些情况下会丢失60秒的数据的代价来换取性能，当然，这会导致一些硬件或者软件的问题。有些情况下这个代价是无法接受的。Redis将选择权交给我们。第六章的时候，还会有第三种选项，将持续性交给slave进程处理。&lt;/p&gt;
 &lt;p&gt;Redis将所有数据存储在内存里，最明显的代价就是：占据太多RAM，而这仍然是服务器硬件中最贵的部分。&lt;/p&gt;
 &lt;p&gt;我觉得有些开发者可能忘了数据所占的空间其实不大。莎士比亚的全集才仅占不到5.5M的内存。而且，其他的解决方案无非是通过不断IO或者大量消耗CPU，也是得不偿失的。所以除非是存储非常大的多媒体文件，内存方面真不是问题。&lt;/p&gt;
 &lt;p&gt;Redis的确是支持虚拟内存的。但是这个特点已被证实是个败笔，不被推荐。&lt;/p&gt;
 &lt;p&gt;（提示：5.5M的莎士比亚全集可以被压缩为2M。虽然Redis不提供自动压缩功能，但是因为它把values看做字节，所以对此数据进行压缩是非常可行的。）&lt;/p&gt;
 &lt;p&gt;      &lt;strong&gt;  5，标题串联&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;     &lt;/strong&gt;最后我想把所有的小标题串联起来。特别是，查询限制，数据结构，Redis的内存存储方式。&lt;/p&gt;
 &lt;p&gt;     当你把这些东西结合起来的时候，就会得出一个灰常牛逼的结果：速度。一些人可能会想，“当然了，一切都在内存中必须快啊”。这只是一部分而已。Redis优于其他解决方案的真正原因是他的特殊的数据结构。&lt;/p&gt;
 &lt;p&gt;     有多快？这取决于很多因素——所用的命令，数据类型，等等。Redis的性能趋向于每秒以万记甚至以十万计数。你可以运行 redis_benchmark (与redis-server，redis-cli同一文件夹下)来测试。&lt;/p&gt;
 &lt;p&gt;    以上这些是非常重要的因为它会影响你以后将如何使用Redis。有SQL使用背景的开发者趋向于减少访问数据库的次数。这对于任何系统来说都是一个好建议，包括Redis。但是，由于我们经常跟简单的数据结构打交道，我们也需要多次访问才能达到目的。刚开始我们可能不适应，但对比以前的方法这种代价还是值得的。&lt;/p&gt;
 &lt;p&gt;            &lt;strong&gt;6，小结&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;尽管我们没怎么实际操作Redis，但我们已经了解了很多必要的知识。可能有些地方还不是很清楚，不要紧，接下来的章节你可能会不经意间发现答案。&lt;/p&gt;
 &lt;p&gt;本章重要内容如下：&lt;/p&gt;
 &lt;p&gt;.key是识别value数据的一个字符串标示。&lt;/p&gt;
 &lt;p&gt;.对Redis而言，value只是一系列字节，不管是何种格式。&lt;/p&gt;
 &lt;p&gt;.Redis有五种特殊的数据结构。&lt;/p&gt;
 &lt;p&gt;.综上所述，Redis即快又易用。但并不适合所有场合。&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;       &lt;strong&gt;第二章   数据结构&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;   &lt;/strong&gt;接下来我们开始学习五种数据结构。我们会解释每一种数据结构，涉及到的方法，以及它使用的场景。&lt;/p&gt;
 &lt;p&gt;迄今为止我们还没有接触数据结构的概念。当我们使用“set”命令的时候，Redis怎么会知道我们使用哪种数据结构呢？其实每条命令都是针对特定的一种数据结构。例如，当你使用“set”的时候，针对的就是string这种数据结构。，当你使用“hset”的时候就是针对hash。&lt;/p&gt;
 &lt;p&gt;各种数据结构详细的方法本书就不再一一列举，感兴趣的可以自行查阅手册。&lt;/p&gt;
 &lt;p&gt;不过，任何时候，你都可以用“flushdb”来清除所有数据。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;1，       Strings&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;Strings是Redis中最基本的数据结构。当你想到key_value对的时候，正是String结构。不要被他的名字迷惑，value值可以是任何形式。&lt;/p&gt;
 &lt;p&gt;我们已经见过常用的形式了。下面的形式是我们以后会经常用到的：&lt;/p&gt;
 &lt;p&gt;  &lt;em&gt;Setusers:leto ‘{“name”:leto,”palnet”:dune,”likes”:[“spice”]}’&lt;/em&gt;&lt;/p&gt;
 &lt;p&gt;另外，Redis提供一些普遍的操作方法。例如，   &lt;em&gt;strlen&amp;lt;key&amp;gt;&lt;/em&gt; 用于获取某个key对应的value的长度；  &lt;em&gt;getrange&amp;lt;key&amp;gt; &amp;lt;start&amp;gt;&amp;lt;end&amp;gt;
&lt;/em&gt;返回value对应范围的值；  &lt;em&gt;append &amp;lt;key&amp;gt;&amp;lt;value&amp;gt;&lt;/em&gt;将value加到对应的value值后面。&lt;/p&gt;
 &lt;p&gt;示例如下：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="http://blog.csdn.net"&gt;&lt;/img&gt;  &lt;br /&gt;
&lt;/p&gt;
 &lt;p&gt;&lt;/p&gt;
 &lt;p&gt;现在，你也许会说，很好，但是这也没什么用啊。你不能有意义的拉出JSON中的值以及附加value值啊。的确，本节内容仅仅是讲解一些命令，尤其是对于string的。&lt;/p&gt;
 &lt;p&gt;前面的时候我们说过Redis是不关心values值的形式的。这句话大部分情况下是正确的。然而，有些针对String的命令对value的类型还是敏感的。例如  &lt;em&gt;incr,incrby,decr,decrby.&lt;/em&gt;示例如下：&lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="http://blog.csdn.net"&gt;&lt;/img&gt;  &lt;br /&gt;
&lt;/p&gt;
 &lt;p&gt;&lt;/p&gt;
 &lt;p&gt;试一下 incr users:leto,会返回一个错误。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;2, Hashes&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;    &lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;

 &lt;div&gt;
    作者：u012327100 发表于2014-11-3 14:05:52   &lt;a href="http://blog.csdn.net/u012327100/article/details/40740141"&gt;原文链接&lt;/a&gt;
&lt;/div&gt;
 &lt;div&gt;
    阅读：72 评论：0   &lt;a href="http://blog.csdn.net/u012327100/article/details/40740141#comments" target="_blank"&gt;查看评论&lt;/a&gt;
&lt;/div&gt;

&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/51611-redis-%E7%BB%8F%E5%85%B8-the</guid>
      <pubDate>Mon, 03 Nov 2014 22:05:52 CST</pubDate>
    </item>
    <item>
      <title>几个经典案例，告诉你如何用“去库存”思想盈利</title>
      <link>https://itindex.net/detail/48026-%E7%BB%8F%E5%85%B8-%E5%91%8A%E8%AF%89-%E5%BA%93%E5%AD%98</link>
      <description>&lt;p&gt;  &lt;img alt="&amp;#24211;&amp;#23384;" height="300" src="http://www.tmtpost.com/wp-content/uploads/2014/02/139207938020.jpg" title="&amp;#24211;&amp;#23384;" width="452"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;互联网发展至今，“  &lt;a href="http://www.tmtpost.com/tag/%e9%95%bf%e5%b0%be%e7%90%86%e8%ae%ba" target="_blank" title="&amp;#26597;&amp;#30475; &amp;#38271;&amp;#23614;&amp;#29702;&amp;#35770; &amp;#20013;&amp;#30340;&amp;#20840;&amp;#37096;&amp;#25991;&amp;#31456;"&gt;长尾理论&lt;/a&gt;”已经被反复验证，悬舞认为这一理论是最具互联网思维特性的，在行业中可否找到那条值钱的尾巴往往是互联网世界盈利的王道。&lt;/p&gt;
 &lt;p&gt;“长尾理论”，简言之即摒弃流行聚焦后更大容量的市场，变“鸡肋”为宝。互联网不推崇头部资源的稀缺价值，弱化了时空的非此即彼，如果说传统企业是以渠道为王，构建等级，不可逾越的话，那么互联网企业则是以流量为王，铲平等级，一马平川。  &lt;strong&gt;因此，互联网世界盈利的关键不是头部的优越感，而是尾部的长度。在悬舞看来，尾巴的长度主要取决于两个方面，即行业市场容量的大小和大众个性化需求的强弱。&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;&lt;/strong&gt;下面，悬舞将详述一些用“去库存”思想（即抓住行业长尾切入市场）的灵敏企业和模式，做一次回顾和分析：&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;亚马逊/当当网：书籍尾巴的长度&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;图书出版市场规模的日益庞大自是不必多说，而读书对于人成长的意义更是被从小灌输。在教育普及的前提下，不同阶层不同社会角色的人都会有自己的可读之书，感兴趣之书，因此，在图书资源充足的情况下，阅读的个性化是人在选择书籍时的鲜明特点。互联网打破地域局限，不需要考虑售书架展示空间的巨大限制，彻底改变了图书的售卖方式，可以充分满足个体的读书需求，也增加了整体的阅读总量，也就是书籍尾巴的长度增长明显。因此不管是亚马逊还是国内的当当网，最初都是运用书籍长尾的巨大价值来构建自己的  &lt;a href="http://www.tmtpost.com/tag/electronic%ef%bc%8dbusiness" target="_blank" title="&amp;#26597;&amp;#30475; &amp;#30005;&amp;#21830; &amp;#20013;&amp;#30340;&amp;#20840;&amp;#37096;&amp;#25991;&amp;#31456;"&gt;电商&lt;/a&gt;王国。&lt;/p&gt;
 &lt;p&gt;在亚马逊网上书店成千上万的商品书中，一小部分畅销书占据总销量的一半，而另外绝大部分的书虽然个别销量小，但凭借种类的繁多可以积少成多而占据总销量的另一半。一个前亚马逊公司员工精辟地概述了公司的“长尾”本质：我们所卖的那些过去根本卖不动的书比我们所卖的那些过去可以卖得动的书多得多。长尾现象或者说长尾效应，警示我们“二八定律”在互联网世界里的光彩褪色。&lt;/p&gt;
 &lt;p&gt;同样的长尾也塑造了当当网。这条尾巴不但对于书籍有价值，也带来了其他商品销售的价值联动。按照某电商行业观察者“东哥解读电商”的观点，图书电商平台可以吸收优质的在线客户。图书用户通常都是高价值的用户，当当超过50%的在线市场份额，意味着一半线上买书的用户都绕不过当当网。这种大比例用户的使用粘性让当当在其他百货零售电商布局上轻松不少。&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;出境游尾单平台：旅游尾巴的长度&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;排除掉尾单陷阱的因素，旅游尾单是指一个团队马上发团，但突然有几个人因事不能随团出发，为了不影响团期而临时以低廉的价格招徕游客应急充数。如果团位尚未收满，商家根据最后不同剩余时间，将会进行相当大幅度的降价来吸引消费者来快速购买。&lt;/p&gt;
 &lt;p&gt;随着新《旅游法》的出台，以往通过强制购物、擅自增加自费项目等隐性方式赚钱的旅行社纷纷调高旅游产品的价格，于是货品积压成了不少旅行社亟待解决的问题。同时，伴随着人民币的持续升值，出境游的性价比凸显。2013年4月25日，中国旅游研究院在京发布《中国出境旅游发展年度报告2013》显示，人口红利与政策红利推动出境旅游规模持续扩展，中国已经成为世界第一大出境旅游消费国。而最新的官方数据亦显示春节黄金周国人出境游意愿高涨，首次超过跨省游。同时，2014年将是OTA移动端市场井喷的一年，也为last minute的概念添了一把好柴。就如同某OTA巨头近期大肆推广的那句广告词的后半部分“说走就走”，边旅行边规划的旅行方式会日益流行。&lt;/p&gt;
 &lt;p&gt;因此，依照悬舞之前所阐释的关于决定尾巴长度的两个主要因素市场容量大小和个性化需求强弱的衡量标准，出境游尾巴的长度值得期待。一边是旅游货品的积压，一边是国人出境游情绪的持续爆发，“说走就走”的背后是商机的应运而生。于是我们看到“来来会”，“爱旅行”“明天去旅行”“麦途”等出境游库存特卖平台的疯狂逐鹿。在“旅游尾单”平台上，用户将会以远低于市场水平的价格进行订购，旅行社可以快速消化剩余库存，从整条线路产品来看也能达到效益最大化。&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;唯品会：时尚零售尾巴的长度&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;传统时尚零售行业由于长期存在信息不对称的状况，导致了巨大的商品溢价空间，也推高了消费者的消费成本，同时形成了过季产品的大量积压，这是传统时尚零售业面临的顽疾。唯品会是一家专门经营大幅折扣名牌商品的B2C企业，它执行的闪购模式其实并不复杂，核心就是帮助品牌商处理过季尾货，同时在互联网上利用限时特卖的方式，刺激和调动消费者的冲动型消费。&lt;/p&gt;
 &lt;p&gt;因为专营折扣商品，唯品会一度被业内人士诟病为清理库存的下水道，而其实时尚零售库存价值巨大。定位于时尚的行业有两大特点不容忽视，一个是产品的个性化特别强，一个是产品的时效性特别强，用时尚衡量商品，一方面导致过时产品容易惨遭“淘汰”厄运，另一方面个性化的时尚选择让过时产品也有可能咸鱼翻身，在质量过硬的条件下，平民消费者对于时尚零售折扣产品还是会产生极大的个性化需求。&lt;/p&gt;
 &lt;p&gt;唯品会定位于品牌特卖，除了填补了为有时尚化个性需求的消费者提供集中打折商品的市场空白，同时还为众多时尚品牌商提供了一个体面地处理库存的平台，从而保证了货源的足够供给，真正是将时尚的两大特性运用精到。2012年，中国服装品牌的库存危机浮出水面，品牌供应商和唯品会之间的互利共赢关系更加紧密。而更为重要的是，时尚零售业的库存问题本就是一个常态问题，一个品牌从设计、采购、生产、流通的时间很长，一般需要12-18个月，周期如此长，因此库存会永远存在，这就意味着处理时尚零售尾单是一个巨大的市场。可以说，唯品会选择“时尚品牌特卖”这片蓝海是其成功的关键起步。创立于2008年的唯品会，成立5年多来实现了爆炸式的增长，从上市破发受质疑到现在被业界称为“中概股之王”，唯品会可以说是中国最不可思议的电商之一。&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;   &lt;a href="http://www.tmtpost.com/tag/%e4%bd%99%e9%a2%9d%e5%ae%9d" target="_blank" title="&amp;#26597;&amp;#30475; &amp;#20313;&amp;#39069;&amp;#23453; &amp;#20013;&amp;#30340;&amp;#20840;&amp;#37096;&amp;#25991;&amp;#31456;"&gt;余额宝&lt;/a&gt;：理财尾巴的长度&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;余额宝最近在电视媒体上打出的广告是5000万人都在使用的货币基金。而单在马年春节的半个月内，其用户量就增长了过千万。截止2014年2月6日，余额宝公布的数据是6100万，这种像疾风般的增长速度，实在令人感慨理财的尾巴到底有多长。2014年1月初，天弘基金发布了余额宝用户的各项趣味特征数据，截至2013年年末，余额宝规模为1853亿元，用户共计4303万户，用户平均年龄仅28岁，人均持有金额为4307元。&lt;/p&gt;
 &lt;p&gt;自2013年6月13日上线以来，余额宝就被称为“屌丝理财神器”，不但对银行业产生了不小震动，而且让互联网金融特别是货币基金（简称货基）为越来越多人熟知和热衷。这些令人羡煞的成绩都得益于阿里深知理财的长尾就是平民屌丝的钱袋子。2013年12月底，央行数据统计居民个人储蓄存款总量45万亿元。其中超过16万亿元为活期存款，在利率市场化没有完成之前，互联网金融的理财长尾将有巨大的发挥空间。这时候谁越早培养屌丝的互联网理财习惯，谁就在抓住这条长尾上具备很大优势。而对于淘宝端运作的驾轻就熟，使得阿里本身就具备很好的平民基础，可以说正是平民的钱袋子最初养富了阿里，对于如何吸纳屌丝的钱袋子阿里有非常丰富的实战经验。而另一方面，随着人均可支配收入的日益增加与传统投资渠道存在的长期平民歧视之间不可调和的矛盾，也使得阿里的屌丝理财战略一经推出就天时地利人和，进而引发其爆发式的增长。&lt;/p&gt;
 &lt;p&gt;同时，余额宝风头正劲也必然引发业内的巨大争议，有业界人士就开始对其流动性管理提出质疑，悬舞在这里不想过多评价这些评论的对错或是偏颇与否，只是或许我们应该换一个角度来思考余额宝的历史意义。在悬舞看来，余额宝开启民智的功能远大过它的理财功能。余额宝从众多理财工具当中挑选最容易被屌丝认识和接受的风险较小的货币基金来开启互联网金融的大幕，让更多人了解手中现金的投资功能和价值，逐渐学习和实践家庭资产配置的合理方式，这一教育意义才是理财长尾越来越具有持久价值的关键。所谓“授人以鱼不如授人以渔”，可能余额宝本身有很多缺点和巨大的发展瓶颈，但即便这款理财工具退出历史舞台，它对于屌丝理财意识的觉醒，才真正促成理财这条长尾越来越具备深挖价值。&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;网络自制剧：关键词尾巴的长度&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;前段时间读到过一篇《视频流媒体 Netflix 的七万多种影视风格》的文章，其中有两段论述悬舞印象特别深刻，摘下来和众位分享：&lt;/p&gt;
 &lt;blockquote&gt;  &lt;p&gt;“Netflix 将影视剧分类到 76897 种微风格下。什么是微风格？顾名思义，即，区别细微的风格。必须提起的一点是，纯粹定义微风格的话，其总量远超 76897，只不过很多风格下还没有填入影视剧，也许是因为目前还不存在这样的影视剧，也许是 Netflix 还没有收集到这样的影视剧。”&lt;/p&gt;
  &lt;p&gt;“当 Netflix 对海量影片进行如此细致的分类，对每部影片所涉及的各种元素进行如此详细的标签、归档，Netflix 想要搞明白用户到底喜欢什么样的影视剧的时候，工作就变得容易太多了。Netflix 甚至可能比用户自己都更明白用户为什么会喜欢一部影片。”&lt;/p&gt;&lt;/blockquote&gt;
 &lt;p&gt;所以我们才看到曾经靠DVD 租赁业务起家的 Netflix 在转型做视频流媒体之后，靠着自己对于微风格的精准把握，拍出了像《纸牌屋》这样可以叫板传统影视剧制作巨头的成功作品。&lt;/p&gt;
 &lt;p&gt;在悬舞看来，微风格的属性就是长尾关键词。和关键词相比，长尾关键词单个搜索量极少，且搜索导入流量并不稳定。但由于越长的搜索关键词越精准，转化为网站产品客户的概率比网站目标关键词高很多。对大中型行业网站来说，长尾关键词流量总和不容忽视。&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;“长尾关键词”产生的基础是网站要具有涵盖所涉及行业的规模内容，没有足够的规模内容被搜索引擎收录索引，就无法形成长尾持续产生的机制，很难从搜索引擎获得持续、规模的长尾流量。&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;这就如悬舞在论述开头所说，尾巴的长度首先取决于行业市场容量的大小。2013年作为国内网络自制剧发力凶猛的一年，却仍然处在粗放式的发展阶段，视频巨头们应该逐渐摒弃掉此前因国内大型视频网站烧版权成本太高从而退其次搞自制剧控成本的心态，而真正认识到通过规模内容的生产和细分化、个性化长尾关键词的挖掘，精确导入高流量用户的巨大价值，就如同Netflix创造的“纸牌屋”奇迹。当然，也许《纸牌屋》只是一例个案，但唯一不变的是关键词长尾的价值，谁真正搞明白了它的打法，谁就可能成为下一个赢家。&lt;/p&gt;
 &lt;p&gt;絮叨了半天，其实悬舞想表达的是：&lt;/p&gt;
 &lt;blockquote&gt;  &lt;p&gt;你见，或者不见长尾&lt;/p&gt;
  &lt;p&gt;长尾就在那里&lt;/p&gt;
  &lt;p&gt;不悲不喜&lt;/p&gt;
  &lt;p&gt; &lt;/p&gt;
  &lt;p&gt;你念，或者不念长尾&lt;/p&gt;
  &lt;p&gt;长尾价值就在那里&lt;/p&gt;
  &lt;p&gt;不来不去&lt;/p&gt;
  &lt;p&gt; &lt;/p&gt;
  &lt;p&gt;你爱或者不爱长尾&lt;/p&gt;
  &lt;p&gt;机会就在那里&lt;/p&gt;
  &lt;p&gt;不增不减&lt;/p&gt;
  &lt;p&gt;你跟，或者不跟长尾&lt;/p&gt;
  &lt;p&gt;长尾的手就在你的手里&lt;/p&gt;
  &lt;p&gt;不舍不弃&lt;/p&gt;
  &lt;p&gt; &lt;/p&gt;
  &lt;p&gt;来长尾怀里&lt;/p&gt;
  &lt;p&gt;或者&lt;/p&gt;
  &lt;p&gt;让长尾住进你的心里&lt;/p&gt;
  &lt;p&gt;默然　相爱&lt;/p&gt;
  &lt;p&gt;寂静　欢喜&lt;/p&gt;&lt;/blockquote&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>互联网 创业 行业 余额宝 投稿</category>
      <guid isPermaLink="true">https://itindex.net/detail/48026-%E7%BB%8F%E5%85%B8-%E5%91%8A%E8%AF%89-%E5%BA%93%E5%AD%98</guid>
      <pubDate>Tue, 11 Feb 2014 08:29:10 CST</pubDate>
    </item>
    <item>
      <title>推荐系统经典论文文献及业界应用</title>
      <link>https://itindex.net/detail/47213-%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F-%E7%BB%8F%E5%85%B8-%E8%AE%BA%E6%96%87</link>
      <description>&lt;p&gt; &lt;/p&gt;
 &lt;h2&gt;Survey方面的文章及资料&lt;/h2&gt;
 &lt;ol&gt;
  &lt;li&gt;Adomavicius G, Tuzhilin A.    &lt;strong&gt;Toward the next generation of recommender systems: A survey of the state-of-the-art and possible extensions&lt;/strong&gt;[J]. Knowledge and Data Engineering, IEEE Transactions on, 2005, 17(6): 734-749. 2005年的state-of-the-art的推荐综述，按照content-based, CF, Hybrid的分类方法进行组织，并介绍了推荐引擎设计时需要关注的特性指标，内容非常全。&lt;/li&gt;
  &lt;li&gt;Marlin B.    &lt;strong&gt;Collaborative filtering: A machine learning perspective&lt;/strong&gt;[D]. University of Toronto, 2004. 从传统机器学习的分类角度来介绍推荐算法，有一定机器学习背景的人来看该文章的话， 会觉得写得通俗易懂&lt;/li&gt;
  &lt;li&gt;Koren Y, Bell R.   &lt;strong&gt; Advances in collaborative filtering[M]//Recommender Systems Handbook&lt;/strong&gt;. Springer US, 2011: 145-186.  RSs Handbook中专门讲述协同过滤的一章，其中对近年协同过滤的一些重要突破进行了介绍，包括因式分解，时间相关推荐，基于近邻的推荐以及多种方法的融合，内部不多，但其中引用的论文值得细看&lt;/li&gt;
  &lt;li&gt;Su X, Khoshgoftaar T M.    &lt;strong&gt;A survey of collaborative filtering techniques&lt;/strong&gt;[J]. Advances in artificial intelligence, 2009, 2009: 4. 协同过滤的篇survey， 按照memory-base, model-based, hybrid分类方法介绍各种协同过滤方法及评价标准，并在其中给出基于netflix数据进行评估的效果对比&lt;/li&gt;
  &lt;li&gt;Koren Y, Bell R, Volinsky C.    &lt;strong&gt;Matrix factorization techniques for recommender systems&lt;/strong&gt;[J]. Computer, 2009, 42(8): 30-37.  主要集中在因式分解实现协同过滤方法，如果看完   &lt;strong&gt;Advances in collaborative filtering[M]//Recommender Systems Handbook&lt;/strong&gt;的话，这篇文章就没有必要再看了&lt;/li&gt;
  &lt;li&gt;Pazzani M J, Billsus D.   &lt;strong&gt; Content-based recommendation systems&lt;/strong&gt;[M]//The adaptive web. Springer Berlin Heidelberg, 2007: 325-341.从宏观上介绍content-based的策略架构&lt;/li&gt;
&lt;/ol&gt;
 &lt;h2&gt;Content-based方法&lt;/h2&gt;
 &lt;p&gt;content-based方法非常依赖于特定领域item的特征提取及处理，例如音乐推荐或是关键词推荐中很多细节内容信息处理过程都是不一样的，故这里仅列了content-based综述类的几篇文章。&lt;/p&gt;
 &lt;ol&gt;
  &lt;li&gt;Pazzani M J, Billsus D.   &lt;strong&gt; Content-based recommendation systems&lt;/strong&gt;[M]//The adaptive web. Springer Berlin Heidelberg, 2007: 325-341.从宏观上介绍content-based的策略架构&lt;/li&gt;
  &lt;li&gt;Lops P, de Gemmis M, Semeraro G.    &lt;strong&gt;Content-based recommender systems: State of the art and trends&lt;/strong&gt;[M]//Recommender Systems Handbook. Springer US, 2011: 73-105. RS Handbook中专门介绍content-based 算法的章节&lt;/li&gt;
  &lt;li&gt;Jannach D, Zanker M, Felfernig A, et al.   &lt;strong&gt; Content-based recommendation&lt;/strong&gt;   [M] Charpter 3 Recommender systems: an introduction[M]. Cambridge University Press, 2010.&lt;/li&gt;
&lt;/ol&gt;
 &lt;h2&gt;Collaborative Filtering方法&lt;/h2&gt;
 &lt;h4&gt;Neighbourhood Based Methods&lt;/h4&gt;
 &lt;ol&gt;
  &lt;li&gt;Sarwar B, Karypis G, Konstan J, et al.   &lt;strong&gt; Item-based collaborative filtering recommendation algorithms&lt;/strong&gt;[C]//Proceedings of the 10th international conference on World Wide Web. ACM, 2001: 285-295. KNN进行item-based推荐的经典文章，其中也介绍了多种相似度度量标准&lt;/li&gt;
  &lt;li&gt;Linden G, Smith B, York J.   &lt;strong&gt; Amazon. com recommendations: Item-to-item collaborative filtering&lt;/strong&gt;[J]. Internet Computing, IEEE, 2003, 7(1): 76-80. 经典的亚马逊item-based算法的文章&lt;/li&gt;
  &lt;li&gt;Gionis A, Indyk P, Motwani R.    &lt;strong&gt;Similarity search in high dimensions via hashing&lt;/strong&gt;[C]//VLDB. 1999, 99: 518-529.  LSH&lt;/li&gt;
  &lt;li&gt;Bell R M, Koren Y.    &lt;strong&gt;Scalable collaborative filtering with jointly derived neighborhood interpolation weights&lt;/strong&gt;[C]//Data Mining, 2007. ICDM 2007. Seventh IEEE International Conference on. IEEE, 2007: 43-52.&lt;/li&gt;
  &lt;li&gt;Indyk P, Motwani R.    &lt;strong&gt;Approximate nearest neighbors: towards removing the curse of dimensionality&lt;/strong&gt;[C]//Proceedings of the thirtieth annual ACM symposium on Theory of computing. ACM, 1998: 604-613. LSH&lt;/li&gt;
  &lt;li&gt;Buhler J.   &lt;strong&gt; Efficient large-scale sequence comparison by locality-sensitive hashing&lt;/strong&gt;[J]. Bioinformatics, 2001, 17(5): 419-428. LSH应用&lt;/li&gt;
&lt;/ol&gt;
 &lt;h4&gt;Model Based Methods&lt;/h4&gt;
 &lt;ol&gt;
  &lt;li&gt; Koren Y, Bell R, Volinsky C.   &lt;strong&gt; Matrix factorization techniques for recommender systems&lt;/strong&gt;[J]. Computer, 2009, 42(8): 30-37.主要集中在因式分解实现协同过滤方法，如果看完   &lt;strong&gt;Advances in collaborative filtering[M]//Recommender Systems Handbook&lt;/strong&gt;的话，这篇文章就没有必要再看了&lt;/li&gt;
  &lt;li&gt;Singh A P, Gordon G J.    &lt;strong&gt;A unified view of matrix factorization models[M]//Machine Learning and Knowledge Discovery in Databases&lt;/strong&gt;. Springer Berlin Heidelberg, 2008: 358-373.&lt;/li&gt;
&lt;/ol&gt;
 &lt;h4&gt;Hybrid Methods&lt;/h4&gt;
 &lt;ol&gt;
  &lt;li&gt;Koren Y.    &lt;strong&gt;Factorization meets the neighborhood: a multifaceted collaborative filtering model&lt;/strong&gt;[C]//Proceedings of the 14th ACM SIGKDD international conference on Knowledge discovery and data mining. ACM, 2008: 426-434. 因式分解与Neighbour-based方法融合&lt;/li&gt;
  &lt;li&gt;Burke R.    &lt;strong&gt;Hybrid recommender systems: Survey and experiments&lt;/strong&gt;[J]. User modeling and user-adapted interaction, 2002, 12(4): 331-370.&lt;/li&gt;
  &lt;li&gt;Burke R.    &lt;strong&gt;Hybrid recommender systems: Survey and experiments&lt;/strong&gt;[J]. User modeling and user-adapted interaction, 2002, 12(4): 331-370. 介绍了多种推荐算法进行融合的框架&lt;/li&gt;
&lt;/ol&gt;
 &lt;h2&gt;推荐系统工业界应用&lt;/h2&gt;
 &lt;ol&gt;
  &lt;li&gt;Netflix：   &lt;a href="http://www.199it.com/archives/139346.html"&gt;Netflix视频推荐的背后：算法知道你想看什么&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Netflix：   &lt;a href="http://pan.baidu.com/share/link?shareid=2246534064&amp;uk=1493671608"&gt;Netflix Recommendations Beyond the 5 Stars&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Hulu：   &lt;a href="http://pan.baidu.com/share/link?shareid=2296326349&amp;uk=1493671608"&gt;Recommender System Algorithm and Architecture-项亮&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Youtube：Davidson J, Liebald B, Liu J, et al.    &lt;strong&gt;The YouTube video recommendation system&lt;/strong&gt;[C]//Proceedings of the fourth ACM conference on Recommender systems. ACM, 2010: 293-296.  Youtube推荐系统中的主要算法。 百度关键词搜索推荐系统对其进行了优化， 实现了任意类型的级联二部图推荐。 具体内容可参见博文：   &lt;a href="http://semocean.com/google-youtube-%E7%94%B5%E5%BD%B1%E6%8E%A8%E8%8D%90%E7%AE%97%E6%B3%95/"&gt; google youtube 电影推荐算法&lt;/a&gt;， 以及百度关键词搜索推荐级联二部图实现&lt;/li&gt;
  &lt;li&gt;豆瓣：    &lt;a href="http://pan.baidu.com/share/link?shareid=2051081290&amp;uk=1493671608"&gt;个性化推荐系统的几个问题_豆瓣网王守崑&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;豆瓣：   &lt;a href="http://pan.baidu.com/share/link?shareid=2080953601&amp;uk=1493671608"&gt;阿稳_寻路推荐_豆瓣&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;豆瓣：   &lt;a href="http://pan.baidu.com/share/link?shareid=2088071106&amp;uk=1493671608"&gt;豆瓣在推荐领域的实践与思考&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;百分点：   &lt;a href="http://pan.baidu.com/share/link?shareid=2093525794&amp;uk=1493671608"&gt;量化美-时尚服饰搭配引擎&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;weibo及考拉FM：   &lt;a href="http://pan.baidu.com/share/link?shareid=2129225473&amp;uk=1493671608"&gt;停不下来的推荐实践_陈开江&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;阿里：   &lt;a href="http://pan.baidu.com/share/link?shareid=2144224118&amp;uk=1493671608"&gt;天猫双11推荐技术应用&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;阿里：   &lt;a href="http://pan.baidu.com/share/link?shareid=2173369320&amp;uk=1493671608"&gt;淘宝推荐系统&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;当当：   &lt;a href="http://pan.baidu.com/share/link?shareid=2178876559&amp;uk=1493671608"&gt;当当网搜索和推荐_庄洪波&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;土豆：   &lt;a href="http://pan.baidu.com/share/link?shareid=2184436735&amp;uk=1493671608"&gt;个性化视频推荐系统土豆_明洪涛&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;360：   &lt;a href="http://pan.baidu.com/share/link?shareid=2191353241&amp;uk=1493671608"&gt;360推荐系统实践-杨浩&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;盛大：   &lt;a href="http://pan.baidu.com/share/link?shareid=2218376965&amp;uk=1493671608"&gt;推荐系统实战与效果提升之道-陈运文&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;盛大：   &lt;a href="http://pan.baidu.com/share/link?shareid=2228144324&amp;uk=1493671608"&gt;智能推荐系统的开发与应用-陈运文&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
 &lt;h2&gt;推荐系统书籍&lt;/h2&gt;
 &lt;ol&gt;
  &lt;li&gt;Segaran T.    &lt;strong&gt;Programming collective intelligence: building smart web 2.0 applications&lt;/strong&gt;[M]. O’Reilly Media, 2007.寓教于乐的一本入门教材，附有可以直接动手实践的toy级别代码&lt;/li&gt;
  &lt;li&gt;Shapira B.    &lt;strong&gt;Recommender systems handbook&lt;/strong&gt;[M]. Springer, 2011.  推荐系统可做枕头，也应该放在枕边的书籍，看了半本多。如果将该书及其中的参考文献都看完并理解，那恭喜你，你已经对这个领域有深入理解了&lt;/li&gt;
  &lt;li&gt;Jannach D, Zanker M, Felfernig A, et al.   &lt;strong&gt; Recommender systems: an introduction&lt;/strong&gt;[M]. Cambridge University Press, 2010.  可以认为是2010年前推荐系统论文的综述集合&lt;/li&gt;
  &lt;li&gt;Celma O.    &lt;strong&gt;Music recommendation and discovery&lt;/strong&gt;[M]. Springer, 2010. 主要内容集中在音乐推荐，领域非常专注于音乐推荐，包括选取的特征，评测时如何考虑音乐因素&lt;/li&gt;
  &lt;li&gt;   &lt;strong&gt;Word sense disambiguation: Algorithms and applications&lt;/strong&gt;[M]. Springer Science+ Business Media, 2006. 如果涉及到关键词推荐，或是文本推荐， 则可以查阅该书&lt;/li&gt;
&lt;/ol&gt;
 &lt;p&gt;P.S. 想对某个领域或是工具有深入了解，可以找一本该行业的XX HandBook满怀勇气与无畏细心看完，然后就会对这个领域有一定（较深）了解，当然如果手头有相关项目同步进行，治疗效果更好^_^&lt;/p&gt;
 &lt;h2&gt;推荐系统工具&lt;/h2&gt;
 &lt;ol&gt;
  &lt;li&gt;   &lt;a href="http://mahout.apache.org/"&gt;Mahout&lt;/a&gt;：基于hadoop的机器学习，数据挖掘，推荐系统开源工具。我厂的超低版本haodop集群居然不支持Mahout，想跑个Mahout还要进行移植，郁闷。。。该死！！&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://scikit-learn.org/stable/"&gt;scikit-learn&lt;/a&gt;：基于python的机器学习，数据挖掘库， 方便好用，适合数据量较小的调研任务，不过，一切不支持大数据的机器学习算法，（一定程度上）都是耍流氓。。。。&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://www.cs.waikato.ac.nz/ml/weka/"&gt;weka&lt;/a&gt;：经典的数据挖掘工具， java版本&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://www.r-project.org/"&gt;R&lt;/a&gt;：R语言&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://glaros.dtc.umn.edu/gkhome/views/cluto"&gt;Cluto&lt;/a&gt;：聚类工具，集成了较多聚类算法及相似度度量方法&lt;/li&gt;
  &lt;li&gt;   &lt;a href="http://rapidminer.com/products/rapidminer-studio/"&gt;RapidMiner&lt;/a&gt;：没用过，但据说使用量非常大&lt;/li&gt;
&lt;/ol&gt;
 &lt;h2&gt;国内推荐系统站点&lt;/h2&gt;
 &lt;ol&gt;
  &lt;li&gt;   &lt;a href="http://www.resyschina.com/"&gt;http://www.resyschina.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
 &lt;p&gt;因为我一直认为推荐系统不是一个独立的学科，它很多技术都是直接来自于机器学习，数据挖掘和信息检索（特别是文本相关的搜索推荐），所以以下也整理了一些之前工作及工作之余看过，了解过，或者准备看的这方面的资料&lt;/p&gt;
 &lt;h2&gt;数据挖掘资料&lt;/h2&gt;
 &lt;ol&gt;
  &lt;li&gt;Han J, Kamber M, Pei J.    &lt;strong&gt;Data mining: concepts and techniques&lt;/strong&gt;[M]. Morgan kaufmann, 2006. 数据挖掘方面的handbook，教科书类型，虽然厚，却通俗易懂(再次提醒，要了解某一领域，找本该领域的啥啥handbook耐心认真读完，那你基本对该领域有一定认识了)&lt;/li&gt;
  &lt;li&gt;Chakrabarti S.    &lt;strong&gt;Mining the Web: Discovering knowledge from hypertext data&lt;/strong&gt;[M]. Morgan Kaufmann, 2003.介绍了一个搜索引擎中的大部分技术，包括spider，索引建立，内部的机器学习算法，信息检索，而且非常具有实用性，我在百度商务搜索部开发的spider，就是按照其中的架构设计开发的&lt;/li&gt;
  &lt;li&gt;Liu B.   &lt;strong&gt; Web data mining: exploring hyperlinks, contents, and usage data&lt;/strong&gt;[M]. Springer, 2007. 如果说    &lt;strong&gt;Mining the Web: Discovering knowledge from hypertext data&lt;/strong&gt;更偏web mining更偏整体，工程的话，这本书就更偏策略，两本都读过的话，你对搜索引擎中的数据挖掘算法的了解，就比较全面了&lt;/li&gt;
  &lt;li&gt;Wu X, Kumar V, Quinlan J R, et al.   &lt;strong&gt; Top 10 algorithms in data mining&lt;/strong&gt;[J]. Knowledge and Information Systems, 2008, 14(1): 1-37. 专门将2006年评选出来的10大数据挖掘算法拎了出来讲讲&lt;/li&gt;
  &lt;li&gt;Rajaraman A, Ullman J D.    &lt;strong&gt;Mining of massive datasets&lt;/strong&gt;[M]. Cambridge University Press, 2012.介绍如何使用hadoop进行数据挖掘，如果有hadoop环境则非常实用&lt;/li&gt;
  &lt;li&gt;Feldman R, Sanger J.    &lt;strong&gt;The text mining handbook: advanced approaches in analyzing unstructured data&lt;/strong&gt;[M]. Cambridge University Press, 2007.文本挖掘的handbook&lt;/li&gt;
&lt;/ol&gt;
 &lt;h2&gt;机器学习资料&lt;/h2&gt;
 &lt;ol&gt;
  &lt;li&gt;Tom M    &lt;strong&gt;Mitchell,Machine Learning&lt;/strong&gt;, McGraw-Hill Science/Engineering/Mat, 1997，非常早起的机器学习书籍，非常适合入门， 浅显易懂， 但对于工业界应用， 只能说是Toy级别的算法。&lt;/li&gt;
  &lt;li&gt;Bishop C M, Nasrabadi N M.    &lt;strong&gt;Pattern recognition and machine learning&lt;/strong&gt;[M]. New York: springer, 2006. 进阶型的书籍，对每种算法都有较为具体的理论介绍&lt;/li&gt;
  &lt;li&gt;课程： 机器学习（Stanford-&amp;gt;Andrew Ng）   &lt;a href="http://v.163.com/special/opencourse/machinelearning.html" target="_top"&gt;http://v.163.com/special/opencourse/machinelearning.html&lt;/a&gt;，大名鼎鼎的Andrew Ng的机器学习公开课，网易上字幕版本；配合   &lt;a href="http://cs229.stanford.edu/"&gt;课程stanford cs229对应的handout及习题&lt;/a&gt;一起学习效果更好&lt;/li&gt;
&lt;/ol&gt;
 &lt;h2&gt;信息检索&lt;/h2&gt;
 &lt;ol&gt;
  &lt;li&gt;Agirre, Eneko, and Philip Glenny Edmonds, eds.    &lt;strong&gt;Word sense disambiguation: Algorithms and applications&lt;/strong&gt;. Vol. 33. Springer Science+ Business Media, 2006.&lt;/li&gt;
  &lt;li&gt;Manning C D, Raghavan P, Schütze H.   &lt;strong&gt; Introduction to information retrieval&lt;/strong&gt;[M]. Cambridge: Cambridge University Press, 2008.&lt;/li&gt;
  &lt;li&gt;MOFFAT A A, Bell T C.    &lt;strong&gt;Managing gigabytes: compressing and indexing documents and images&lt;/strong&gt;[M]. Morgan Kaufmann, 1999.一本很老的介绍搜索引擎的书了，不过09年的时候看还是被震撼到了，书中各种变着戏法使用几十M内存处理上G数据，感觉非常牛叉。&lt;/li&gt;
&lt;/ol&gt;
 &lt;p&gt;百度关键词工具介绍参见：  &lt;a href="http://support.baidu.com/product/fc/4.html?castk=24b18bi7062c720d0d596"&gt;http://support.baidu.com/product/fc/4.html?castk=24b18bi7062c720d0d596&lt;/a&gt;&lt;/p&gt;
 &lt;p&gt;也可关注我的微博：   &lt;a href="http://weibo.com/dustinsea" target="_blank"&gt; weibo.com/dustinsea&lt;/a&gt;&lt;/p&gt;
 &lt;p&gt;或是直接访问： http://semocean.com&lt;/p&gt;
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>Uncategorized</category>
      <guid isPermaLink="true">https://itindex.net/detail/47213-%E6%8E%A8%E8%8D%90%E7%B3%BB%E7%BB%9F-%E7%BB%8F%E5%85%B8-%E8%AE%BA%E6%96%87</guid>
      <pubDate>Tue, 24 Dec 2013 11:12:22 CST</pubDate>
    </item>
    <item>
      <title>Android开发面试题 71道经典题目</title>
      <link>https://itindex.net/detail/46052-android-%E5%BC%80%E5%8F%91-%E9%9D%A2%E8%AF%95</link>
      <description>&lt;p&gt;  &lt;strong&gt;注：本文来自“安卓巴士”&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;  &lt;strong&gt;   &lt;br /&gt;
&lt;/strong&gt;&lt;/p&gt;
 &lt;p&gt;Android面试题&lt;/p&gt;
1.        下列哪些语句关于内存回收的说明是正确的? (b ) A、
 程序员必须创建一个线程来释放内存 &lt;br /&gt;
  B、 内存回收程序负责释放无用内存  &lt;br /&gt;
  C、 内存回收程序允许程序员直接释放内存  &lt;br /&gt;
  D、 内存回收程序可以在指定的时间释放内存对象  &lt;br /&gt;
2.        下面异常是属于Runtime Exception 的是（abcd）(多选) 
     A、ArithmeticException  &lt;br /&gt;
      B、IllegalArgumentException  &lt;br /&gt;
      C、NullPointerException  &lt;br /&gt;
      D、BufferUnderflowException  &lt;br /&gt;
3.         Math.round(11.5)等于多少(). Math.round(-11.5)等于多少(c). c 
   A、11 ,-11   B、11 ,-12   C、12 ,-11   D、12 ,-12 &lt;br /&gt;
4.        下列程序段的输出结果是：（b ） &lt;br /&gt;
     void complicatedexpression_r(){ &lt;br /&gt;
     int x=20, y=30; &lt;br /&gt;
     boolean b; &lt;br /&gt;
     b=x&amp;gt;50&amp;amp;&amp;amp;y&amp;gt;60||x&amp;gt;50&amp;amp;&amp;amp;y&amp;lt;-60||x&amp;lt;-50&amp;amp;&amp;amp;y&amp;gt;60||x&amp;lt;-50&amp;amp;&amp;amp;y&amp;lt;-60; &lt;br /&gt;
     System.out.println(b); &lt;br /&gt;
     } &lt;br /&gt;
     A、true  B、false  C、1  D、011.activity5.        对一些资源以及状态的操作保存，最好是保存在生命周期的哪个函数中进行(d)   A、onPause()  B、onCreate()   C、 onResume()   D、onStart() &lt;br /&gt;
6.        Intent传递数据时，下列的数据类型哪些可以被传递（abcd）(多选) 
      A、Serializable  B、charsequence  C、Parcelable  D、Bundle &lt;br /&gt;
7.        android 中下列属于Intent的作用的是(c)  A、实现应用程序间的数据共享 &lt;br /&gt;
  B、是一段长的生命周期，没有用户界面的程序，可以保持应用在后台运行，而不会因为切换页面而消失 &lt;br /&gt;
  C、可以实现界面间的切换，可以包含动作和动作数据，连接四大组件的纽带 &lt;br /&gt;
  D、处理一个应用程序整体性的工作 &lt;br /&gt;
8.        下列属于SAX解析xml文件的优点的是(b)      A、将整个文档树在内存中，便于操作，支持删除，修改，重新排列等多种功能 &lt;br /&gt;
      B、不用事先调入整个文档，占用资源少 &lt;br /&gt;
      C、整个文档调入内存，浪费时间和空间 &lt;br /&gt;
      D、不是长久驻留在内存，数据不是持久的，事件过后，若没有保存数据，数据就会 &lt;br /&gt;
  消失 &lt;br /&gt;
9.         下面的对自定style的方式正确的是（a）    A、 &amp;lt;resources&amp;gt; &lt;br /&gt;
       &amp;lt;style name=&amp;quot;myStyle&amp;quot;&amp;gt; &lt;br /&gt;
                            &amp;lt;itemname=&amp;quot;android:layout_width&amp;quot;&amp;gt;fill_parent&amp;lt;/item&amp;gt; &lt;br /&gt;
                     &amp;lt;/style&amp;gt; &lt;br /&gt;
&amp;lt;/resources&amp;gt; &lt;br /&gt;
     B、 &amp;lt;style name=&amp;quot;myStyle&amp;quot;&amp;gt; &lt;br /&gt;
                            &amp;lt;itemname=&amp;quot;android:layout_width&amp;quot;&amp;gt;fill_parent&amp;lt;/item&amp;gt; &lt;br /&gt;
   &amp;lt;/style&amp;gt; &lt;br /&gt;
     C、 &amp;lt;resources&amp;gt; &lt;br /&gt;
                            &amp;lt;itemname=&amp;quot;android:layout_width&amp;quot;&amp;gt;fill_parent&amp;lt;/item&amp;gt; &lt;br /&gt;
  &amp;lt;/resources&amp;gt; &lt;br /&gt;
     D、 &amp;lt;resources&amp;gt; &lt;br /&gt;
                            &amp;lt;stylename=&amp;quot;android:layout_width&amp;quot;&amp;gt;fill_parent&amp;lt;/style&amp;gt; &lt;br /&gt;
  &amp;lt;/resources&amp;gt; &lt;br /&gt;
10.       在android中使用Menu时可能需要重写的方法有（ac）。(多选) 
     A、onCreateOptionsMenu()  &lt;br /&gt;
  B、onCreateMenu() &lt;br /&gt;
  C、onOptionsItemSelected() &lt;br /&gt;
  D、onItemSelected() &lt;br /&gt;
11.      在SQL Server Management Studio 中运行下列T-SQL语句，其输出值（c）。 SELECT
 @@IDENTITY   &lt;br /&gt;
     A、      可能为0.1 &lt;br /&gt;
     B、       可能为3 &lt;br /&gt;
     C、      不可能为-100 &lt;br /&gt;
     D、      肯定为0 &lt;br /&gt;
12.     在SQL Server 2005中运行如下T-SQL语句，假定SALES表中有多行数据，执行查询之     后的结果是（d）。 BEGIN
 TRANSACTION A &lt;br /&gt;
       Update SALES Set qty=30 WHERE qty&amp;lt;30 &lt;br /&gt;
        BEGIN TRANSACTION B &lt;br /&gt;
              Update SALES Set qty=40 WHEREqty&amp;lt;40 &lt;br /&gt;
              Update SALES Set qty=50 WHEREqty&amp;lt;50 &lt;br /&gt;
              Update SALES Set qty=60 WHEREqty&amp;lt;60 &lt;br /&gt;
        COMMIT　TRANSACTION B &lt;br /&gt;
        COMMIT TRANSACTION A &lt;br /&gt;
A、SALES表中qty列最小值大于等于30 &lt;br /&gt;
B、SALES表中qty列最小值大于等于40 &lt;br /&gt;
C、SALES表中qty列的数据全部为50 &lt;br /&gt;
D、SALES表中qty列最小值大于等于60 &lt;br /&gt;
13.      在android中使用SQLiteOpenHelper这个辅助类时，可以生成一个数据库，并可以对数据库版本进行管理的方法可以是(ab) 
   A、getWriteableDatabase() &lt;br /&gt;
B、getReadableDatabase() &lt;br /&gt;
C、getDatabase() &lt;br /&gt;
D、getAbleDatabase() &lt;br /&gt;
14.     android 关于service生命周期的onCreate()和onStart()说法正确的是(ad)(多选题) 
   A、当第一次启动的时候先后调用onCreate()和onStart()方法 &lt;br /&gt;
    B、当第一次启动的时候只会调用onCreate()方法 &lt;br /&gt;
    C、如果service已经启动，将先后调用onCreate()和onStart()方法 &lt;br /&gt;
D、如果service已经启动，只会执行onStart()方法，不在执行onCreate()方法 &lt;br /&gt;
15.     下面是属于GLSurFaceView特性的是(abc)(多选) A、管理一个surface，这个surface就是一块特殊的内存，能直接排版到android的视图 &lt;br /&gt;
    view上。 &lt;br /&gt;
B、管理一个EGL
 display，它能让opengl把内容渲染到上述的surface上。 &lt;br /&gt;
C、让渲染器在独立的线程里运作，和UI线程分离。 &lt;br /&gt;
D、可以直接从内存或者DMA等硬件接口取得图像数据 &lt;br /&gt;
16.     下面在AndroidManifest.xml文件中注册BroadcastReceiver方式正确的(a) 
      A、&amp;lt;receiver android:name=&amp;quot;NewBroad&amp;quot;&amp;gt; &lt;br /&gt;
                     &amp;lt;intent-filter&amp;gt; &lt;br /&gt;
                            &amp;lt;action   &lt;br /&gt;
                   android:name=&amp;quot;android.provider.action.NewBroad&amp;quot;/&amp;gt; &lt;br /&gt;
                &amp;lt;action&amp;gt; &lt;br /&gt;
                     &amp;lt;/intent-filter&amp;gt; &lt;br /&gt;
              &amp;lt;/receiver&amp;gt; &lt;br /&gt;
     B、&amp;lt;receiver android:name=&amp;quot;NewBroad&amp;quot;&amp;gt; &lt;br /&gt;
                     &amp;lt;intent-filter&amp;gt; &lt;br /&gt;
                   android:name=&amp;quot;android.provider.action.NewBroad&amp;quot;/&amp;gt; &lt;br /&gt;
                     &amp;lt;/intent-filter&amp;gt; &lt;br /&gt;
              &amp;lt;/receiver&amp;gt; &lt;br /&gt;
     C、&amp;lt;receiver android:name=&amp;quot;NewBroad&amp;quot;&amp;gt; &lt;br /&gt;
                     &amp;lt;action   &lt;br /&gt;
                  android:name=&amp;quot;android.provider.action.NewBroad&amp;quot;/&amp;gt; &lt;br /&gt;
             &amp;lt;action&amp;gt; &lt;br /&gt;
              &amp;lt;/receiver&amp;gt; &lt;br /&gt;
     D、&amp;lt;intent-filter&amp;gt; &lt;br /&gt;
         &amp;lt;receiver android:name=&amp;quot;NewBroad&amp;quot;&amp;gt; &lt;br /&gt;
                           &amp;lt;action&amp;gt; &lt;br /&gt;
                   android:name=&amp;quot;android.provider.action.NewBroad&amp;quot;/&amp;gt; &lt;br /&gt;
                  &amp;lt;action&amp;gt; &lt;br /&gt;
                     &amp;lt;/receiver&amp;gt; &lt;br /&gt;
&amp;lt;/intent-filter&amp;gt; &lt;br /&gt;
17.     关于ContenValues类说法正确的是(a)     A、他和Hashtable比较类似，也是负责存储一些名值对，但是他存储的名值对当中的 &lt;br /&gt;
        名是String类型，而值都是基本类型 &lt;br /&gt;
     B、他和Hashtable比较类似，也是负责存储一些名值对，但是他存储的名值对当中的 &lt;br /&gt;
        名是任意类型，而值都是基本类型 &lt;br /&gt;
     C、他和Hashtable比较类似，也是负责存储一些名值对，但是他存储的名值对当中的 &lt;br /&gt;
        名，可以为空，而值都是String类型      &lt;br /&gt;
     D、他和Hashtable比较类似，也是负责存储一些名值对，但是他存储的名值对当中 &lt;br /&gt;
        的名是String类型，而值也是String类型 &lt;br /&gt;
18.     我们都知道Hanlder是线程与Activity通信的桥梁,如果线程处理不当，你的机器就会变得越慢，那么线程销毁的方法是(a) 
     A、onDestroy()  &lt;br /&gt;
      B、onClear() &lt;br /&gt;
      C、onFinish()  &lt;br /&gt;
      D、onStop() &lt;br /&gt;
19.     下面退出Activity错误的方法是（c）       A、finish() &lt;br /&gt;
         B、抛异常强制退出 &lt;br /&gt;
       C、System.exit() &lt;br /&gt;
       D、onStop() &lt;br /&gt;
20.     下面属于android的动画分类的有(ab)(多项)       A、Tween  B、Frame
 C、Draw D、Animation  &lt;br /&gt;
21.     下面关于Android dvm的进程和Linux的进程,应用程序的进程说法正确的是(d) 
       A、DVM指dalivk的虚拟机.每一个Android应用程序都在它自己的进程中运行,不一定拥有一个独立 的Dalvik虚拟机实例.而每一个DVM都是在Linux中的一个进程,所以说可以认为是同一个概念. &lt;br /&gt;
        B、DVM指dalivk的虚拟机.每一个Android应用程序都在它自己的进程中运行,不一定拥有一个独立的Dalvik虚拟机实例.而每一个DVM不一定都是在Linux 中的一个进程,所以说不是一个概念. &lt;br /&gt;
        C、DVM指dalivk的虚拟机.每一个Android应用程序都在它自己的进程中运行,都拥有一个独立的Dalvik虚拟机实例.而每一个DVM不一定都是在Linux 中的一个进程,所以说不是一个概念. &lt;br /&gt;
        D、DVM指dalivk的虚拟机.每一个Android应用程序都在它自己的进程中运行,都拥有一个独立的 Dalvik虚拟机实例.而每一个DVM都是在Linux 中的一个进程,所以说可以认为是同一个概念. &lt;br /&gt;
22.       Android项目工程下面的assets目录的作用是什么bA、放置应用到的图片资源。 &lt;br /&gt;
B、主要放置多媒体等数据文件 &lt;br /&gt;
C、放置字符串，颜色，数组等常量数据 &lt;br /&gt;
D、放置一些与UI相应的布局文件，都是xml文件 &lt;br /&gt;
23.       关于res/raw目录说法正确的是(a)A、
 这里的文件是原封不动的存储到设备上不会转换为二进制的格式 &lt;br /&gt;

 &lt;p&gt;
B、这里的文件是原封不动的存储到设备上会转换为二进制的格式&lt;/p&gt;
C、 这里的文件最终以二进制的格式存储到指定的包中 &lt;br /&gt;

 &lt;p&gt;
D、这里的文件最终不会以二进制的格式存储到指定的包中&lt;/p&gt;
24.      下列对android NDK的理解正确的是(abcd )A、
 NDK是一系列工具的集合 &lt;br /&gt;
B、 NDK 提供了一份稳定、功能有限的 API 头文件声明。 &lt;br /&gt;
C、 使 “Java+C” 的开发方式终于转正，成为官方支持的开发方式 &lt;br /&gt;
D、 NDK 将是 Android 平台支持 C 开发的开端 &lt;br /&gt;
 &lt;br /&gt;
二．填空题 &lt;br /&gt;
25.      android中常用的四个布局是framlayout，linenarlayout，relativelayout和tablelayout。26. 
     android 的四大组件是activiey，service，broadcast和contentprovide。27. 
     java.io包中的objectinputstream和objectoutputstream类主要用于对对象(Object)的读写。28. 
     android 中service的实现方法是：startservice和bindservice。29. 
     activity一般会重载7个方法用来维护其生命周期，除了onCreate(),onStart(),onDestory()   外还有onrestart,onresume,onpause,onstop。30. 
     android的数据存储的方式sharedpreference,文件,SQlite,contentprovider,网络。31.     当启动一个Activity并且新的Activity执行完后需要返回到启动它的Activity来执行
 的回调函数是startActivityResult()。32.     请使用命令行的方式创建一个名字为myAvd,sdk版本为2.2,sd卡是在d盘的根目录下,名字为scard.img， 并指定屏幕大小HVGA.____________________________________。33. 
      程序运行的结果是：_____good and gbc__________。 
   public classExample{  &lt;br /&gt;
　　String str=new String(&amp;quot;good&amp;quot;);  &lt;br /&gt;
　　char[]ch={&amp;apos;a&amp;apos;,&amp;apos;b&amp;apos;,&amp;apos;c&amp;apos;};  &lt;br /&gt;
　　public static void main(String args[]){  &lt;br /&gt;
　　　　Example ex=new Example();  &lt;br /&gt;
　　　　ex.change(ex.str,ex.ch);  &lt;br /&gt;
　　　　System.out.print(ex.str+&amp;quot; and &amp;quot;);  &lt;br /&gt;
　　　　Sytem.out.print(ex.ch);  &lt;br /&gt;
　　}  &lt;br /&gt;
　　public void change(String str,char ch[]){  &lt;br /&gt;
　　　　str=&amp;quot;test ok&amp;quot;;  &lt;br /&gt;
　　　　ch[0]=&amp;apos;g&amp;apos;;  &lt;br /&gt;
　　}  &lt;br /&gt;
}  &lt;br /&gt;
 &lt;br /&gt;
34.      在android中，请简述jni的调用过程。(8分)1)安装和下载Cygwin，下载
 Android NDK &lt;br /&gt;
  2)在ndk项目中JNI接口的设计 &lt;br /&gt;
  3)使用C/C++实现本地方法 &lt;br /&gt;
  4)JNI生成动态链接库.so文件 &lt;br /&gt;
  5)将动态链接库复制到java工程，在java工程中调用，运行java工程即可 &lt;br /&gt;
 &lt;br /&gt;
35.     简述Android应用程序结构是哪些?（7分）Android应用程序结构是： &lt;br /&gt;
  Linux Kernel(Linux内核)、Libraries(系统运行库或者是c/c++核心库)、Application   &lt;br /&gt;
  Framework(开发框架包)、Applications  (核心应用程序) &lt;br /&gt;
 &lt;br /&gt;
36.     请继承SQLiteOpenHelper实现：(10分)   1）.创建一个版本为1的“diaryOpenHelper.db”的数据库， &lt;br /&gt;
   2）.同时创建一个 “diary” 表（包含一个_id主键并自增长，topic字符型100 &lt;br /&gt;
       长度， content字符型1000长度） &lt;br /&gt;
    3）.在数据库版本变化时请删除diary表，并重新创建出diary表。 &lt;br /&gt;
 &lt;br /&gt;
publicclass DBHelper  extends SQLiteOpenHelper{ &lt;br /&gt;
 &lt;br /&gt;
       public final static String DATABASENAME =&amp;quot;diaryOpenHelper.db&amp;quot;; &lt;br /&gt;
       public final static int DATABASEVERSION =1; &lt;br /&gt;
 &lt;br /&gt;
       //创建数据库 &lt;br /&gt;
       public DBHelper(Context context,Stringname,CursorFactory factory,int version) &lt;br /&gt;
       { &lt;br /&gt;
              super(context, name, factory,version); &lt;br /&gt;
       } &lt;br /&gt;
       //创建表等机构性文件 &lt;br /&gt;
       public void onCreate(SQLiteDatabase db) &lt;br /&gt;
       { &lt;br /&gt;
              String sql =&amp;quot;create tablediary&amp;quot;+ &lt;br /&gt;
                                   &amp;quot;(&amp;quot;+ &lt;br /&gt;
                                   &amp;quot;_idinteger primary key autoincrement,&amp;quot;+ &lt;br /&gt;
                                   &amp;quot;topicvarchar(100),&amp;quot;+ &lt;br /&gt;
                                   &amp;quot;contentvarchar(1000)&amp;quot;+ &lt;br /&gt;
                                   &amp;quot;)&amp;quot;; &lt;br /&gt;
              db.execSQL(sql); &lt;br /&gt;
       } &lt;br /&gt;
       //若数据库版本有更新，则调用此方法 &lt;br /&gt;
       public void onUpgrade(SQLiteDatabasedb,int oldVersion,int newVersion) &lt;br /&gt;
       { &lt;br /&gt;
               &lt;br /&gt;
              String sql = &amp;quot;drop table ifexists diary&amp;quot;; &lt;br /&gt;
              db.execSQL(sql); &lt;br /&gt;
              this.onCreate(db); &lt;br /&gt;
       } &lt;br /&gt;
} &lt;br /&gt;
 &lt;br /&gt;
37.     页面上现有ProgressBar控件progressBar，请用书写线程以10秒的的时间完成其进度显示工作。（10分）答案 &lt;br /&gt;
publicclass ProgressBarStu extends Activity { &lt;br /&gt;
 &lt;br /&gt;
       private ProgressBar progressBar = null; &lt;br /&gt;
       protected void onCreate(BundlesavedInstanceState) { &lt;br /&gt;
              super.onCreate(savedInstanceState); &lt;br /&gt;
              setContentView(R.layout.progressbar); &lt;br /&gt;
              //从这到下是关键 &lt;br /&gt;
              progressBar = (ProgressBar)findViewById(R.id.progressBar); &lt;br /&gt;
               &lt;br /&gt;
              Thread thread = new Thread(newRunnable() { &lt;br /&gt;
                      &lt;br /&gt;
                     @Override &lt;br /&gt;
                     public void run() { &lt;br /&gt;
                            int progressBarMax =progressBar.getMax(); &lt;br /&gt;
                            try { &lt;br /&gt;
                                   while(progressBarMax!=progressBar.getProgress()) &lt;br /&gt;
                                   { &lt;br /&gt;
                                           &lt;br /&gt;
                                          intstepProgress = progressBarMax/10; &lt;br /&gt;
                                          intcurrentprogress = progressBar.getProgress(); &lt;br /&gt;
                                          progressBar.setProgress(currentprogress+stepProgress); &lt;br /&gt;
                                          Thread.sleep(1000); &lt;br /&gt;
                                   } &lt;br /&gt;
                                    &lt;br /&gt;
                            } catch(InterruptedException e) { &lt;br /&gt;
                                   // TODO Auto-generatedcatch block &lt;br /&gt;
                                   e.printStackTrace(); &lt;br /&gt;
                            } &lt;br /&gt;
                             &lt;br /&gt;
                     } &lt;br /&gt;
              }); &lt;br /&gt;
               &lt;br /&gt;
              thread.start(); &lt;br /&gt;
 &lt;br /&gt;
              //关键结束 &lt;br /&gt;
       } &lt;br /&gt;
        &lt;br /&gt;
} &lt;br /&gt;
38.        请描述下Activity的生命周期。      必调用的三个方法：onCreate()
 --&amp;gt; onStart() --&amp;gt; onResume()，用AAA表示 &lt;br /&gt;
（1）父Activity启动子Activity，子Actvity退出，父Activity调用顺序如下 &lt;br /&gt;
AAA --&amp;gt; onFreeze() --&amp;gt; onPause() --&amp;gt; onStop() --&amp;gt; onRestart()--&amp;gt; onStart(),onResume() … &lt;br /&gt;
（2）用户点击Home，Actvity调用顺序如下 &lt;br /&gt;
AAA --&amp;gt; onFreeze() --&amp;gt; onPause() --&amp;gt; onStop() -- Maybe --&amp;gt;onDestroy() – Maybe &lt;br /&gt;
（3）调用finish()， Activity调用顺序如下 &lt;br /&gt;
AAA --&amp;gt; onPause() --&amp;gt; onStop() --&amp;gt; onDestroy() &lt;br /&gt;
（4）在Activity上显示dialog，Activity调用顺序如下 &lt;br /&gt;
AAA &lt;br /&gt;
（5）在父Activity上显示透明的或非全屏的activity，Activity调用顺序如下 &lt;br /&gt;
AAA --&amp;gt; onFreeze() --&amp;gt; onPause() &lt;br /&gt;
（6）设备进入睡眠状态，Activity调用顺序如下 &lt;br /&gt;
AAA --&amp;gt; onFreeze() --&amp;gt; onPause() &lt;br /&gt;
39.      如果后台的Activity由于某原因被系统回收了，如何在被系统回收之前保存当前状态？ 
     onSaveInstanceState() &lt;br /&gt;
      当你的程序中某一个Activity A在运行时，主动或被动地运行另一个新的Activity B，这个时候A会执行onSaveInstanceState()。B完成以后又会来找A，这个时候就有两种情况：一是A被回收，二是A没有被回收，被回收的A就要重新调用onCreate()方法，不同于直接启动的是这回onCreate()里是带上了参数savedInstanceState；而没被收回的就直接执行onResume()，跳过onCreate()了。  &lt;br /&gt;
40.       如何将一个Activity设置成窗口的样式。      在AndroidManifest.xml
 中定义Activity的地方一句话android:theme=&amp;quot;@android:style/Theme.Dialog&amp;quot;或android:theme=&amp;quot;@android:style/Theme.Translucent&amp;quot;就变成半透明的 &lt;br /&gt;
41.     如何退出Activity？如何安全退出已调用多个Activity的Application？对于单一Activity的应用来说，退出很简单，直接finish()即可。 &lt;br /&gt;
当然，也可以用killProcess()和System.exit()这样的方法。 &lt;br /&gt;
 &lt;br /&gt;
但是，对于多Activity的应用来说，在打开多个Activity后，如果想在最后打开的Activity直接退出，上边的方法都是没有用的，因为上边的方法都是结束一个Activity而已。 &lt;br /&gt;
当然，网上也有人说可以。 &lt;br /&gt;
就好像有人问，在应用里如何捕获Home键，有人就会说用keyCode比较KEYCODE_HOME即可，而事实上如果不修改framework，根本不可能做到这一点一样。 &lt;br /&gt;
所以，最好还是自己亲自试一下。 &lt;br /&gt;
 &lt;br /&gt;
那么，有没有办法直接退出整个应用呢？ &lt;br /&gt;
在2.1之前，可以使用ActivityManager的restartPackage方法。 &lt;br /&gt;
它可以直接结束整个应用。在使用时需要权限android.permission.RESTART_PACKAGES。 &lt;br /&gt;
注意不要被它的名字迷惑。 &lt;br /&gt;
 &lt;br /&gt;
可是，在2.2，这个方法失效了。 &lt;br /&gt;
在2.2添加了一个新的方法，killBackgroundProcesses()，需要权限android.permission.KILL_BACKGROUND_PROCESSES。 &lt;br /&gt;
可惜的是，它和2.2的restartPackage一样，根本起不到应有的效果。 &lt;br /&gt;
 &lt;br /&gt;
另外还有一个方法，就是系统自带的应用程序管理里，强制结束程序的方法，forceStopPackage()。 &lt;br /&gt;
它需要权限android.permission.FORCE_STOP_PACKAGES。 &lt;br /&gt;
并且需要添加android:sharedUserId=&amp;quot;android.uid.system&amp;quot;属性 &lt;br /&gt;
同样可惜的是，该方法是非公开的，他只能运行在系统进程，第三方程序无法调用。 &lt;br /&gt;
因为需要在Android.mk中添加LOCAL_CERTIFICATE := platform。 &lt;br /&gt;
而Android.mk是用于在Android源码下编译程序用的。 &lt;br /&gt;
 &lt;br /&gt;
从以上可以看出，在2.2，没有办法直接结束一个应用，而只能用自己的办法间接办到。 &lt;br /&gt;
 &lt;br /&gt;
现提供几个方法，供参考： &lt;br /&gt;
 &lt;br /&gt;
1、抛异常强制退出： &lt;br /&gt;
该方法通过抛异常，使程序ForceClose。 &lt;br /&gt;
验证可以，但是，需要解决的问题是，如何使程序结束掉，而不弹出Force Close的窗口。 &lt;br /&gt;
 &lt;br /&gt;
2、记录打开的Activity： &lt;br /&gt;
每打开一个Activity，就记录下来。在需要退出时，关闭每一个Activity即可。 &lt;br /&gt;
 &lt;br /&gt;
3、发送特定广播： &lt;br /&gt;
在需要结束应用时，发送一个特定的广播，每个Activity收到广播后，关闭即可。 &lt;br /&gt;
 &lt;br /&gt;
4、递归退出 &lt;br /&gt;
在打开新的Activity时使用startActivityForResult，然后自己加标志，在onActivityResult中处理，递归关闭。 &lt;br /&gt;
 &lt;br /&gt;
除了第一个，都是想办法把每一个Activity都结束掉，间接达到目的。 &lt;br /&gt;
但是这样做同样不完美。 &lt;br /&gt;
你会发现，如果自己的应用程序对每一个Activity都设置了nosensor，在两个Activity结束的间隙，sensor可能有效了。 &lt;br /&gt;
但至少，我们的目的达到了，而且没有影响用户使用。 &lt;br /&gt;
 &lt;br /&gt;
为了编程方便，最好定义一个Activity基类，处理这些共通问题。  &lt;br /&gt;
42.    请介绍下Android中常用的五种布局。FrameLayout（框架布局），LinearLayout
 （线性布局），AbsoluteLayout（绝对布局），RelativeLayout（相对布局），TableLayout（表格布局） &lt;br /&gt;
43.    请介绍下Android的数据存储方式。一.SharedPreferences方式 &lt;br /&gt;
二.文件存储方式 &lt;br /&gt;
三.SQLite数据库方式 &lt;br /&gt;
四.内容提供器（Content provider）方式 &lt;br /&gt;
五. 网络存储方式 &lt;br /&gt;
44.     请介绍下ContentProvider是如何实现数据共享的。创建一个属于你自己的Content
 provider或者将你的数据添加到一个已经存在的Contentprovider中，前提是有相同数据类型并且有写入Content provider的权限。 &lt;br /&gt;
45.    如何启用Service，如何停用Service。Android中的service类似于windows中的service，service一般没有用户操作界面，它运行于系统中不容易被用户发觉， &lt;br /&gt;
可以使用它开发如监控之类的程序。 &lt;br /&gt;
一。步骤 &lt;br /&gt;
第一步：继承Service类 &lt;br /&gt;
public class SMSService extends Service { } &lt;br /&gt;
第二步：在AndroidManifest.xml文件中的&amp;lt;application&amp;gt;节点里对服务进行配置: &lt;br /&gt;
&amp;lt;service android:name=&amp;quot;.DemoService&amp;quot; /&amp;gt; &lt;br /&gt;
二。Context.startService()和Context.bindService &lt;br /&gt;
服务不能自己运行，需要通过调用Context.startService()或Context.bindService()方法启动服务。这两个方法都可 &lt;br /&gt;
以启动Service，但是它们的使用场合有所不同。 &lt;br /&gt;
1.使用startService()方法启用服务，调用者与服务之间没有关连，即使调用者退出了，服务仍然运行。 &lt;br /&gt;
使用bindService()方法启用服务，调用者与服务绑定在了一起，调用者一旦退出，服务也就终止。 &lt;br /&gt;
2.采用Context.startService()方法启动服务，在服务未被创建时，系统会先调用服务的onCreate()方法， &lt;br /&gt;
接着调用onStart()方法。如果调用startService()方法前服务已经被创建，多次调用startService()方法并 &lt;br /&gt;
不会导致多次创建服务，但会导致多次调用onStart()方法。 &lt;br /&gt;
采用startService()方法启动的服务，只能调用Context.stopService()方法结束服务，服务结束时会调用 &lt;br /&gt;
onDestroy()方法。  &lt;br /&gt;
 &lt;br /&gt;
3.采用Context.bindService()方法启动服务，在服务未被创建时，系统会先调用服务的onCreate()方法， &lt;br /&gt;
接着调用onBind()方法。这个时候调用者和服务绑定在一起，调用者退出了，系统就会先调用服务的onUnbind()方法， &lt;br /&gt;
。接着调用onDestroy()方法。如果调用bindService()方法前服务已经被绑定，多次调用bindService()方法并不会 &lt;br /&gt;
导致多次创建服务及绑定(也就是说onCreate()和onBind()方法并不会被多次调用)。如果调用者希望与正在绑定的服务 &lt;br /&gt;
解除绑定，可以调用unbindService()方法，调用该方法也会导致系统调用服务的onUnbind()--&amp;gt;onDestroy()方法。 &lt;br /&gt;
三。Service的生命周期 &lt;br /&gt;
1.Service常用生命周期回调方法如下： &lt;br /&gt;
 &lt;br /&gt;
onCreate() 该方法在服务被创建时调用，该方法只会被调用一次，无论调用多少次startService()或bindService()方法， &lt;br /&gt;
服务也只被创建一次。 onDestroy()该方法在服务被终止时调用。  &lt;br /&gt;
 &lt;br /&gt;
2. Context.startService()启动Service有关的生命周期方法 &lt;br /&gt;
onStart() 只有采用Context.startService()方法启动服务时才会回调该方法。该方法在服务开始运行时被调用。 &lt;br /&gt;
多次调用startService()方法尽管不会多次创建服务，但onStart() 方法会被多次调用。 &lt;br /&gt;
 &lt;br /&gt;
3. Context.bindService()启动Service有关的生命周期方法 &lt;br /&gt;
onBind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务绑定时被调用， &lt;br /&gt;
当调用者与服务已经绑定，多次调用Context.bindService()方法并不会导致该方法被多次调用。 &lt;br /&gt;
onUnbind()只有采用Context.bindService()方法启动服务时才会回调该方法。该方法在调用者与服务解除绑定时被调用。 &lt;br /&gt;
备注： &lt;br /&gt;
1. 采用startService()启动服务 &lt;br /&gt;
     Intent intent =new Intent(DemoActivity.this, DemoService.class); &lt;br /&gt;
    startService(intent); &lt;br /&gt;
2.Context.bindService()启动 &lt;br /&gt;
    Intent intent =new Intent(DemoActivity.this, DemoService.class); &lt;br /&gt;
   bindService(intent, conn, Context.BIND_AUTO_CREATE); &lt;br /&gt;
   //unbindService(conn);//解除绑定 &lt;br /&gt;
46.    注册广播有几种方式，这些方式有何优缺点？请谈谈Android引入广播机制的用意。  Android广播机制（两种注册方法）  &lt;br /&gt;
在android下，要想接受广播信息，那么这个广播接收器就得我们自己来实现了，我们可以继承BroadcastReceiver，就可以有一个广播接受器了。有个接受器还不够，我们还得重写BroadcastReceiver里面的onReceiver方法，当来广播的时候我们要干什么，这就要我们自己来实现，不过我们可以搞一个信息防火墙。具体的代码： &lt;br /&gt;
 &lt;br /&gt;
public class SmsBroadCastReceiverextends BroadcastReceiver     &lt;br /&gt;
{   &lt;br /&gt;
 &lt;br /&gt;
   @Override   &lt;br /&gt;
   public void onReceive(Context context, Intent intent)    &lt;br /&gt;
   {    &lt;br /&gt;
       Bundle bundle = intent.getExtras();   &lt;br /&gt;
       Object[] object = (Object[])bundle.get(&amp;quot;pdus&amp;quot;);    &lt;br /&gt;
       SmsMessage sms[]=new SmsMessage[object.length];    &lt;br /&gt;
       for(int i=0;i&amp;lt;object.length;i++)   &lt;br /&gt;
       {    &lt;br /&gt;
            sms[0] =SmsMessage.createFromPdu((byte[])object);   &lt;br /&gt;
            Toast.makeText(context, &amp;quot;来自&amp;quot;+sms.getDisplayOriginatingAddress()+&amp;quot;的消息是：&amp;quot;+sms.getDisplayMessageBody(),Toast.LENGTH_SHORT).show(); 
   &lt;br /&gt;
       }    &lt;br /&gt;
       //终止广播，在这里我们可以稍微处理，根据用户输入的号码可以实现短信防火墙。    &lt;br /&gt;
       abortBroadcast();    &lt;br /&gt;
   }    &lt;br /&gt;
       &lt;br /&gt;
}  &lt;br /&gt;
 &lt;br /&gt;
当实现了广播接收器，还要设置广播接收器接收广播信息的类型，这里是信息：android.provider.Telephony.SMS_RECEIVED &lt;br /&gt;
 &lt;br /&gt;
我们就可以把广播接收器注册到系统里面，可以让系统知道我们有个广播接收器。这里有两种，一种是代码动态注册： &lt;br /&gt;
 &lt;br /&gt;
//生成广播处理   &lt;br /&gt;
smsBroadCastReceiver = newSmsBroadCastReceiver();    &lt;br /&gt;
//实例化过滤器并设置要过滤的广播   &lt;br /&gt;
 &lt;br /&gt;
IntentFilter intentFilter = newIntentFilter(&amp;quot;android.provider.Telephony.SMS_RECEIVED&amp;quot;);  &lt;br /&gt;
 &lt;br /&gt;
//注册广播    &lt;br /&gt;
BroadCastReceiverActivity.this.registerReceiver(smsBroadCastReceiver,intentFilter);   &lt;br /&gt;
一种是在AndroidManifest.xml中配置广播 &lt;br /&gt;
 &lt;br /&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot;encoding=&amp;quot;utf-8&amp;quot;?&amp;gt;   &lt;br /&gt;
&amp;lt;manifestxmlns:android=&amp;quot;http://schemas.android.com/apk/res/android&amp;quot;   &lt;br /&gt;
     package=&amp;quot;spl.broadCastReceiver&amp;quot;   &lt;br /&gt;
     android:versionCode=&amp;quot;1&amp;quot;  &lt;br /&gt;
     android:versionName=&amp;quot;1.0&amp;quot;&amp;gt;  &lt;br /&gt;
   &amp;lt;application android:icon=&amp;quot;@drawable/icon&amp;quot;android:label=&amp;quot;@string/app_name&amp;quot;&amp;gt;  &lt;br /&gt;
       &amp;lt;activity android:name=&amp;quot;.BroadCastReceiverActivity&amp;quot;   &lt;br /&gt;
                  android:label=&amp;quot;@string/app_name&amp;quot;&amp;gt;   &lt;br /&gt;
            &amp;lt;intent-filter&amp;gt;   &lt;br /&gt;
                &amp;lt;actionandroid:name=&amp;quot;android.intent.action.MAIN&amp;quot; /&amp;gt;   &lt;br /&gt;
                &amp;lt;categoryandroid:name=&amp;quot;android.intent.category.LAUNCHER&amp;quot; /&amp;gt;   &lt;br /&gt;
            &amp;lt;/intent-filter&amp;gt;   &lt;br /&gt;
       &amp;lt;/activity&amp;gt;   &lt;br /&gt;
            &lt;br /&gt;
       &amp;lt;!--广播注册--&amp;gt;   &lt;br /&gt;
       &amp;lt;receiver android:name=&amp;quot;.SmsBroadCastReceiver&amp;quot;&amp;gt;   &lt;br /&gt;
            &amp;lt;intent-filterandroid:priority=&amp;quot;20&amp;quot;&amp;gt;   &lt;br /&gt;
                &amp;lt;actionandroid:name=&amp;quot;android.provider.Telephony.SMS_RECEIVED&amp;quot;/&amp;gt;   &lt;br /&gt;
            &amp;lt;/intent-filter&amp;gt;   &lt;br /&gt;
       &amp;lt;/receiver&amp;gt;   &lt;br /&gt;
            &lt;br /&gt;
   &amp;lt;/application&amp;gt;   &lt;br /&gt;
       &lt;br /&gt;
   &amp;lt;uses-sdk android:minSdkVersion=&amp;quot;7&amp;quot; /&amp;gt;   &lt;br /&gt;
       &lt;br /&gt;
   &amp;lt;!-- 权限申请 --&amp;gt;   &lt;br /&gt;
   &amp;lt;uses-permissionandroid:name=&amp;quot;android.permission.RECEIVE_SMS&amp;quot;&amp;gt;&amp;lt;/uses-permission&amp;gt;   &lt;br /&gt;
       &lt;br /&gt;
&amp;lt;/manifest&amp;gt;    &lt;br /&gt;
 &lt;br /&gt;
两种注册类型的区别是： &lt;br /&gt;
 &lt;br /&gt;
    1)第一种不是常驻型广播，也就是说广播跟随程序的生命周期。 &lt;br /&gt;
 &lt;br /&gt;
    2)第二种是常驻型，也就是说当应用程序关闭后，如果有信息广播来，程序也会被系统调用自动运行。 &lt;br /&gt;
47.    请解释下在单线程模型中Message、Handler、MessageQueue、Looper之间的关系。Handler简介： &lt;br /&gt;
一个Handler允许你发送和处理Message和Runable对象，这些对象和一个线程的MessageQueue相关联。每一个线程实例和一个单独的线程以及该线程的MessageQueue相关联。当你创建一个新的Handler时，它就和创建它的线程绑定在一起了。这里，线程我们也可以理解为线程的MessageQueue。从这一点上来看，Handler把Message和Runable对象传递给MessageQueue，而且在这些对象离开MessageQueue时，Handler负责执行他们。 &lt;br /&gt;
 &lt;br /&gt;
Handler有两个主要的用途：（1）确定在将来的某个时间点执行一个或者一些Message和Runnable对象。（2）在其他线程（不是Handler绑定线程）中排入一些要执行的动作。 &lt;br /&gt;
 &lt;br /&gt;
Scheduling Message，即（1），可以通过以下方法完成： &lt;br /&gt;
post(Runnable):Runnable在handler绑定的线程上执行，也就是说不创建新线程。 &lt;br /&gt;
postAtTime(Runnable,long): &lt;br /&gt;
postDelayed(Runnable,long): &lt;br /&gt;
sendEmptyMessage(int): &lt;br /&gt;
sendMessage(Message): &lt;br /&gt;
sendMessageAtTime(Message,long): &lt;br /&gt;
sendMessageDelayed(Message,long): &lt;br /&gt;
post这个动作让你把Runnable对象排入MessageQueue,MessageQueue受到这些消息的时候执行他们，当然以一定的排序。sendMessage这个动作允许你把Message对象排成队列，这些Message对象包含一些信息，Handler的hanlerMessage(Message)会处理这些Message.当然，handlerMessage(Message)必须由Handler的子类来重写。这是编程人员需要作的事。 &lt;br /&gt;
 &lt;br /&gt;
当posting或者sending到一个Hanler时，你可以有三种行为：当MessageQueue准备好就处理，定义一个延迟时间，定义一个精确的时间去处理。后两者允许你实现timeout,tick,和基于时间的行为。 &lt;br /&gt;
 &lt;br /&gt;
当你的应用创建一个新的进程时，主线程（也就是UI线程）自带一个MessageQueue，这个MessageQueue管理顶层的应用对象（像activities,broadcast
 receivers等）和主线程创建的窗体。你可以创建自己的线程，并通过一个Handler和主线程进行通信。这和之前一样，通过post和sendmessage来完成，差别在于在哪一个线程中执行这么方法。在恰当的时候，给定的Runnable和Message将在Handler的MessageQueue中被Scheduled。 &lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
Message简介： &lt;br /&gt;
Message类就是定义了一个信息，这个信息中包含一个描述符和任意的数据对象，这个信息被用来传递给Handler.Message对象提供额外的两个int域和一个Object域，这可以让你在大多数情况下不用作分配的动作。 &lt;br /&gt;
尽管Message的构造函数是public的，但是获取Message实例的最好方法是调用Message.obtain(),或者Handler.obtainMessage()方法，这些方法会从回收对象池中获取一个。 &lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
MessageQueue简介： &lt;br /&gt;
这是一个包含message列表的底层类。Looper负责分发这些message。Messages并不是直接加到一个MessageQueue中，而是通过MessageQueue.IdleHandler关联到Looper。 &lt;br /&gt;
你可以通过Looper.myQueue()从当前线程中获取MessageQueue。 &lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
Looper简介： &lt;br /&gt;
Looper类被用来执行一个线程中的message循环。默认情况，没有一个消息循环关联到线程。在线程中调用prepare()创建一个Looper，然后用loop()来处理messages，直到循环终止。 &lt;br /&gt;
 &lt;br /&gt;
大多数和message loop的交互是通过Handler。 &lt;br /&gt;
 &lt;br /&gt;
下面是一个典型的带有Looper的线程实现。 &lt;br /&gt;
  class LooperThread extends Thread { &lt;br /&gt;
      public Handler mHandler; &lt;br /&gt;
       &lt;br /&gt;
      public void run() { &lt;br /&gt;
          Looper.prepare(); &lt;br /&gt;
           &lt;br /&gt;
          mHandler = new Handler() { &lt;br /&gt;
              public voidhandleMessage(Message msg) { &lt;br /&gt;
                  // process incomingmessages here &lt;br /&gt;
              } &lt;br /&gt;
          }; &lt;br /&gt;
           &lt;br /&gt;
          Looper.loop(); &lt;br /&gt;
      } &lt;br /&gt;
  } &lt;br /&gt;
 &lt;br /&gt;
48.       AIDL的全称是什么？如何工作？能处理哪些类型的数据？AIDL的英文全称是Android Interface
 Define Language &lt;br /&gt;
当A进程要去调用B进程中的service时，并实现通信，我们通常都是通过AIDL来操作的 &lt;br /&gt;
A工程： &lt;br /&gt;
首先我们在net.blogjava.mobile.aidlservice包中创建一个RemoteService.aidl文件，在里面我们自定义一个接口，含有方法get。ADT插件会在gen目录下自动生成一个RemoteService.java文件，该类中含有一个名为RemoteService.stub的内部类，该内部类中含有aidl文件接口的get方法。 &lt;br /&gt;
说明一：aidl文件的位置不固定，可以任意 &lt;br /&gt;
然后定义自己的MyService类，在MyService类中自定义一个内部类去继承RemoteService.stub这个内部类，实现get方法。在onBind方法中返回这个内部类的对象，系统会自动将这个对象封装成IBinder对象，传递给他的调用者。 &lt;br /&gt;
其次需要在AndroidManifest.xml文件中配置MyService类，代码如下： &lt;br /&gt;
&amp;lt;!-- 注册服务 --&amp;gt;   &lt;br /&gt;
&amp;lt;service android:name=&amp;quot;.MyService&amp;quot;&amp;gt;  &lt;br /&gt;
  &amp;lt;intent-filter&amp;gt;  &lt;br /&gt;
   &amp;lt;!--  指定调用AIDL服务的ID  --&amp;gt;  &lt;br /&gt;
       &amp;lt;actionandroid:name=&amp;quot;net.blogjava.mobile.aidlservice.RemoteService&amp;quot; /&amp;gt;  &lt;br /&gt;
   &amp;lt;/intent-filter&amp;gt;  &lt;br /&gt;
&amp;lt;/service&amp;gt; &lt;br /&gt;
为什么要指定调用AIDL服务的ID,就是要告诉外界MyService这个类能够被别的进程访问，只要别的进程知道这个ID，正是有了这个ID,B工程才能找到A工程实现通信。 &lt;br /&gt;
说明：AIDL并不需要权限 &lt;br /&gt;
B工程： &lt;br /&gt;
      首先我们要将A工程中生成的RemoteService.java文件拷贝到B工程中，在bindService方法中绑定aidl服务 &lt;br /&gt;
      绑定AIDL服务就是将RemoteService的ID作为intent的action参数。 &lt;br /&gt;
      说明：如果我们单独将RemoteService.aidl文件放在一个包里，那个在我们将gen目录下的该包拷贝到B工程中。如果我们将RemoteService.aidl文件和我们的其他类存放在一起，那么我们在B工程中就要建立相应的包，以保证RmoteService.java文件的报名正确，我们不能修改RemoteService.java文件 &lt;br /&gt;
          bindService(newInten(&amp;quot;net.blogjava.mobile.aidlservice.RemoteService&amp;quot;),serviceConnection, Context.BIND_AUTO_CREATE);  &lt;br /&gt;
      ServiceConnection的onServiceConnected(ComponentName name, IBinderservice)方法中的service参数就是A工程中MyService类中继承了RemoteService.stub类的内部类的对象。 &lt;br /&gt;
49.    请解释下Android程序运行时权限与文件系统权限的区别。运行时权限Dalvik( android授权)  &lt;br /&gt;
文件系统 linux 内核授权 &lt;br /&gt;
 &lt;br /&gt;
50.     系统上安装了多种浏览器，能否指定某浏览器访问指定页面？请说明原由。通过直接发送Uri把参数带过去，或者通过manifest里的intentfilter里的data属性 &lt;br /&gt;
 &lt;br /&gt;
51.    你如何评价Android系统？优缺点。答：Android平台手机 5大优势：  &lt;br /&gt;
一、开放性  &lt;br /&gt;
在优势方面，Android平台首先就是其开发性，开发的平台允许任何移动终端厂商加入到Android联盟中来。显著的开放性可以使其拥有更多的开发者，随着用户和应用的日益丰富，一个崭新的平台也将很快走向成熟。开放性对于Android的发展而言，有利于积累人气，这里的人气包括消费者和厂商，而对于消费者来讲，随大的受益正是丰富的软件资源。开放的平台也会带来更大竞争，如此一来，消费者将可以用更低的价位购得心仪的手机。 &lt;br /&gt;
二、挣脱运营商的束缚  &lt;br /&gt;
在过去很长的一段时间，特别是在欧美地区，手机应用往往受到运营商制约，使用什么功能接入什么网络，几乎都受到运营商的控制。从去年iPhone 上市 ，用户可以更加方便地连接网络，运营商的制约减少。随着EDGE、HSDPA这些2G至3G移动网络的逐步过渡和提升，手机随意接入网络已不是运营商口中的笑谈，当你可以通过手机IM软件方便地进行即时聊天时，再回想不久前天价的彩信和图铃下载业务，是不是像噩梦一样？互联网巨头Google推动的Android终端天生就有网络特色，将让用户离互联网更近。 &lt;br /&gt;
三、丰富的硬件选择  &lt;br /&gt;
这一点还是与Android平台的开放性相关，由于Android的开放性，众多的厂商会推出千奇百怪，功能特色各具的多种产品。功能上的差异和特色，却不会影响到数据同步、甚至软件的兼容，好比你从诺基亚 Symbian风格手机 一下改用苹果 iPhone ，同时还可将Symbian中优秀的软件带到iPhone上使用、联系人等资料更是可以方便地转移，是不是非常方便呢？ &lt;br /&gt;
四、不受任何限制的开发商  &lt;br /&gt;
Android平台提供给第三方开发商一个十分宽泛、自由的环境，不会受到各种条条框框的阻扰，可想而知，会有多少新颖别致的软件会诞生。但也有其两面性，血腥、暴力、情色方面的程序和游戏如可控制正是留给Android难题之一。 &lt;br /&gt;
五、无缝结合的Google应用  &lt;br /&gt;
如今叱诧互联网的Google已经走过10年度历史，从搜索巨人到全面的互联网渗透，Google服务如地图、邮件、搜索等已经成为连接用户和互联网的重要纽带，而Android平台手机将无缝结合这些优秀的Google服务。 &lt;br /&gt;
再说Android的5大不足： &lt;br /&gt;
一、安全和隐私  &lt;br /&gt;
由于手机与互联网的紧密联系，个人隐私很难得到保守。除了上网过程中经意或不经意留下的个人足迹，Google这个巨人也时时站在你的身后，洞穿一切，因此，互联网的深入将会带来新一轮的隐私危机。 &lt;br /&gt;
二、首先开卖Android手机的不是最大运营商  &lt;br /&gt;
众所周知，T-Mobile在23日，于美国纽约发布 了Android首款手机G1。但是在北美市场，最大的两家运营商乃AT&amp;amp;T和Verizon，而目前所知取得Android手机销售权的仅有 T-Mobile和Sprint，其中T-Mobile的3G网络相对于其他三家也要逊色不少，因此，用户可以买账购买G1，能否体验到最佳的3G网络服务则要另当别论了！ &lt;br /&gt;
三、运营商仍然能够影响到Android手机  &lt;br /&gt;
在国内市场，不少用户对购得移动定制机不满，感觉所购的手机被人涂画了广告一般。这样的情况在国外市场同样出现。Android手机的另一发售运营商Sprint就将在其机型中内置其手机商店程序。 &lt;br /&gt;
四、同类机型用户减少  &lt;br /&gt;
在不少手机论坛都会有针对某一型号的子论坛，对一款手机的使用心得交流，并分享软件资源。而对于Android平台手机，由于厂商丰富，产品类型多样，这样使用同一款机型的用户越来越少，缺少统一机型的程序强化。举个稍显不当的例子，现在山寨机泛滥，品种各异，就很少有专门针对某个型号山寨机的讨论和群组，除了哪些功能异常抢眼、颇受追捧的机型以外。 &lt;br /&gt;
五、过分依赖开发商缺少标准配置  &lt;br /&gt;
在使用PC端的Windows Xp系统的时候，都会内置微软Windows Media Player这样一个浏览器程序，用户可以选择更多样的播放器，如Realplay或暴风影音等。但入手开始使用默认的程序同样可以应付多样的需要。在Android平台中，由于其开放性，软件更多依赖第三方厂商，比如Android系统的SDK中就没有内置音乐 播放器，全部依赖第三方开发，缺少了产品的统一性。 &lt;br /&gt;
 &lt;br /&gt;
52.  什么是ANR 如何避免它?  &lt;br /&gt;
　　答：ANR：Application NotResponding，五秒  &lt;br /&gt;
 &lt;br /&gt;
在Android中，活动管理器和窗口管理器这两个系统服务负责监视应用程序的响应。当出现下列情况时，Android就会显示ANR对话框了：  &lt;br /&gt;
 &lt;br /&gt;
　　对输入事件(如按键、触摸屏事件)的响应超过5秒  &lt;br /&gt;
 &lt;br /&gt;
　　意向接受器(intentReceiver)超过10秒钟仍未执行完毕  &lt;br /&gt;
 &lt;br /&gt;
　　Android应用程序完全运行在一个独立的线程中(例如main)。这就意味着，任何在主线程中运行的，需要消耗大量时间的操作都会引发ANR。因为此时，你的应用程序已经没有机会去响应输入事件和意向广播(Intentbroadcast)。  &lt;br /&gt;
 &lt;br /&gt;
　　因此，任何运行在主线程中的方法，都要尽可能的只做少量的工作。特别是活动生命周期中的重要方法如onCreate()和 onResume()等更应如此。潜在的比较耗时的操作，如访问网络和数据库;或者是开销很大的计算，比如改变位图的大小，需要在一个单独的子线程中完成(或者是使用异步请求，如数据库操作)。但这并不意味着你的主线程需要进入阻塞状态已等待子线程结束 -- 也不需要调用Therad.wait()或者Thread.sleep()方法。取而代之的是，主线程为子线程提供一个句柄(Handler)，让子线程在即将结束的时候调用它(xing:可以参看Snake的例子，这种方法与以前我们所接触的有所不同)。使用这种方法涉及你的应用程序，能够保证你的程序对输入保持良好的响应，从而避免因为输入事件超过5秒钟不被处理而产生的ANR。这种实践需要应用到所有显示用户界面的线程，因为他们都面临着同样的超时问题。  &lt;br /&gt;
 &lt;br /&gt;
53.     什么情况会导致Force Close ?如何避免?能否捕获导致其的异常?  &lt;br /&gt;
　　答：一般像空指针啊，可以看起logcat，然后对应到程序中 来解决错误  &lt;br /&gt;
 &lt;br /&gt;
54.     Android本身的api并未声明会抛出异常，则其在运行时有无可能抛出runtime异常，你遇到过吗?诺有的话会导致什么问题?如何解决?  &lt;br /&gt;
55.     简要解释一下activity、 intent 、intent filter、service、Broadcase、BroadcaseReceiver  &lt;br /&gt;
　　答：一个activity呈现了一个用户可以操作的可视化用户界面  &lt;br /&gt;
 &lt;br /&gt;
　　一个service不包含可见的用户界面，而是在后台无限地运行  &lt;br /&gt;
 &lt;br /&gt;
　　可以连接到一个正在运行的服务中，连接后，可以通过服务中暴露出来的借口与其进行通信  &lt;br /&gt;
 &lt;br /&gt;
　　一个broadcast receiver是一个接收广播消息并作出回应的component，broadcastreceiver没有界面  &lt;br /&gt;
 &lt;br /&gt;
　　intent:content provider在接收到ContentResolver的请求时被激活。  &lt;br /&gt;
 &lt;br /&gt;
　　activity, service和broadcast receiver是被称为intents的异步消息激活的。  &lt;br /&gt;
 &lt;br /&gt;
一个intent是一个Intent对象，它保存了消息的内容。对于activity和service来说，它指定了请求的操作名称和待操作数据的URI  &lt;br /&gt;
 &lt;br /&gt;
　　Intent对象可以显式的指定一个目标component。如果这样的话，android会找到这个component(基于manifest文件中的声明)并激活它。但如果一个目标不是显式指定的，android必须找到响应intent的最佳component。  &lt;br /&gt;
 &lt;br /&gt;
　　它是通过将Intent对象和目标的intent filter相比较来完成这一工作的。一个component的intent filter告诉android该component能处理的intent。intent filter也是在manifest文件中声明的。  &lt;br /&gt;
56.     　IntentService有何优点?  &lt;br /&gt;
　　答：IntentService 的好处  &lt;br /&gt;
 &lt;br /&gt;
　　* Acitivity的进程，当处理Intent的时候，会产生一个对应的Service  &lt;br /&gt;
 &lt;br /&gt;
　　* Android的进程处理器现在会尽可能的不kill掉你  &lt;br /&gt;
 &lt;br /&gt;
　　* 非常容易使用  &lt;br /&gt;
 &lt;br /&gt;
57.     横竖屏切换时候activity的生命周期?  &lt;br /&gt;
　　1、不设置Activity的android:configChanges时，切屏会重新调用各个生命周期，切横屏时会执行一次，切竖屏时会执行两次  &lt;br /&gt;
 &lt;br /&gt;
　　2、设置Activity的android:configChanges=&amp;quot;orientation&amp;quot;时，切屏还是会重新调用各个生命周期，切横、竖屏时只会执行一次  &lt;br /&gt;
 &lt;br /&gt;
　　3、设置Activity的android:configChanges=&amp;quot;orientation|keyboardHidden&amp;quot;时，切屏不会重新调用各个生命周期，只会执行onConfigurationChanged方法  &lt;br /&gt;
 &lt;br /&gt;
　　 &lt;br /&gt;
如何将SQLite数据库(dictionary.db文件)与apk文件一起发布?  &lt;br /&gt;
 &lt;br /&gt;
　　解答：可以将dictionary.db文件复制到Eclipse Android工程中的res aw目录中。所有在res aw目录中的文件不会被压缩，这样可以直接提取该目录中的文件。可以将dictionary.db文件复制到res aw目录中  &lt;br /&gt;
 &lt;br /&gt;
58.     如何将打开res aw目录中的数据库文件?  &lt;br /&gt;
　　解答：在Android中不能直接打开res aw目录中的数据库文件，而需要在程序第一次启动时将该文件复制到手机内存或SD卡的某个目录中，然后再打开该数据库文件。复制的基本方法是使用getResources().openRawResource方法获得res aw目录中资源的 InputStream对象，然后将该InputStream对象中的数据写入其他的目录中相应文件中。在Android SDK中可以使用SQLiteDatabase.openOrCreateDatabase方法来打开任意目录中的SQLite数据库文件。  &lt;br /&gt;
 &lt;br /&gt;
59.     Android引入广播机制的用意?  &lt;br /&gt;
　　答：a:从MVC的角度考虑(应用程序内)  &lt;br /&gt;
 &lt;br /&gt;
　其实回答这个问题的时候还可以这样问，android为什么要有那4大组件，现在的移动开发模型基本上也是照搬的web那一套MVC架构，只不过是改了点嫁妆而已。android的四大组件本质上就是为了实现移动或者说嵌入式设备上的MVC架构，它们之间有时候是一种相互依存的关系，有时候又是一种补充关系，引入广播机制可以方便几大组件的信息和数据交互。  &lt;br /&gt;
 &lt;br /&gt;
　　b：程序间互通消息(例如在自己的应用程序内监听系统来电)  &lt;br /&gt;
 &lt;br /&gt;
　　c：效率上(参考UDP的广播协议在局域网的方便性)  &lt;br /&gt;
 &lt;br /&gt;
　　d：设计模式上(反转控制的一种应用，类似监听者模式) &lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
60.     Android dvm的进程和Linux的进程, 应用程序的进程是否为同一个概念  &lt;br /&gt;
　　DVM指dalivk的虚拟机。每一个Android应用程序都在它自己的进程中运行，都拥有一个独立的Dalvik虚拟机实例。而每一个DVM都是在Linux 中的一个进程，所以说可以认为是同一个概念。  &lt;br /&gt;
 &lt;br /&gt;
61.     sim卡的EF 文件有何作用  &lt;br /&gt;
　　sim卡的文件系统有自己规范，主要是为了和手机通讯，sim本 身可以有自己的操作系统，EF就是作存储并和手机通讯用的  &lt;br /&gt;
 &lt;br /&gt;
62.     嵌入式操作系统内存管理有哪几种， 各有何特性  &lt;br /&gt;
　　页式，段式，段页，用到了MMU,虚拟空间等技术  &lt;br /&gt;
 &lt;br /&gt;
63.      什么是嵌入式实时操作系统, Android 操作系统属于实时操作系统吗?  &lt;br /&gt;
　　嵌入式实时操作系统是指当外界事件或数据产生时，能够接受并以足够快的速度予以处理，其处理的结果又能在规定的时间之内来控制生产过程或对处理系统作出快速响应，并控制所有实时任务协调一致运行的嵌入式操作系统。主要用于工业控制、 军事设备、 航空航天等领域对系统的响应时间有苛刻的要求，这就需要使用实时系统。又可分为软实时和硬实时两种，而android是基于linux内核的，因此属于软实时。  &lt;br /&gt;
 &lt;br /&gt;
64.     一条最长的短信息约占多少byte?  &lt;br /&gt;
　　中文70(包括标点)，英文160，160个字节。  &lt;br /&gt;
 &lt;br /&gt;
65.     android中的动画有哪几类，它们的特点和区别是什么?  &lt;br /&gt;
　　两种，一种是Tween动画、还有一种是Frame动画。Tween动画，这种实现方式可以使视图组件移动、放大、缩小以及产生透明度的变化;另一种Frame动画，传统的动画方法，通过顺序的播放排列好的图片来实现，类似电影。  &lt;br /&gt;
 &lt;br /&gt;
66.     handler机制的原理  &lt;br /&gt;
　　andriod提供了Handler 和 Looper 来满足线程间的通信。Handler先进先出原则。Looper类用来管理特定线程内对象之间的消息交换(MessageExchange)。  &lt;br /&gt;
 &lt;br /&gt;
　　1)Looper: 一个线程可以产生一个Looper对象，由它来管理此线程里的MessageQueue(消息队列)。  &lt;br /&gt;
 &lt;br /&gt;
　　2)Handler: 你可以构造Handler对象来与Looper沟通，以便push新消息到MessageQueue里;或者接收Looper从Message Queue取出)所送来的消息。  &lt;br /&gt;
 &lt;br /&gt;
　　3) Message Queue(消息队列):用来存放线程放入的消息。  &lt;br /&gt;
 &lt;br /&gt;
　　4)线程：UIthread 通常就是main thread，而Android启动程序时会替它建立一个MessageQueue。  &lt;br /&gt;
67.     说说mvc模式的原理，它在android中的运用  &lt;br /&gt;
　MVC(Model_view_contraller)”模型_视图_控制器”。 MVC应用程序总是由这三个部分组成。Event(事件)导致Controller改变Model或View，或者同时改变两者。只要Controller改变了Models的数据或者属性，所有依赖的View都会自动更新。类似的，只要Contro &lt;br /&gt;
68.    DDMS和TraceView的区别? DDMS是一个程序执行查看器，在里面可以看见线程和堆栈等信息，TraceView是程序性能分析器 。 &lt;br /&gt;
69.    java中如何引用本地语言 可以用JNI（java nativeinterface  java 本地接口）接口。 &lt;br /&gt;
 &lt;br /&gt;
70.    谈谈Android的IPC（进程间通信）机制 IPC是内部进程通信的简称， 是共享&amp;quot;命名管道&amp;quot;的资源。Android中的IPC机制是为了让Activity和Service之间可以随时的进行交互，故在Android中该机制，只适用于Activity和Service之间的通信，类似于远程方法调用，类似于C/S模式的访问。通过定义AIDL接口文件来定义IPC接口。Servier端实现IPC接口，Client端调用IPC接口本地代理。 &lt;br /&gt;
71.    NDK是什么NDK是一些列工具的集合，NDK提供了一系列的工具，帮助开发者迅速的开发C/C++的动态库，并能自动将so和java 应用打成apk包。 &lt;br /&gt;
NDK集成了交叉编译器，并提供了相应的mk文件和隔离cpu、平台等的差异，开发人员只需简单的修改mk文件就可以创建出so

 &lt;div&gt;
    作者：u011133213 发表于2013-10-16 0:31:36   &lt;a href="http://blog.csdn.net/ljphhj/article/details/12762605"&gt;原文链接&lt;/a&gt;
&lt;/div&gt;
 &lt;div&gt;
    阅读：176 评论：0   &lt;a href="http://blog.csdn.net/ljphhj/article/details/12762605#comments" target="_blank"&gt;查看评论&lt;/a&gt;
&lt;/div&gt;

&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/46052-android-%E5%BC%80%E5%8F%91-%E9%9D%A2%E8%AF%95</guid>
      <pubDate>Wed, 16 Oct 2013 08:31:36 CST</pubDate>
    </item>
    <item>
      <title>JQuery经典总结</title>
      <link>https://itindex.net/detail/46663-jquery-%E7%BB%8F%E5%85%B8</link>
      <description>&lt;p&gt;1、jQuery介绍&lt;/p&gt;
 &lt;p&gt;jQuery是一个js框架(其实就是一个.js文件),它的特点是使用选择器查找要操作的节点,并且将这些节点封装成一个jQuery对象。封装的目的是为了更好地兼容不同的浏览器之间的差异，同时也会简化代码。&lt;/p&gt;
 &lt;p&gt;注：&lt;/p&gt;
 &lt;p&gt;选择器是jQuery借鉴css选择器的语法而创建的一种查找要操作的节点的语法格式。比如  $(&amp;apos;#id&amp;apos;);&lt;/p&gt;
 &lt;p&gt;2、jQuery基础&lt;/p&gt;
 &lt;p&gt;(1)jQuery编程的基本步骤&lt;/p&gt;
 &lt;p&gt;step1,引入jQuery.js文件&lt;/p&gt;
 &lt;p&gt;step2, 使用选择器查找要操作的节点&lt;/p&gt;
 &lt;p&gt;step3,调用jQuery对象的属性或者方法来操作相应的节点。&lt;/p&gt;
 &lt;p&gt;(2)jQuery对象与dom对象之间的转换&lt;/p&gt;
 &lt;p&gt;1)dom对象 --- &amp;gt; jQuery对象&lt;/p&gt;
 &lt;p&gt;var $obj = $(dom对象);&lt;/p&gt;
 &lt;p&gt;             eg:var $d = $(div);&lt;/p&gt;
 &lt;p&gt;2)jQuery对象 ---- &amp;gt; dom对象&lt;/p&gt;
 &lt;p&gt;第一种方式:   var obj = $obj.get(0);&lt;/p&gt;
 &lt;p&gt;第二种方式:   var obj = $obj.get()[0];&lt;/p&gt;
 &lt;p&gt;    JQuery经典总结&lt;/p&gt;
 &lt;p&gt;(3) jQuery与prototype如何同时使用？&lt;/p&gt;
 &lt;p&gt;因为jQuery与prototype都使用$函数，需要使用&lt;/p&gt;
 &lt;p&gt;var $a = jQuery.noConflict()将$函数改名为&amp;quot;$a&amp;quot;。&lt;/p&gt;
 &lt;p&gt;&lt;/p&gt;
 &lt;p&gt;3、jQuery选择器   selector&lt;/p&gt;
 &lt;p&gt;1)、基本选择器   selector/a1.html&lt;/p&gt;
 &lt;p&gt;         *   ——&amp;gt;匹配所有元素&lt;/p&gt;
 &lt;p&gt;#id   ——&amp;gt;  根据给定的ID匹配一个元素。&lt;/p&gt;
 &lt;p&gt;.class ——&amp;gt;  根据给定的类匹配元素。&lt;/p&gt;
 &lt;p&gt;element ——&amp;gt;根据给定的元素名匹配所有元素&lt;/p&gt;
 &lt;p&gt;selector1,selector2..selectorn ——&amp;gt;将每一个选择器匹配到的元素合并&lt;/p&gt;
 &lt;p&gt;                                                 后一起返回。&lt;/p&gt;
 &lt;p&gt;2)、层次选择器 selector/a2.html&lt;/p&gt;
 &lt;p&gt;select1 select2——&amp;gt;匹配select1下的所有儿子元素（不包含孙子元素）&lt;/p&gt;
 &lt;p&gt;select1&amp;gt;select2——&amp;gt;匹配select1下的所有子元素（包含孙子元素）&lt;/p&gt;
 &lt;p&gt;select1+select2——&amp;gt;匹配紧跟在select1后的第一个兄弟元素（同辈元素）&lt;/p&gt;
 &lt;p&gt;select1~select2——&amp;gt;匹配select1后的所有兄弟元素（及找到所有的同&lt;/p&gt;
 &lt;p&gt;                            辈元素）&lt;/p&gt;
 &lt;p&gt;3)、过滤选择器  &lt;/p&gt;
 &lt;p&gt;a.基本过滤选择器 selector/ a3.html&lt;/p&gt;
 &lt;p&gt;:first——&amp;gt;获取第一个元素&lt;/p&gt;
 &lt;p&gt;:last——&amp;gt;获取第一个元素&lt;/p&gt;
 &lt;p&gt;:not(selector)——&amp;gt;获取去除给定元素后的所有匹配元素&lt;/p&gt;
 &lt;p&gt;:even——&amp;gt;匹配所有索引值为偶数的元素，从 0 开始计数&lt;/p&gt;
 &lt;p&gt;:odd——&amp;gt;匹配所有索引值为奇数的元素，从 0 开始计数&lt;/p&gt;
 &lt;p&gt;:eq(index)——&amp;gt;匹配一个给定索引值的元素&lt;/p&gt;
 &lt;p&gt;:gt(index)——&amp;gt;匹配所有大于给定索引值的元素&lt;/p&gt;
 &lt;p&gt;:lt(index)——&amp;gt;匹配所有小于给定索引值的元素&lt;/p&gt;
 &lt;p&gt; JQuery经典总结&lt;/p&gt;
 &lt;p&gt;b.内容过滤选择器  selector/ a4.html&lt;/p&gt;
 &lt;p&gt;:contains(text)——&amp;gt;匹配包含给定文本的元素&lt;/p&gt;
 &lt;p&gt;:empty   ——&amp;gt;匹配没有子元素且文本为空的元素        :has(selector)——&amp;gt;匹配含有选择器所匹配的元素的元素&lt;/p&gt;
 &lt;p&gt;:parent ——&amp;gt; 跟empty相反,即有子节点，或者内容不为空的节点。&lt;/p&gt;
 &lt;p&gt;c.可见性过滤选择器 selector/ a5.html&lt;/p&gt;
 &lt;p&gt;:hidden——&amp;gt;匹配所有不可见元素，或者type为hidden的元素&lt;/p&gt;
 &lt;p&gt;:visible——&amp;gt;匹配所有的可见元素&lt;/p&gt;
 &lt;p&gt;d.属性过滤选择器 selector/ a6.html&lt;/p&gt;
 &lt;p&gt;[attribute]——&amp;gt;匹配包含给定属性的元素&lt;/p&gt;
 &lt;p&gt;[attribute=value]——&amp;gt;匹配给定的属性是某个特定值的元素&lt;/p&gt;
 &lt;p&gt;[attribute!=value]——&amp;gt;匹配属性不等于特定值的元素。&lt;/p&gt;
 &lt;p&gt;e.子元素过滤选择器 selector/ a7.html&lt;/p&gt;
 &lt;p&gt;:nth-child(index/even/odd)——&amp;gt;匹配其父元素下的第N个子或奇&lt;/p&gt;
 &lt;p&gt;                                                  偶元素（即同辈中第N个元素）&lt;/p&gt;
 &lt;p&gt;           :first-child——&amp;gt;匹配其父元素下第一个子元素&lt;/p&gt;
 &lt;p&gt;           :last-child——&amp;gt;匹配其父元素下最后一个子元素&lt;/p&gt;
 &lt;p&gt;f.表单对象属性过滤选择器&lt;/p&gt;
 &lt;p&gt;:enabled——&amp;gt;匹配所有可用元素&lt;/p&gt;
 &lt;p&gt;:disabled——&amp;gt;匹配所有不可用元素&lt;/p&gt;
 &lt;p&gt;:checked——&amp;gt;匹配复选框、单选按钮中被选中的元素&lt;/p&gt;
 &lt;p&gt;:selected——&amp;gt;匹配所有选中的option元素&lt;/p&gt;
 &lt;p&gt;  4)、表单选择器&lt;/p&gt;
 &lt;p&gt;:input——&amp;gt;匹配所有 input, textarea, select 和 button 元素&lt;/p&gt;
 &lt;p&gt;:text——&amp;gt;匹配所有的单行文本框&lt;/p&gt;
 &lt;p&gt;:pasword——&amp;gt;匹配所有密码框&lt;/p&gt;
 &lt;p&gt;:radio——&amp;gt;匹配所有单选按钮&lt;/p&gt;
 &lt;p&gt;:checkbox——&amp;gt;匹配所有复选框&lt;/p&gt;
 &lt;p&gt;:submit——&amp;gt;匹配所有提交按钮&lt;/p&gt;
 &lt;p&gt;:image——&amp;gt;匹配所有图像域&lt;/p&gt;
 &lt;p&gt;:reset——&amp;gt;匹配所有重置按钮&lt;/p&gt;
 &lt;p&gt;:button——&amp;gt;匹配所有按钮&lt;/p&gt;
 &lt;p&gt;:file——&amp;gt;匹配所有文件域&lt;/p&gt;
 &lt;p&gt;:hidden——&amp;gt; 匹配所有不可见元素，或者type为hidden的元素&lt;/p&gt;
 &lt;p&gt;4、dom操作&lt;/p&gt;
 &lt;p&gt;1)、查询  dom / d1.html&lt;/p&gt;
 &lt;p&gt;利用选择器找到要操作的节点之后，访问节点的html内容、text内容、&lt;/p&gt;
 &lt;p&gt;           节点的值以及节点的属性值。除此之外，还可以修改这些值。&lt;/p&gt;
 &lt;p&gt;a, html() : 相当于innerHTML&lt;/p&gt;
 &lt;p&gt;b, text(): 获取div,p,span等元素内文本相当于innerText，&lt;/p&gt;
 &lt;p&gt;c, val():获取文本框text、下拉列表select或选择框checkbox的值&lt;/p&gt;
 &lt;p&gt;d, attr():获取或设置节点的属性值&lt;/p&gt;
 &lt;p&gt;2)、创建   dom / d2.html&lt;/p&gt;
 &lt;p&gt;$(html);&lt;/p&gt;
 &lt;p&gt;3)、插入节点&lt;/p&gt;
 &lt;p&gt;append():向每个匹配的元素内部追加内容，当做最后一个儿子&lt;/p&gt;
 &lt;p&gt;prepend():向每个匹配的元素内部前置内容。当做第一个儿子&lt;/p&gt;
 &lt;p&gt;after():在每个匹配的元素之后插入内容，当做后一个兄弟 &lt;/p&gt;
 &lt;p&gt;before():在每个匹配的元素之前插入内容，当做前一个兄弟&lt;/p&gt;
 &lt;p&gt;  eg:JQuery经典总结&lt;/p&gt;
 &lt;p&gt;       var $obj = $(&amp;apos;&amp;lt;div&amp;gt;首先是培养兴趣，然后是多写代码&amp;lt;/div&amp;gt;&amp;apos;);&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;body&amp;apos;).append($obj);&lt;/p&gt;
 &lt;p&gt;也可以简化为&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;body&amp;apos;).append(&amp;apos;&amp;lt;div&amp;gt;首先是培养兴趣，然后是多写代码&amp;lt;/div&amp;gt;&amp;apos;);&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;4)、删除节点 dom / d3.html&lt;/p&gt;
 &lt;p&gt;remove()：$(&amp;apos;ul li:eq(1)&amp;apos;).remove();&lt;/p&gt;
 &lt;p&gt;remove(selector)：$(&amp;apos;ul li&amp;apos;).remove(&amp;apos;#l1&amp;apos;);&lt;/p&gt;
 &lt;p&gt;empty():清空节点：$(&amp;apos;ul li:eq(1)&amp;apos;).empty();&lt;/p&gt;
 &lt;p&gt;&lt;/p&gt;
 &lt;p&gt;5)、复制节点  dom / d6.html&lt;/p&gt;
 &lt;p&gt;clone():不复制行为&lt;/p&gt;
 &lt;p&gt;clone(true):使复制的节点也具有行为&lt;/p&gt;
 &lt;p&gt;6)、属性操作  dom / d7.html&lt;/p&gt;
 &lt;p&gt;读取：attr(&amp;apos; &amp;apos;);     $(&amp;quot;img&amp;quot;).attr(&amp;quot;src&amp;quot;);&lt;/p&gt;
 &lt;p&gt;设置： attr(&amp;apos; &amp;apos;,&amp;apos; &amp;apos;) $(&amp;quot;img&amp;quot;).attr(‘src’, ‘test.jpg’); &lt;/p&gt;
 &lt;p&gt;        s(&amp;apos;#d1&amp;apos;).attr(&amp;apos;value&amp;apos;,&amp;apos;font-size:40px;color:red;&amp;apos;);&lt;/p&gt;
 &lt;p&gt;        $(&amp;apos;#form1 input:disabled&amp;apos;).attr(&amp;apos;disabled&amp;apos;,false);&lt;/p&gt;
 &lt;p&gt;或者一次设置多个 attr({&amp;quot;&amp;quot;:&amp;quot;&amp;quot;,&amp;quot;&amp;quot;:&amp;quot;&amp;quot;});&lt;/p&gt;
 &lt;p&gt;      eg:$(&amp;apos;div&amp;apos;).attr({&amp;apos;class&amp;apos;:&amp;apos;s1&amp;apos;,&amp;apos;style&amp;apos;:&amp;apos;color:red;&amp;apos;});&lt;/p&gt;
 &lt;p&gt;删除：removeAttr(&amp;apos; &amp;apos;)&lt;/p&gt;
 &lt;p&gt;7)、样式操作  dom / d8.html&lt;/p&gt;
 &lt;p&gt;       获取和设置: attr(&amp;quot;class&amp;quot;,&amp;quot;&amp;quot;), attr(&amp;quot;style&amp;quot;,&amp;quot;&amp;quot;);&lt;/p&gt;
 &lt;p&gt;      alert($(&amp;apos;div&amp;apos;).attr(&amp;apos;class&amp;apos;));&lt;/p&gt;
 &lt;p&gt;      $(&amp;apos;div&amp;apos;).attr(&amp;apos;class&amp;apos;,&amp;apos;s1&amp;apos;)&lt;/p&gt;
 &lt;p&gt;      $(&amp;apos;div&amp;apos;).attr(&amp;apos;style&amp;apos;,&amp;apos;color:blue;&amp;apos;);&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;追加:addClass(&amp;apos;&amp;apos;):$(&amp;apos;div&amp;apos;).addClass(&amp;apos;s2 s3&amp;apos;);&lt;/p&gt;
 &lt;p&gt;移除:removeClass(&amp;apos;&amp;apos;) :$(&amp;apos;div&amp;apos;).removeClass(&amp;apos;s3&amp;apos;);&lt;/p&gt;
 &lt;p&gt;或者removeClass(&amp;apos;s1 s2&amp;apos;) &lt;/p&gt;
 &lt;p&gt;或者removeClass()//会删除所有样式&lt;/p&gt;
 &lt;p&gt;切换样式：toggleClass:$(&amp;apos;div&amp;apos;).toggleClass(&amp;apos;s3&amp;apos;);&lt;/p&gt;
 &lt;p&gt;是否有某个样式 hasClass(&amp;apos;&amp;apos;):alert($(&amp;apos;div&amp;apos;).hasClass(&amp;apos;s3&amp;apos;));&lt;/p&gt;
 &lt;p&gt;读取css(&amp;apos;&amp;apos;)&lt;/p&gt;
 &lt;p&gt;设置css(&amp;apos;&amp;apos;,&amp;apos;&amp;apos;)或者css({&amp;apos;&amp;apos;:&amp;apos;&amp;apos;,&amp;apos;&amp;apos;:&amp;apos;&amp;apos;})//设置多个样式&lt;/p&gt;
 &lt;p&gt;       $(&amp;apos;table tr:first&amp;apos;).css(&amp;apos;background-color&amp;apos;,&amp;apos;#cccccc&amp;apos;);&lt;/p&gt;
 &lt;p&gt;       $(&amp;apos;table tr:first&amp;apos;).css({&amp;apos;background-color&amp;apos;:&amp;apos;#cccccc&amp;apos;,’width’:’3px’});&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;8)、遍历节点 dom / d9.html&lt;/p&gt;
 &lt;p&gt;children()/children(selector):var $obj = $(&amp;apos;#d0&amp;apos;).children(&amp;apos;div&amp;apos;);&lt;/p&gt;
 &lt;p&gt;只考虑子元素，不考虑其它后代元素。&lt;/p&gt;
 &lt;p&gt;next(selector): 下一个兄弟$(&amp;apos;#d2&amp;apos;).next()&lt;/p&gt;
 &lt;p&gt;prev(selector):上一个兄弟$(&amp;apos;#d2&amp;apos;).prev()&lt;/p&gt;
 &lt;p&gt;siblings(selector):其它兄弟，&lt;/p&gt;
 &lt;p&gt;       $(&amp;apos;#d2&amp;apos;).siblings(‘#id’)除#d2之外的其他兄弟节点&lt;/p&gt;
 &lt;p&gt;       也可以写成：$(‘#id’).siblings()&lt;/p&gt;
 &lt;p&gt;parent():父节点,不是爷爷节点&lt;/p&gt;
 &lt;p&gt;find(selector): 从当前节点开始，查找所有后代，包括孙子。&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;5、如何将js代码与html分开(将数据与行为分离) &lt;/p&gt;
 &lt;p&gt; 就上将形如&amp;lt;input type=”button” id=”b1” onclick=”fun();”/&amp;gt;改写为：&lt;/p&gt;
 &lt;p&gt;&amp;lt;input type=”button” id=”b1” /&amp;gt;&lt;/p&gt;
 &lt;p&gt; $(function(){&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;#b1&amp;apos;).click(function(){&lt;/p&gt;
 &lt;p&gt;//.........&lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt;的形式&lt;/p&gt;
 &lt;p&gt;window.onload : 当整个页面加载完毕，会产生load事件，就会执行绑订&lt;/p&gt;
 &lt;p&gt;                   的函数。&lt;/p&gt;
 &lt;p&gt;window.onload = function () {&lt;/p&gt;
 &lt;p&gt;var obj = document.getElementById(&amp;quot;d1&amp;quot;);&lt;/p&gt;
 &lt;p&gt;obj.onclick = function () {&lt;/p&gt;
 &lt;p&gt;obj.innerHTML = &amp;quot;hello java&amp;quot;;&lt;/p&gt;
 &lt;p&gt;};&lt;/p&gt;
 &lt;p&gt;};&lt;/p&gt;
 &lt;p&gt;在使用jQuery时，可以使用如下的代码来实现js与html的分离:&lt;/p&gt;
 &lt;p&gt;$(function(){&lt;/p&gt;
 &lt;p&gt;//js代码: 这些js代码会在整个页面加载完毕之后&lt;/p&gt;
 &lt;p&gt;//执行。&lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt;eg:&lt;/p&gt;
 &lt;p&gt;$(function(){相当于window.onload = function ()&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;#b1&amp;apos;).click(function(){&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;div&amp;apos;).attr({&amp;apos;class&amp;apos;:&amp;apos;s1&amp;apos;,&amp;apos;style&amp;apos;:&amp;apos;color:red;&amp;apos;});&lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt;上面的代码等同于：&lt;/p&gt;
 &lt;p&gt;window.onload = function () {&lt;/p&gt;
 &lt;p&gt;　　$(&amp;apos;#b1&amp;apos;).get(0).onclick=function(){&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;div&amp;apos;).attr({&amp;apos;class&amp;apos;:&amp;apos;s1&amp;apos;,&amp;apos;style&amp;apos;:&amp;apos;color:red;&amp;apos;});&lt;/p&gt;
 &lt;p&gt;}&lt;/p&gt;
 &lt;p&gt;}&lt;/p&gt;
 &lt;p&gt;6、事件处理机制   event&lt;/p&gt;
 &lt;p&gt;1)、事件绑订  event/e1.html&lt;/p&gt;
 &lt;p&gt;bind(type,fn)&lt;/p&gt;
 &lt;p&gt;      eg:&lt;/p&gt;
 &lt;p&gt;$(function(){&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;#d1&amp;apos;).bind(&amp;apos;click&amp;apos;,function(){&lt;/p&gt;
 &lt;p&gt;$(this).html(&amp;apos;hello java&amp;apos;);&lt;/p&gt;
 &lt;p&gt;}); &lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt;2)、绑订方式的简写形式&lt;/p&gt;
 &lt;p&gt;        上个列子可以简写为：&lt;/p&gt;
 &lt;p&gt;$(function(){&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;#d1&amp;apos;).click(function(){&lt;/p&gt;
 &lt;p&gt;$(this).html(&amp;apos;hello java&amp;apos;);&lt;/p&gt;
 &lt;p&gt;}); &lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt;3)、合成事件  event/e2.html   e3.html&lt;/p&gt;
 &lt;p&gt;hover(mouseenter,leave) : 模拟光标悬停事件，区别于CSS中的伪&lt;/p&gt;
 &lt;p&gt;                                   类&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;.s1&amp;apos;).hover(function(){&lt;/p&gt;
 &lt;p&gt;$(this).addClass(&amp;apos;s2&amp;apos;);&lt;/p&gt;
 &lt;p&gt;},function(){&lt;/p&gt;
 &lt;p&gt;$(this).removeClass(&amp;apos;s2&amp;apos;);&lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;相当于以下连个函数的合成：&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;.s1&amp;apos;).mouseenter(function(){&lt;/p&gt;
 &lt;p&gt;$(this).addClass(&amp;apos;s2&amp;apos;);&lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;.s1&amp;apos;).mouseleave(function(){&lt;/p&gt;
 &lt;p&gt;$(this).removeClass(&amp;apos;s2&amp;apos;);&lt;/p&gt;
 &lt;p&gt;  });&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;上面的mouseenter和mouseleave两个函数可以合并为：&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;.s1&amp;apos;).mouseenter(function(){&lt;/p&gt;
 &lt;p&gt;$(this).addClass(&amp;apos;s2&amp;apos;);&lt;/p&gt;
 &lt;p&gt;}).mouseleave(function(){&lt;/p&gt;
 &lt;p&gt;$(this).removeClass(&amp;apos;s2&amp;apos;);&lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt;toggle(fn1,fn2...)：模拟鼠标连续单击事件&lt;/p&gt;
 &lt;p&gt;         $(&amp;apos;#a1&amp;apos;).toggle(function(){&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;#d1&amp;apos;).show(&amp;apos;slow&amp;apos;);&lt;/p&gt;
 &lt;p&gt;},function(){&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;#d1&amp;apos;).hide(&amp;apos;slow&amp;apos;);&lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt;4)、事件冒泡&lt;/p&gt;
 &lt;p&gt;(1)获得事件对象  event/e4.html e5.html e6.html&lt;/p&gt;
 &lt;p&gt;click(function(e){&lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt;function f1(e){&lt;/p&gt;
 &lt;p&gt;依据事件对象获得事件源(即哪一个节点产生了该事件，返回的是原&lt;/p&gt;
 &lt;p&gt;       始的DOM节点)，其中e不再是DOM对象，而是封装之后的JQuery&lt;/p&gt;
 &lt;p&gt;       对象。&lt;/p&gt;
 &lt;p&gt;var srcObj = e.srcElement;  //ie&lt;/p&gt;
 &lt;p&gt;var srcObj = e.target; //firefox,chrome&lt;/p&gt;
 &lt;p&gt;var srcObj = e.srcElement || e.target; //同时兼容ie,firefox,chrome&lt;/p&gt;
 &lt;p&gt;alert(srcObj.innerHTML);&lt;/p&gt;
 &lt;p&gt;依据事件对象获得鼠标点击的坐标（相对于屏幕）&lt;/p&gt;
 &lt;p&gt;alert(e.clientX + &amp;apos;:&amp;apos; + e.clientY);&lt;/p&gt;
 &lt;p&gt;}&lt;/p&gt;
 &lt;p&gt;       (2)事件对象的属性  event/e6.html&lt;/p&gt;
 &lt;p&gt;event.type&lt;/p&gt;
 &lt;p&gt;event.target:返回事件源(是dom对象)&lt;/p&gt;
 &lt;p&gt;event.pageX/pageY   获得相对于当前浏览器页面的坐标&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;(3)停止冒泡   event / e7.html&lt;/p&gt;
 &lt;p&gt;event.stopPropagation()&lt;/p&gt;
 &lt;p&gt;function clickA(e){&lt;/p&gt;
 &lt;p&gt;alert(&amp;quot;你点击了一个链接&amp;quot;);&lt;/p&gt;
 &lt;p&gt;//取消冒泡&lt;/p&gt;
 &lt;p&gt;e.stopPropagation();&lt;/p&gt;
 &lt;p&gt;  }&lt;/p&gt;
 &lt;p&gt;function clickDiv(e){&lt;/p&gt;
 &lt;p&gt;alert(&amp;quot;你点击了一个Div&amp;quot;);&lt;/p&gt;
 &lt;p&gt;}&lt;/p&gt;
 &lt;p&gt;上列中，链接处于div中，当取消冒泡后，单击链接便不会触发div上面&lt;/p&gt;
 &lt;p&gt;onlick事件的执行，上例中的输出结果为：你点击了一个链接&lt;/p&gt;
 &lt;p&gt;(4)停止默认行为  event / e8.html&lt;/p&gt;
 &lt;p&gt;event.preventDefault()&lt;/p&gt;
 &lt;p&gt;$(function(){&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;#d1&amp;apos;).click(function(e){&lt;/p&gt;
 &lt;p&gt;var flag = confirm(&amp;apos;确定删除吗&amp;apos;);&lt;/p&gt;
 &lt;p&gt;if(!flag){&lt;/p&gt;
 &lt;p&gt;e.preventDefault();&lt;/p&gt;
 &lt;p&gt;}&lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt;设置停止了默认行为后，表单提交按钮便不会自动提交了。相当于：&lt;/p&gt;
 &lt;p&gt;　　&amp;lt;input type=”submit” id=”d1” name=”username” &lt;/p&gt;
 &lt;p&gt;　　  onclick=”return fonfirm(‘确定要删除吗’)”/&amp;gt;&lt;/p&gt;
 &lt;p&gt;5)、模拟操作  event / e9.html&lt;/p&gt;
 &lt;p&gt;trigger(&amp;apos;click&amp;apos;) 
&lt;/p&gt;
 &lt;p&gt;$(function(){&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;#b1&amp;apos;).click(function(){&lt;/p&gt;
 &lt;p&gt;//$(&amp;apos;#username&amp;apos;).trigger(&amp;apos;focus&amp;apos;);&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;#username&amp;apos;).focus();&lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt;上列模拟了文本框控件获得焦点的行为，当点击按钮后，文本框便获得了焦点，表现为文本框内有光标闪动。&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;mouseenter和mouseover效果一样，可以互换使用&lt;/p&gt;
 &lt;p&gt;mouseout和mouseleave效果一样，可以互换使用&lt;/p&gt;
 &lt;p&gt;7、动画   animate&lt;/p&gt;
 &lt;p&gt;   1)、show(), hide()   a1.html&lt;/p&gt;
 &lt;p&gt;作用：通过同时改变元素的宽度与高度来实现显示和隐藏的效果。&lt;/p&gt;
 &lt;p&gt;语法:&lt;/p&gt;
 &lt;p&gt;show(速度,callback);&lt;/p&gt;
 &lt;p&gt;速度:  &amp;apos;slow&amp;apos;,&amp;apos;normal&amp;apos;,&amp;apos;fast&amp;apos; / 800(毫秒)&lt;/p&gt;
 &lt;p&gt;callback: 在动画执行完毕之后，会执行这个函数&lt;/p&gt;
 &lt;p&gt;         $(function(){&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;#btn1&amp;apos;).click(function(){&lt;/p&gt;
 &lt;p&gt;   $(&amp;apos;#sp1&amp;apos;).hide/show(500);&lt;/p&gt;
 &lt;p&gt;                 $(&amp;apos;#sp1&amp;apos;).hide/show(500,function(){alert(&amp;quot;H&amp;quot;);});&lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt;2)、fadeIn() fadeOut():  animate / a2.html&lt;/p&gt;
 &lt;p&gt;作用， 通过改变元素的不透明度来实现显示和隐藏的效果。&lt;/p&gt;
 &lt;p&gt;语法: fadeIn/fadeOut(速度,callback);&lt;/p&gt;
 &lt;p&gt;$(function(){&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;#btn1&amp;apos;).click(function(){&lt;/p&gt;
 &lt;p&gt;   $(&amp;apos;#sp1&amp;apos;).fadeIn/fadeOut(500);&lt;/p&gt;
 &lt;p&gt;                 $(&amp;apos;#sp1&amp;apos;).fadeIn/fadeOut(500,function(){alert(&amp;quot;H&amp;quot;);});&lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;3)、slideUp() slideDown() :  amimate/a1.html&lt;/p&gt;
 &lt;p&gt;作用：通过改变元素的高度来实现显示和隐藏的效果。&lt;/p&gt;
 &lt;p&gt;语法: slideUp(速度,callback);&lt;/p&gt;
 &lt;p&gt;$(function(){&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;#a1&amp;apos;).toggle(function(){&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;#d1&amp;apos;).slideDown(&amp;apos;slow&amp;apos;);&lt;/p&gt;
 &lt;p&gt;},function(){&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;#d1&amp;apos;).slideUp(&amp;apos;slow&amp;apos;);&lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt;&lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt;4)、自定义动画 animate(params,speed,callback) a3.html&lt;/p&gt;
 &lt;p&gt;语法: JQuery经典总结&lt;/p&gt;
 &lt;p&gt;params:是一个js对象，描述了动画执行结束时元素的样式，&lt;/p&gt;
 &lt;p&gt;                  比如:&lt;/p&gt;
 &lt;p&gt;{&amp;apos;top&amp;apos;:&amp;apos;600px&amp;apos;,&amp;apos;left&amp;apos;:&amp;apos;200px&amp;apos;}&lt;/p&gt;
 &lt;p&gt;speed:  毫秒&lt;/p&gt;
 &lt;p&gt;callback: 在动画执行完毕之后，会执行这个函数&lt;/p&gt;
 &lt;p&gt;$(this).animate({&amp;apos;left&amp;apos;:&amp;apos;500px&amp;apos;},4000);&lt;/p&gt;
 &lt;p&gt;$(this).animate({&amp;apos;top&amp;apos;:&amp;apos;250px&amp;apos;},2000).fadeOut(&amp;apos;slow&amp;apos;);&lt;/p&gt;
 &lt;p&gt;8、类数组的操作  &lt;/p&gt;
 &lt;p&gt;jQuery选择器返回的是一个jQuery对象(该对象可能包括了多个dom&lt;/p&gt;
 &lt;p&gt;       节点),如果要对这些dom节点分别做不同的处理，就需要去遍历，需要&lt;/p&gt;
 &lt;p&gt;       调用jQuery对象提供的一些方法或者属性，称之为类数组的操作。&lt;/p&gt;
 &lt;p&gt;       类数组就是DOM节点数组&lt;/p&gt;
 &lt;p&gt;1)each(fn(i)):循环遍历每一个元素,this代表被迭代的dom对象，&lt;/p&gt;
 &lt;p&gt;                 $(this)代表被迭代的jQuery对象。（i根据实际情况选择要&lt;/p&gt;
 &lt;p&gt;                 还是不要）。&lt;/p&gt;
 &lt;p&gt;2)eq(index)：返回index+1位置处的jQuery对象&lt;/p&gt;
 &lt;p&gt;3)index(obj)：返回下标，其中obj可以是dom对象或者jQuery对象。&lt;/p&gt;
 &lt;p&gt;4)length属性：dom对象的个数&lt;/p&gt;
 &lt;p&gt;5)get()：返回dom对象组成的数组&lt;/p&gt;
 &lt;p&gt;6)get(index)：返回index+1个dom对象。&lt;/p&gt;
 &lt;p&gt;eg1:&lt;/p&gt;
 &lt;p&gt;//把我的好友中所有的用户放到用户列表中&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;#b4&amp;apos;).click(function(){&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;#s2 option&amp;apos;).each(function(){&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;#s1&amp;apos;).append($(this));&lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt;    eg2:&lt;/p&gt;
 &lt;p&gt;$(function(){&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;#b1&amp;apos;).click(function(){&lt;/p&gt;
 &lt;p&gt;var $obj = $(&amp;apos;ul li&amp;apos;);&lt;/p&gt;
 &lt;p&gt;$obj.each(function(i){&lt;/p&gt;
 &lt;p&gt;//i:表示正在被访问的那个节点的下标,&lt;/p&gt;
 &lt;p&gt;//下标从0开始&lt;/p&gt;
 &lt;p&gt;if(i == 0){&lt;/p&gt;
 &lt;p&gt;$(this).css(&amp;apos;font-size&amp;apos;,&amp;apos;50px&amp;apos;);&lt;/p&gt;
 &lt;p&gt;}else if(i==1){&lt;/p&gt;
 &lt;p&gt;$(this).css(&amp;apos;font-style&amp;apos;,&amp;apos;italic&amp;apos;);&lt;/p&gt;
 &lt;p&gt;}else{&lt;/p&gt;
 &lt;p&gt;$(this).css(&amp;apos;color&amp;apos;,&amp;apos;red&amp;apos;).css(&amp;apos;font-size&amp;apos;,&amp;apos;80px&amp;apos;);&lt;/p&gt;
 &lt;p&gt;}&lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;9、jQuery对ajax编程的支持&lt;/p&gt;
 &lt;p&gt;(1)load方法:&lt;/p&gt;
 &lt;p&gt;作用：是将服务器返回的数据直接添加到符合要求的节点之上，相当于&lt;/p&gt;
 &lt;p&gt;             obj.innerHTML = 返回的数据。&lt;/p&gt;
 &lt;p&gt;语法:&lt;/p&gt;
 &lt;p&gt;$obj.load(请求地址,[请求参数]);&lt;/p&gt;
 &lt;p&gt;其中，请求参数可以有两种形式:&lt;/p&gt;
 &lt;p&gt;第一种：请求字符串，比如 &amp;quot;username=zs&amp;quot;,或者&lt;/p&gt;
 &lt;p&gt;“username=zs&amp;amp;age=22&amp;quot;。&lt;/p&gt;
 &lt;p&gt;第二种：javascript对象，比如 &lt;/p&gt;
 &lt;p&gt;{&amp;apos;username&amp;apos;:&amp;apos;zs&amp;apos;}，或者{&amp;apos;username&amp;apos;:&amp;apos;zs&amp;apos;,&amp;apos;age&amp;apos;:22}&lt;/p&gt;
 &lt;p&gt;load方法如果没有请求参数，会发送get请求，如果有请求参数，会发送&lt;/p&gt;
 &lt;p&gt;       post请求。&lt;/p&gt;
 &lt;p&gt;&lt;/p&gt;
 &lt;p&gt;(2)$.get方法&lt;/p&gt;
 &lt;p&gt;作用：向服务器发送get请求&lt;/p&gt;
 &lt;p&gt;语法:   $.get(url,[data],[callback],[type]):&lt;/p&gt;
 &lt;p&gt;url:请求地址&lt;/p&gt;
 &lt;p&gt;data:请求参数,可以是请求字符串或者是js对象。&lt;/p&gt;
 &lt;p&gt;                 格式为：{key,value}&lt;/p&gt;
 &lt;p&gt;                 eg:{&amp;quot;name&amp;quot;:$(&amp;quot;#cost_name&amp;quot;).val()}&lt;/p&gt;
 &lt;p&gt;callback: 是一个回调函数，用于处理服务器返回的数据，其格式 &lt;/p&gt;
 &lt;p&gt;                   function(data,statusText),&lt;/p&gt;
 &lt;p&gt;data是服务器返回的数据，如果服务器返回的是json字符串，$.get&lt;/p&gt;
 &lt;p&gt;          方法会自动将其转换成一个js对象或者js对象组成的数组。&lt;/p&gt;
 &lt;p&gt;                  statusText是服务器处理的状态。&lt;/p&gt;
 &lt;p&gt;type:服务器返回的数据类型:&lt;/p&gt;
 &lt;p&gt;text : 文本字符串&lt;/p&gt;
 &lt;p&gt;html : html内容&lt;/p&gt;
 &lt;p&gt;xml: 返回dom兼容的xml对象&lt;/p&gt;
 &lt;p&gt;json: json字符串&lt;/p&gt;
 &lt;p&gt;script: javascript脚本&lt;/p&gt;
 &lt;p&gt;eg:&lt;/p&gt;
 &lt;p&gt;function quoto(){&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;#tb1&amp;apos;).empty();&lt;/p&gt;
 &lt;p&gt;$.get(&amp;apos;quoto.do?&amp;apos; + Math.random(),function(data){&lt;/p&gt;
 &lt;p&gt;//data:服务器返回的数据, 如果服务器&lt;/p&gt;
 &lt;p&gt;//返回的是json字符串，$.get方法会自动&lt;/p&gt;
 &lt;p&gt;//将其转换成一个js对象或者js对象组成的数组。&lt;/p&gt;
 &lt;p&gt;for(i=0;i&amp;lt;data.length;i++){&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;#tb1&amp;apos;).append(&lt;/p&gt;
 &lt;p&gt;&amp;apos;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;&amp;apos; + data[i].code &lt;/p&gt;
 &lt;p&gt;+&amp;apos;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt; &amp;apos;+ data[i].name&lt;/p&gt;
 &lt;p&gt; + &amp;apos;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt; &amp;apos; + data[i].price&lt;/p&gt;
 &lt;p&gt;  + &amp;apos;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;apos;);&lt;/p&gt;
 &lt;p&gt;}&lt;/p&gt;
 &lt;p&gt;},&amp;apos;json&amp;apos;);&lt;/p&gt;
 &lt;p&gt;}&lt;/p&gt;
 &lt;p&gt;$.post()格式同上。&lt;/p&gt;
 &lt;p&gt;$.put(url,[data],[callback],[type]):&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt; //焦点离开资费名输入框进行ajax检测&lt;/p&gt;
 &lt;p&gt;         $(function(){&lt;/p&gt;
 &lt;p&gt;         $(&amp;quot;#name&amp;quot;).blur(function(){          &lt;/p&gt;
 &lt;p&gt;             var name = $(this).val();&lt;/p&gt;
 &lt;p&gt;         
//发送ajax请求&lt;/p&gt;
 &lt;p&gt;         $.post(&lt;/p&gt;
 &lt;p&gt;         
&amp;quot;validFeeName.action&amp;quot;,//请求url&lt;/p&gt;
 &lt;p&gt;         {&amp;quot;name&amp;quot;:name},//提交参数&lt;/p&gt;
 &lt;p&gt;         
function(data){//data是服务器返回的ok值&lt;/p&gt;
 &lt;p&gt;         
if(data){//如果返回true             $(&amp;quot;#name_error&amp;quot;).removeClass(&amp;quot;error_msg&amp;quot;)&lt;/p&gt;
 &lt;p&gt;               .html(&amp;quot;资费名称可用&amp;quot;);&lt;/p&gt;
 &lt;p&gt;         }else{//如果返回false&lt;/p&gt;
 &lt;p&gt;         $(&amp;quot;#name_error&amp;quot;).addClass(&amp;quot;error_msg&amp;quot;)&lt;/p&gt;
 &lt;p&gt;                               .html(&amp;quot;资费名称重复&amp;quot;);&lt;/p&gt;
 &lt;p&gt;         }&lt;/p&gt;
 &lt;p&gt;         }&lt;/p&gt;
 &lt;p&gt;         ,&amp;quot;text&amp;quot;);  &lt;/p&gt;
 &lt;p&gt;         });&lt;/p&gt;
 &lt;p&gt;        });&lt;/p&gt;
 &lt;p&gt;(3)$.ajax方法&lt;/p&gt;
 &lt;p&gt;作用：可以设置不同的参数，控制ajax对象向服务器发请求。&lt;/p&gt;
 &lt;p&gt;语法:&lt;/p&gt;
 &lt;p&gt;$.ajax(options): &lt;/p&gt;
 &lt;p&gt;其中，options是一个形如&lt;/p&gt;
 &lt;p&gt;{key1:value1,key2,value2...}的js对象，&lt;/p&gt;
 &lt;p&gt;用于指定发送请求的选项。&lt;/p&gt;
 &lt;p&gt;选项参数如下：&lt;/p&gt;
 &lt;p&gt;url(string):请求地址&lt;/p&gt;
 &lt;p&gt;type(string):GET/POST&lt;/p&gt;
 &lt;p&gt;data(object/string):请求参数，可以是请求字符串或者js对象&lt;/p&gt;
 &lt;p&gt;dataType(string) :服务器返回的数据类型&lt;/p&gt;
 &lt;p&gt;success(function):请求成功后调用的回调函数，有两个参数：&lt;/p&gt;
 &lt;p&gt;function(data,textStatus),其中，&lt;/p&gt;
 &lt;p&gt;data是服务器返回的数据，&lt;/p&gt;
 &lt;p&gt;textStatus 描述状态的字符串。&lt;/p&gt;
 &lt;p&gt;       error(function):请求失败时调用的函数，有三个参数&lt;/p&gt;
 &lt;p&gt;function(xhr,textStatus,errorThrown),&lt;/p&gt;
 &lt;p&gt;xhr: ajax对象，即XMLHttpRequest对象。&lt;/p&gt;
 &lt;p&gt;textStatus和errorThrown，jQuery保证其中的一个&lt;/p&gt;
 &lt;p&gt;                         参数可以获得异常的描述。&lt;/p&gt;
 &lt;p&gt;           async: true(缺省)/false&lt;/p&gt;
 &lt;p&gt;eg:&lt;/p&gt;
 &lt;p&gt;$(function(){&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;#s1&amp;apos;).change(function(){&lt;/p&gt;
 &lt;p&gt;//先清空表格&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;#tb1&amp;apos;).empty();&lt;/p&gt;
 &lt;p&gt;$.ajax({&lt;/p&gt;
 &lt;p&gt;&amp;apos;url&amp;apos;:&amp;apos;carInfo.do&amp;apos;,&lt;/p&gt;
 &lt;p&gt;&amp;apos;type&amp;apos;:&amp;apos;post&amp;apos;,&lt;/p&gt;
 &lt;p&gt;&amp;apos;data&amp;apos;:&amp;apos;carName=&amp;apos; + $(&amp;apos;#s1&amp;apos;).val(),&lt;/p&gt;
 &lt;p&gt;&amp;apos;dataType&amp;apos;:&amp;apos;xml&amp;apos;,&lt;/p&gt;
 &lt;p&gt;&amp;apos;success&amp;apos;:function(data){&lt;/p&gt;
 &lt;p&gt;//data:服务器返回的数据如果服务器返回的是xml,&lt;/p&gt;
 &lt;p&gt;                         浏览器不一样，则生成的dom树的结果也不一样，&lt;/p&gt;
 &lt;p&gt;                         为了方便解析dom树，一般 我们使用$()函数将其&lt;/p&gt;
 &lt;p&gt;                         转换成jQuery对象,然后进行遍历或者查找。&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;#tb1&amp;apos;).append(&lt;/p&gt;
 &lt;p&gt;&amp;apos;&amp;lt;tr&amp;gt;&amp;lt;td&amp;gt;价格:&amp;apos; + $(data).find(&amp;apos;price&amp;apos;).text() &lt;/p&gt;
 &lt;p&gt;+ &amp;apos; 车重:&amp;apos; + $(data).find(&amp;apos;weight&amp;apos;).text() &lt;/p&gt;
 &lt;p&gt;+ &amp;apos;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;门数:&amp;apos; &lt;/p&gt;
 &lt;p&gt;+ $(data).find(&amp;apos;doors&amp;apos;).text() &lt;/p&gt;
 &lt;p&gt;+ &amp;apos; 长宽高:&amp;apos; +  $(data).find(&amp;apos;size&amp;apos;).text() &lt;/p&gt;
 &lt;p&gt;+ &amp;apos;&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;排量:&amp;apos; + $(data).find(&amp;apos;vol&amp;apos;).text() &lt;/p&gt;
 &lt;p&gt;+ &amp;apos; 加速性能:&amp;apos; &lt;/p&gt;
 &lt;p&gt;+ $(data).find(&amp;apos;speed&amp;apos;).text() + &amp;apos;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;apos;);&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;#d2&amp;apos;).show();&lt;/p&gt;
 &lt;p&gt;setTimeout(function(){&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;#d2&amp;apos;).fadeOut(&amp;apos;slow&amp;apos;);&lt;/p&gt;
 &lt;p&gt;},3000);&lt;/p&gt;
 &lt;p&gt;},&lt;/p&gt;
 &lt;p&gt;&amp;apos;error&amp;apos;:function(){&lt;/p&gt;
 &lt;p&gt;alert(&amp;apos;服务暂时不可用&amp;apos;);&lt;/p&gt;
 &lt;p&gt;}&lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt;&lt;/p&gt;
 &lt;p&gt;练习1：商品热卖&lt;/p&gt;
 &lt;p&gt;练习2：自动完成&lt;/p&gt;
 &lt;p&gt;step1,服务器端代码&lt;/p&gt;
 &lt;p&gt;服务器会返回一个类似于以下的字符串:&lt;/p&gt;
 &lt;p&gt;小米,小米2,小说,小米官网&lt;/p&gt;
 &lt;p&gt;step2,&lt;/p&gt;
 &lt;p&gt;分解服务器返回的字符串，并且将&lt;/p&gt;
 &lt;p&gt;其添加到文本输入框的下面。&lt;/p&gt;
 &lt;p&gt;每一个选项要绑订click事件(将用户&lt;/p&gt;
 &lt;p&gt;选中的选项复制到文本输入框)和mouseenter&lt;/p&gt;
 &lt;p&gt;事件(加亮对应的选项)处理代码。&lt;/p&gt;
 &lt;p&gt;keyup事件：&lt;/p&gt;
 &lt;p&gt;注意：keyup事件在某些浏览器中，在切换中文输入法时，会有&lt;/p&gt;
 &lt;p&gt;bug,需要我们自己解决，如果发现有这个问题，需要使用如下&lt;/p&gt;
 &lt;p&gt;代码：&lt;/p&gt;
 &lt;p&gt;var eventname = &amp;apos;input&amp;apos;;&lt;/p&gt;
 &lt;p&gt;if(navigator.userAgent.indexOf(&amp;apos;MSIE&amp;apos;)!=-1){&lt;/p&gt;
 &lt;p&gt;eventname = &amp;apos;propertychange&amp;apos;;&lt;/p&gt;
 &lt;p&gt;}&lt;/p&gt;
 &lt;p&gt;$(&amp;apos;#key&amp;apos;).bind(eventname,fn);&lt;/p&gt;
 &lt;p&gt;10、给JQuery添加插件&lt;/p&gt;
 &lt;p&gt;可以把JQuery看做一个类，给JQuery添加插件就是给Jquery类中添加方法。相当于在Java中给String类增加方法（当然是不可以增加的），这样就可以用JQuery对象直接调用了，方便多次使用。&lt;/p&gt;
 &lt;p&gt;使用场合：使用频率高的方法，&lt;/p&gt;
 &lt;p&gt; JQuery经典总结&lt;/p&gt;
 &lt;p&gt;eg:下面代码的作用是对指定的文本框(errorContent)进行非空验证，并输出（errorMsg）验证提示信息。&lt;/p&gt;
 &lt;p&gt;   写法一：&lt;/p&gt;
 &lt;p&gt;$.fn.required = function(errorContent, errorMsg) {&lt;/p&gt;
 &lt;p&gt;　　 
var val = $(this).val();&lt;/p&gt;
 &lt;p&gt;　　 
if (val != null &amp;amp;&amp;amp; val.length &amp;gt; 0) {&lt;/p&gt;
 &lt;p&gt;　　 $(errorContent).text(&amp;quot;&amp;quot;);&lt;/p&gt;
 &lt;p&gt;　　 
return true;&lt;/p&gt;
 &lt;p&gt;　　 } else {&lt;/p&gt;
 &lt;p&gt;　　 $(errorContent).text(errorMsg);&lt;/p&gt;
 &lt;p&gt;　　 
return false;&lt;/p&gt;
 &lt;p&gt;　　 }&lt;/p&gt;
 &lt;p&gt;    　}&lt;/p&gt;
 &lt;p&gt;写法二：&lt;/p&gt;
 &lt;p&gt;;(function($){&lt;/p&gt;
 &lt;p&gt;$.fn.extend({&lt;/p&gt;
 &lt;p&gt;   rangeLength:function(errorContent, errorMsg){&lt;/p&gt;
 &lt;p&gt;var val = $(this).val();&lt;/p&gt;
 &lt;p&gt;if (val != null &amp;amp;&amp;amp; val.length &amp;gt; 0) {&lt;/p&gt;
 &lt;p&gt;$(errorContent).text(&amp;quot;&amp;quot;);&lt;/p&gt;
 &lt;p&gt;return true;&lt;/p&gt;
 &lt;p&gt;} else {&lt;/p&gt;
 &lt;p&gt;$(errorContent).text(errorMsg);&lt;/p&gt;
 &lt;p&gt;return false;&lt;/p&gt;
 &lt;p&gt;}&lt;/p&gt;
 &lt;p&gt;   }&lt;/p&gt;
 &lt;p&gt;});&lt;/p&gt;
 &lt;p&gt;   })(jQuery)&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;/p&gt;
 &lt;p&gt;   $(function() {&lt;/p&gt;
 &lt;p&gt;     $(&amp;quot;#submit&amp;quot;).bind(&amp;quot;click&amp;quot;,function(){&lt;/p&gt;
 &lt;p&gt;        var b1 = $(&amp;quot;#adminCode&amp;quot;)&lt;/p&gt;
 &lt;p&gt;          .required($(&amp;quot;#error_adminCode&amp;quot;),&amp;quot;账号必须填写&amp;quot;);&lt;/p&gt;
 &lt;p&gt;        var b2 = $(&amp;quot;#password&amp;quot;)&lt;/p&gt;
 &lt;p&gt;          .required($(&amp;quot;#error_password&amp;quot;),&amp;quot;密码必须填写&amp;quot;)&lt;/p&gt;
 &lt;p&gt;        if(b1 &amp;amp;&amp;amp; b3) {&lt;/p&gt;
 &lt;p&gt;           $(&amp;quot;#loginForm&amp;quot;).submit();&lt;/p&gt;
 &lt;p&gt;        }&lt;/p&gt;
 &lt;p&gt;     });&lt;/p&gt;
 &lt;p&gt;   });&lt;/p&gt;
 &lt;p&gt;&amp;lt;/script&amp;gt;&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;

 &lt;div&gt;
    作者：u012875880 发表于2013-11-23 9:27:35   &lt;a href="http://blog.csdn.net/zhu_xun/article/details/16891445"&gt;原文链接&lt;/a&gt;
&lt;/div&gt;
 &lt;div&gt;
    阅读：73 评论：0   &lt;a href="http://blog.csdn.net/zhu_xun/article/details/16891445#comments" target="_blank"&gt;查看评论&lt;/a&gt;
&lt;/div&gt;

&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/46663-jquery-%E7%BB%8F%E5%85%B8</guid>
      <pubDate>Sat, 23 Nov 2013 17:27:35 CST</pubDate>
    </item>
    <item>
      <title>sql经典语句</title>
      <link>https://itindex.net/detail/47158-sql-%E7%BB%8F%E5%85%B8-%E8%AF%AD%E5%8F%A5</link>
      <description>&lt;div&gt;
  &lt;ol&gt;
   &lt;li&gt;一、基础 &lt;/li&gt;
   &lt;li&gt;1、说明：创建数据库 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;CREATE&lt;/strong&gt;    &lt;strong&gt;DATABASE&lt;/strong&gt;    &lt;strong&gt;database&lt;/strong&gt;-    &lt;strong&gt;name&lt;/strong&gt;
&lt;/li&gt;
   &lt;li&gt;2、说明：删除数据库 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;drop&lt;/strong&gt;    &lt;strong&gt;database&lt;/strong&gt; dbname 
&lt;/li&gt;
   &lt;li&gt;3、说明：备份sql server &lt;/li&gt;
   &lt;li&gt;--- 创建 备份数据的 device &lt;/li&gt;
   &lt;li&gt;USE master &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;EXEC&lt;/strong&gt; sp_addumpdevice &amp;apos;disk&amp;apos;, &amp;apos;testBack&amp;apos;, &amp;apos;c:\mssql7backup\MyNwind_1.dat&amp;apos;
&lt;/li&gt;
   &lt;li&gt;--- 开始 备份 &lt;/li&gt;
   &lt;li&gt;
BACKUP     &lt;strong&gt;DATABASE&lt;/strong&gt; pubs     &lt;strong&gt;TO&lt;/strong&gt; testBack 
&lt;/li&gt;
   &lt;li&gt;4、说明：创建新表 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;create&lt;/strong&gt;    &lt;strong&gt;table&lt;/strong&gt; tabname(col1 type1 [notnull] [    &lt;strong&gt;primary&lt;/strong&gt;    &lt;strong&gt;key&lt;/strong&gt;],col2 type2 [notnull],..) 
&lt;/li&gt;
   &lt;li&gt;根据已有的表创建新表： &lt;/li&gt;
   &lt;li&gt;
A：    &lt;strong&gt;create&lt;/strong&gt;    &lt;strong&gt;table&lt;/strong&gt; tab_new like tab_old (使用旧表创建新表) 
&lt;/li&gt;
   &lt;li&gt;
B：    &lt;strong&gt;create&lt;/strong&gt;    &lt;strong&gt;table&lt;/strong&gt; tab_new     &lt;strong&gt;as&lt;/strong&gt;    &lt;strong&gt;select&lt;/strong&gt; col1,col2…     &lt;strong&gt;from&lt;/strong&gt; tab_old definition     &lt;strong&gt;only&lt;/strong&gt;
&lt;/li&gt;
   &lt;li&gt;5、说明：删除新表 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;drop&lt;/strong&gt;    &lt;strong&gt;table&lt;/strong&gt; tabname 
&lt;/li&gt;
   &lt;li&gt;6、说明：增加一个列 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;Alter&lt;/strong&gt;    &lt;strong&gt;table&lt;/strong&gt; tabname     &lt;strong&gt;add&lt;/strong&gt;    &lt;strong&gt;column&lt;/strong&gt; col type 
&lt;/li&gt;
   &lt;li&gt;
注：列增加后将不能删除。DB2中列加上后数据类型也不能改变，唯一能改变的是增加    &lt;strong&gt;varchar&lt;/strong&gt;类型的长度。 
&lt;/li&gt;
   &lt;li&gt;
7、说明：添加主键：     &lt;strong&gt;Alter&lt;/strong&gt;    &lt;strong&gt;table&lt;/strong&gt; tabname     &lt;strong&gt;add&lt;/strong&gt;    &lt;strong&gt;primary&lt;/strong&gt;    &lt;strong&gt;key&lt;/strong&gt;(col) 
&lt;/li&gt;
   &lt;li&gt;
说明：删除主键：     &lt;strong&gt;Alter&lt;/strong&gt;    &lt;strong&gt;table&lt;/strong&gt; tabname     &lt;strong&gt;drop&lt;/strong&gt;    &lt;strong&gt;primary&lt;/strong&gt;    &lt;strong&gt;key&lt;/strong&gt;(col) 
&lt;/li&gt;
   &lt;li&gt;
8、说明：创建索引：    &lt;strong&gt;create&lt;/strong&gt; [    &lt;strong&gt;unique&lt;/strong&gt;]     &lt;strong&gt;index&lt;/strong&gt; idxname     &lt;strong&gt;on&lt;/strong&gt; tabname(col….) 
&lt;/li&gt;
   &lt;li&gt;
删除索引：    &lt;strong&gt;drop&lt;/strong&gt;    &lt;strong&gt;index&lt;/strong&gt; idxname 
&lt;/li&gt;
   &lt;li&gt;注：索引是不可更改的，想更改必须删除重新建。 &lt;/li&gt;
   &lt;li&gt;
9、说明：创建视图：    &lt;strong&gt;create&lt;/strong&gt;    &lt;strong&gt;view&lt;/strong&gt; viewname     &lt;strong&gt;as&lt;/strong&gt;    &lt;strong&gt;select&lt;/strong&gt; statement 
&lt;/li&gt;
   &lt;li&gt;
删除视图：    &lt;strong&gt;drop&lt;/strong&gt;    &lt;strong&gt;view&lt;/strong&gt; viewname 
&lt;/li&gt;
   &lt;li&gt;10、说明：几个简单的基本的sql语句 &lt;/li&gt;
   &lt;li&gt;
选择：    &lt;strong&gt;select&lt;/strong&gt; *     &lt;strong&gt;from&lt;/strong&gt; table1     &lt;strong&gt;where&lt;/strong&gt; 范围 
&lt;/li&gt;
   &lt;li&gt;
插入：    &lt;strong&gt;insert&lt;/strong&gt;    &lt;strong&gt;into&lt;/strong&gt; table1(field1,field2)     &lt;strong&gt;values&lt;/strong&gt;(value1,value2) 
&lt;/li&gt;
   &lt;li&gt;
删除：    &lt;strong&gt;delete&lt;/strong&gt;    &lt;strong&gt;from&lt;/strong&gt; table1     &lt;strong&gt;where&lt;/strong&gt; 范围 
&lt;/li&gt;
   &lt;li&gt;
更新：    &lt;strong&gt;update&lt;/strong&gt; table1     &lt;strong&gt;set&lt;/strong&gt; field1=value1     &lt;strong&gt;where&lt;/strong&gt; 范围 
&lt;/li&gt;
   &lt;li&gt;
查找：    &lt;strong&gt;select&lt;/strong&gt; *     &lt;strong&gt;from&lt;/strong&gt; table1     &lt;strong&gt;where&lt;/strong&gt; field1 like ’%value1%’ ---like的语法很精妙，查资料! 
&lt;/li&gt;
   &lt;li&gt;
排序：    &lt;strong&gt;select&lt;/strong&gt; *     &lt;strong&gt;from&lt;/strong&gt; table1     &lt;strong&gt;order&lt;/strong&gt;    &lt;strong&gt;by&lt;/strong&gt; field1,field2 [    &lt;strong&gt;desc&lt;/strong&gt;] 
&lt;/li&gt;
   &lt;li&gt;
总数：    &lt;strong&gt;select&lt;/strong&gt;count    &lt;strong&gt;as&lt;/strong&gt; totalcount     &lt;strong&gt;from&lt;/strong&gt; table1 
&lt;/li&gt;
   &lt;li&gt;
求和：    &lt;strong&gt;select&lt;/strong&gt;sum(field1)     &lt;strong&gt;as&lt;/strong&gt; sumvalue     &lt;strong&gt;from&lt;/strong&gt; table1 
&lt;/li&gt;
   &lt;li&gt;
平均：    &lt;strong&gt;select&lt;/strong&gt;avg(field1)     &lt;strong&gt;as&lt;/strong&gt; avgvalue     &lt;strong&gt;from&lt;/strong&gt; table1 
&lt;/li&gt;
   &lt;li&gt;
最大：    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;max&lt;/strong&gt;(field1)     &lt;strong&gt;as&lt;/strong&gt; maxvalue     &lt;strong&gt;from&lt;/strong&gt; table1 
&lt;/li&gt;
   &lt;li&gt;
最小：    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;min&lt;/strong&gt;(field1)     &lt;strong&gt;as&lt;/strong&gt; minvalue     &lt;strong&gt;from&lt;/strong&gt; table1 
&lt;/li&gt;
   &lt;li&gt;11、说明：几个高级查询运算词 &lt;/li&gt;
   &lt;li&gt;
A：     &lt;strong&gt;UNION&lt;/strong&gt; 运算符 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;UNION&lt;/strong&gt; 运算符通过组合其他两个结果表（例如 TABLE1 和 TABLE2）并消去表中任何重复行而派生出一个结果表。当 ALL 随     &lt;strong&gt;UNION&lt;/strong&gt; 一起使用时（即     &lt;strong&gt;UNION&lt;/strong&gt;ALL），不消除重复行。两种情况下，派生表的每一行不是来自 TABLE1 就是来自 TABLE2。 
&lt;/li&gt;
   &lt;li&gt;
B：     &lt;strong&gt;EXCEPT&lt;/strong&gt; 运算符 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;EXCEPT&lt;/strong&gt; 运算符通过包括所有在 TABLE1 中但不在 TABLE2 中的行并消除所有重复行而派生出一个结果表。当 ALL 随     &lt;strong&gt;EXCEPT&lt;/strong&gt; 一起使用时 (    &lt;strong&gt;EXCEPT&lt;/strong&gt;ALL)，不消除重复行。 
&lt;/li&gt;
   &lt;li&gt;
C：     &lt;strong&gt;INTERSECT&lt;/strong&gt; 运算符 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;INTERSECT&lt;/strong&gt; 运算符通过只包括 TABLE1 和 TABLE2 中都有的行并消除所有重复行而派生出一个结果表。当 ALL 随     &lt;strong&gt;INTERSECT&lt;/strong&gt; 一起使用时 (    &lt;strong&gt;INTERSECT&lt;/strong&gt;ALL)，不消除重复行。 
&lt;/li&gt;
   &lt;li&gt;注：使用运算词的几个查询结果行必须是一致的。 &lt;/li&gt;
   &lt;li&gt;12、说明：使用外连接 &lt;/li&gt;
   &lt;li&gt;
A、left （outer） join： 
&lt;/li&gt;
   &lt;li&gt;左外连接（左连接）：结果集几包括连接表的匹配行，也包括左连接表的所有行。 &lt;/li&gt;
   &lt;li&gt;
SQL:     &lt;strong&gt;select&lt;/strong&gt; a.a, a.b, a.c, b.c, b.d, b.f     &lt;strong&gt;from&lt;/strong&gt; a LEFT    &lt;strong&gt;OUT&lt;/strong&gt;JOIN b     &lt;strong&gt;ON&lt;/strong&gt; a.a = b.c 
&lt;/li&gt;
   &lt;li&gt;
B：right （outer） join: 
&lt;/li&gt;
   &lt;li&gt;右外连接(右连接)：结果集既包括连接表的匹配连接行，也包括右连接表的所有行。 &lt;/li&gt;
   &lt;li&gt;
C：    &lt;strong&gt;full&lt;/strong&gt;/cross （outer） join： 
&lt;/li&gt;
   &lt;li&gt;全外连接：不仅包括符号连接表的匹配行，还包括两个连接表中的所有记录。 &lt;/li&gt;
   &lt;li&gt;
12、分组:    &lt;strong&gt;Group&lt;/strong&gt;    &lt;strong&gt;by&lt;/strong&gt;: 
&lt;/li&gt;
   &lt;li&gt;一张表，一旦分组 完成后，查询后只能得到组相关的信息。 &lt;/li&gt;
   &lt;li&gt;
组相关的信息：（统计信息） count,sum,    &lt;strong&gt;max&lt;/strong&gt;,    &lt;strong&gt;min&lt;/strong&gt;,avg 分组的标准) 
&lt;/li&gt;
   &lt;li&gt;在SQLServer中分组时：不能以text,ntext,image类型的字段作为分组依据 &lt;/li&gt;
   &lt;li&gt;在selecte统计函数中的字段，不能和普通的字段放在一起； &lt;/li&gt;
   &lt;li&gt;13、对数据库进行操作： &lt;/li&gt;
   &lt;li&gt;分离数据库： sp_detach_db; 附加数据库：sp_attach_db 后接表明，附加需要完整的路径名 &lt;/li&gt;
   &lt;li&gt;14.如何修改数据库的名称: &lt;/li&gt;
   &lt;li&gt;
sp_renamedb &amp;apos;old_name&amp;apos;, &amp;apos;new_name&amp;apos;
&lt;/li&gt;
   &lt;li&gt;
&lt;/li&gt;   &lt;li&gt;二、提升 &lt;/li&gt;
   &lt;li&gt;1、说明：复制表(只复制结构,源表名：a 新表名：b) (Access可用) &lt;/li&gt;
   &lt;li&gt;
法一：    &lt;strong&gt;select&lt;/strong&gt; *     &lt;strong&gt;into&lt;/strong&gt; b     &lt;strong&gt;from&lt;/strong&gt; a     &lt;strong&gt;where&lt;/strong&gt; 1&amp;lt;&amp;gt;1（仅用于SQlServer） 
&lt;/li&gt;
   &lt;li&gt;
法二：    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;top&lt;/strong&gt; 0 *     &lt;strong&gt;into&lt;/strong&gt; b     &lt;strong&gt;from&lt;/strong&gt; a 
&lt;/li&gt;
   &lt;li&gt;2、说明：拷贝表(拷贝数据,源表名：a 目标表名：b) (Access可用) &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;insert&lt;/strong&gt;    &lt;strong&gt;into&lt;/strong&gt; b(a, b, c)     &lt;strong&gt;select&lt;/strong&gt; d,e,f     &lt;strong&gt;from&lt;/strong&gt; b; 
&lt;/li&gt;
   &lt;li&gt;3、说明：跨数据库之间表的拷贝(具体数据使用绝对路径) (Access可用) &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;insert&lt;/strong&gt;    &lt;strong&gt;into&lt;/strong&gt; b(a, b, c)     &lt;strong&gt;select&lt;/strong&gt; d,e,f     &lt;strong&gt;from&lt;/strong&gt; b in ‘具体数据库’     &lt;strong&gt;where&lt;/strong&gt; 条件 
&lt;/li&gt;
   &lt;li&gt;
例子：..    &lt;strong&gt;from&lt;/strong&gt; b in&amp;apos;&amp;quot;&amp;amp;Server.MapPath(&amp;quot;.&amp;quot;)&amp;amp;&amp;quot;\data.mdb&amp;quot; &amp;amp;&amp;quot;&amp;apos;    &lt;strong&gt;where&lt;/strong&gt;.. 
&lt;/li&gt;
   &lt;li&gt;4、说明：子查询(表名1：a 表名2：b) &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; a,b,c     &lt;strong&gt;from&lt;/strong&gt; a     &lt;strong&gt;where&lt;/strong&gt; a IN (    &lt;strong&gt;select&lt;/strong&gt; d     &lt;strong&gt;from&lt;/strong&gt; b ) 或者:     &lt;strong&gt;select&lt;/strong&gt; a,b,c     &lt;strong&gt;from&lt;/strong&gt; a     &lt;strong&gt;where&lt;/strong&gt; a IN (1,2,3) 
&lt;/li&gt;
   &lt;li&gt;5、说明：显示文章、提交人和最后回复时间 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; a.title,a.username,b.adddate     &lt;strong&gt;from&lt;/strong&gt;    &lt;strong&gt;table&lt;/strong&gt; a,(    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;max&lt;/strong&gt;(adddate) adddate     &lt;strong&gt;from&lt;/strong&gt;    &lt;strong&gt;table&lt;/strong&gt;    &lt;strong&gt;where&lt;/strong&gt;    &lt;strong&gt;table&lt;/strong&gt;.title=a.title) b 
&lt;/li&gt;
   &lt;li&gt;6、说明：外连接查询(表名1：a 表名2：b) &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; a.a, a.b, a.c, b.c, b.d, b.f     &lt;strong&gt;from&lt;/strong&gt; a LEFT    &lt;strong&gt;OUT&lt;/strong&gt;JOIN b     &lt;strong&gt;ON&lt;/strong&gt; a.a = b.c 
&lt;/li&gt;
   &lt;li&gt;7、说明：在线视图查询(表名1：a ) &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; *     &lt;strong&gt;from&lt;/strong&gt; (    &lt;strong&gt;SELECT&lt;/strong&gt; a,b,c     &lt;strong&gt;FROM&lt;/strong&gt; a) T     &lt;strong&gt;where&lt;/strong&gt; t.a &amp;gt; 1; 
&lt;/li&gt;
   &lt;li&gt;
8、说明：between的用法,between限制查询数据范围时包括了边界值,notbetween不包括 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; *     &lt;strong&gt;from&lt;/strong&gt; table1     &lt;strong&gt;where&lt;/strong&gt;    &lt;strong&gt;time&lt;/strong&gt;between time1 and time2 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; a,b,c,     &lt;strong&gt;from&lt;/strong&gt; table1     &lt;strong&gt;where&lt;/strong&gt; a notbetween 数值1 and 数值2 
&lt;/li&gt;
   &lt;li&gt;
9、说明：in 的使用方法 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; *     &lt;strong&gt;from&lt;/strong&gt; table1     &lt;strong&gt;where&lt;/strong&gt; a [not] in (‘值1’,’值2’,’值4’,’值6’) 
&lt;/li&gt;
   &lt;li&gt;10、说明：两张关联表，删除主表中已经在副表中没有的信息 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;delete&lt;/strong&gt;    &lt;strong&gt;from&lt;/strong&gt; table1     &lt;strong&gt;where&lt;/strong&gt;not exists (     &lt;strong&gt;select&lt;/strong&gt; *     &lt;strong&gt;from&lt;/strong&gt; table2     &lt;strong&gt;where&lt;/strong&gt; table1.field1=table2.field1 ) 
&lt;/li&gt;
   &lt;li&gt;11、说明：四表联查问题： &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; *     &lt;strong&gt;from&lt;/strong&gt; a left    &lt;strong&gt;inner&lt;/strong&gt;join b     &lt;strong&gt;on&lt;/strong&gt; a.a=b.b right    &lt;strong&gt;inner&lt;/strong&gt;join c     &lt;strong&gt;on&lt;/strong&gt; a.a=c.c     &lt;strong&gt;inner&lt;/strong&gt;join d     &lt;strong&gt;on&lt;/strong&gt; a.a=d.d     &lt;strong&gt;where&lt;/strong&gt; ..... 
&lt;/li&gt;
   &lt;li&gt;12、说明：日程安排提前五分钟提醒 &lt;/li&gt;
   &lt;li&gt;
SQL:     &lt;strong&gt;select&lt;/strong&gt; *     &lt;strong&gt;from&lt;/strong&gt; 日程安排     &lt;strong&gt;where&lt;/strong&gt; datediff(&amp;apos;minute&amp;apos;,f开始时间,getdate())&amp;gt;5 
&lt;/li&gt;
   &lt;li&gt;13、说明：一条sql 语句搞定数据库分页 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;top&lt;/strong&gt; 10 b.*     &lt;strong&gt;from&lt;/strong&gt; (    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;top&lt;/strong&gt; 20 主键字段,排序字段     &lt;strong&gt;from&lt;/strong&gt; 表名     &lt;strong&gt;order&lt;/strong&gt;    &lt;strong&gt;by&lt;/strong&gt; 排序字段     &lt;strong&gt;desc&lt;/strong&gt;) a,表名 b     &lt;strong&gt;where&lt;/strong&gt; b.主键字段 = a.主键字段     &lt;strong&gt;order&lt;/strong&gt;    &lt;strong&gt;by&lt;/strong&gt; a.排序字段 
&lt;/li&gt;
   &lt;li&gt;具体实现： &lt;/li&gt;
   &lt;li&gt;关于数据库分页： &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;declare&lt;/strong&gt; @start     &lt;strong&gt;int&lt;/strong&gt;,@    &lt;strong&gt;end&lt;/strong&gt;    &lt;strong&gt;int&lt;/strong&gt;
&lt;/li&gt;
   &lt;li&gt;@sql nvarchar(600) &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;set&lt;/strong&gt; @sql=’    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;top&lt;/strong&gt;’+str(@    &lt;strong&gt;end&lt;/strong&gt;-@start+1)+’+    &lt;strong&gt;from&lt;/strong&gt; T     &lt;strong&gt;where&lt;/strong&gt; rid notin(    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;top&lt;/strong&gt;’+str(@str-1)+’Rid     &lt;strong&gt;from&lt;/strong&gt; T     &lt;strong&gt;where&lt;/strong&gt; Rid&amp;gt;-1)’ 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;exec&lt;/strong&gt; sp_executesql @sql 
&lt;/li&gt;
   &lt;li&gt;
&lt;/li&gt;   &lt;li&gt;
注意：在    &lt;strong&gt;top&lt;/strong&gt;后不能直接跟一个变量，所以在实际应用中只有这样的进行特殊的处理。Rid为一个标识列，如果    &lt;strong&gt;top&lt;/strong&gt;后还有具体的字段，这样做是非常有好处的。因为这样可以避免     &lt;strong&gt;top&lt;/strong&gt;的字段如果是逻辑索引的，查询的结果后实际表中的不一致（逻辑索引中的数据有可能和数据表中的不一致，而查询时如果处在索引则首先查询索引） 
&lt;/li&gt;
   &lt;li&gt;14、说明：前10条记录 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;top&lt;/strong&gt; 10 * form table1     &lt;strong&gt;where&lt;/strong&gt; 范围 
&lt;/li&gt;
   &lt;li&gt;15、说明：选择在每一组b值相同的数据中对应的a最大的记录的所有信息(类似这样的用法可以用于论坛每月排行榜,每月热销产品分析,按科目成绩排名,等等.) &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; a,b,c     &lt;strong&gt;from&lt;/strong&gt; tablename ta     &lt;strong&gt;where&lt;/strong&gt; a=(    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;max&lt;/strong&gt;(a)     &lt;strong&gt;from&lt;/strong&gt; tablename tb     &lt;strong&gt;where&lt;/strong&gt; tb.b=ta.b) 
&lt;/li&gt;
   &lt;li&gt;16、说明：包括所有在 TableA 中但不在 TableB和TableC 中的行并消除所有重复行而派生出一个结果表 &lt;/li&gt;
   &lt;li&gt;
(    &lt;strong&gt;select&lt;/strong&gt; a     &lt;strong&gt;from&lt;/strong&gt; tableA )     &lt;strong&gt;except&lt;/strong&gt; (    &lt;strong&gt;select&lt;/strong&gt; a     &lt;strong&gt;from&lt;/strong&gt; tableB)     &lt;strong&gt;except&lt;/strong&gt; (    &lt;strong&gt;select&lt;/strong&gt; a     &lt;strong&gt;from&lt;/strong&gt; tableC) 
&lt;/li&gt;
   &lt;li&gt;17、说明：随机取出10条数据 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;top&lt;/strong&gt; 10 *     &lt;strong&gt;from&lt;/strong&gt; tablename     &lt;strong&gt;order&lt;/strong&gt;    &lt;strong&gt;by&lt;/strong&gt; newid() 
&lt;/li&gt;
   &lt;li&gt;18、说明：随机选择记录 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; newid() 
&lt;/li&gt;
   &lt;li&gt;19、说明：删除重复记录 &lt;/li&gt;
   &lt;li&gt;
1),    &lt;strong&gt;delete&lt;/strong&gt;    &lt;strong&gt;from&lt;/strong&gt; tablename     &lt;strong&gt;where&lt;/strong&gt; id notin (    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;max&lt;/strong&gt;(id)     &lt;strong&gt;from&lt;/strong&gt; tablename     &lt;strong&gt;group&lt;/strong&gt;    &lt;strong&gt;by&lt;/strong&gt; col1,col2,...) 
&lt;/li&gt;
   &lt;li&gt;
2),    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;distinct&lt;/strong&gt; *     &lt;strong&gt;into&lt;/strong&gt;    &lt;strong&gt;temp&lt;/strong&gt;    &lt;strong&gt;from&lt;/strong&gt; tablename 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;delete&lt;/strong&gt;    &lt;strong&gt;from&lt;/strong&gt; tablename 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;insert&lt;/strong&gt;    &lt;strong&gt;into&lt;/strong&gt; tablename     &lt;strong&gt;select&lt;/strong&gt; *     &lt;strong&gt;from&lt;/strong&gt;    &lt;strong&gt;temp&lt;/strong&gt;
&lt;/li&gt;
   &lt;li&gt;评价： 这种操作牵连大量的数据的移动，这种做法不适合大容量但数据操作 &lt;/li&gt;
   &lt;li&gt;3),例如：在一个外部表中导入数据，由于某些原因第一次只导入了一部分，但很难判断具体位置，这样只有在下一次全部导入，这样也就产生好多重复的字段，怎样删除重复字段 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;alter&lt;/strong&gt;    &lt;strong&gt;table&lt;/strong&gt; tablename 
&lt;/li&gt;
   &lt;li&gt;--添加一个自增列 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;add&lt;/strong&gt; column_b     &lt;strong&gt;int&lt;/strong&gt; identity(1,1) 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;delete&lt;/strong&gt;    &lt;strong&gt;from&lt;/strong&gt; tablename     &lt;strong&gt;where&lt;/strong&gt; column_b notin( 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;max&lt;/strong&gt;(column_b)     &lt;strong&gt;from&lt;/strong&gt; tablename     &lt;strong&gt;group&lt;/strong&gt;    &lt;strong&gt;by&lt;/strong&gt; column1,column2,...) 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;alter&lt;/strong&gt;    &lt;strong&gt;table&lt;/strong&gt; tablename     &lt;strong&gt;drop&lt;/strong&gt;    &lt;strong&gt;column&lt;/strong&gt; column_b 
&lt;/li&gt;
   &lt;li&gt;20、说明：列出数据库里所有的表名 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;name&lt;/strong&gt;    &lt;strong&gt;from&lt;/strong&gt; sysobjects     &lt;strong&gt;where&lt;/strong&gt; type=&amp;apos;U&amp;apos; // U代表用户 
&lt;/li&gt;
   &lt;li&gt;21、说明：列出表里的所有的列名 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;name&lt;/strong&gt;    &lt;strong&gt;from&lt;/strong&gt; syscolumns     &lt;strong&gt;where&lt;/strong&gt; id=object_id(&amp;apos;TableName&amp;apos;) 
&lt;/li&gt;
   &lt;li&gt;
22、说明：列示type、vender、pcs字段，以type字段排列，case可以方便地实现多重选择，类似    &lt;strong&gt;select&lt;/strong&gt; 中的case。 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; type,sum(case vender     &lt;strong&gt;when&lt;/strong&gt;&amp;apos;A&amp;apos;    &lt;strong&gt;then&lt;/strong&gt; pcs     &lt;strong&gt;else&lt;/strong&gt; 0     &lt;strong&gt;end&lt;/strong&gt;),sum(case vender     &lt;strong&gt;when&lt;/strong&gt;&amp;apos;C&amp;apos;    &lt;strong&gt;then&lt;/strong&gt; pcs     &lt;strong&gt;else&lt;/strong&gt; 0     &lt;strong&gt;end&lt;/strong&gt;),sum(case vender     &lt;strong&gt;when&lt;/strong&gt;&amp;apos;B&amp;apos;    &lt;strong&gt;then&lt;/strong&gt; pcs     &lt;strong&gt;else&lt;/strong&gt; 0     &lt;strong&gt;end&lt;/strong&gt;)     &lt;strong&gt;FROM&lt;/strong&gt; tablename     &lt;strong&gt;group&lt;/strong&gt;    &lt;strong&gt;by&lt;/strong&gt; type 
&lt;/li&gt;
   &lt;li&gt;显示结果： &lt;/li&gt;
   &lt;li&gt;type vender pcs &lt;/li&gt;
   &lt;li&gt;电脑 A 1 &lt;/li&gt;
   &lt;li&gt;电脑 A 1 &lt;/li&gt;
   &lt;li&gt;光盘 B 2 &lt;/li&gt;
   &lt;li&gt;光盘 A 2 &lt;/li&gt;
   &lt;li&gt;手机 B 3 &lt;/li&gt;
   &lt;li&gt;手机 C 3 &lt;/li&gt;
   &lt;li&gt;23、说明：初始化表table1 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;TRUNCATE&lt;/strong&gt;    &lt;strong&gt;TABLE&lt;/strong&gt; table1 
&lt;/li&gt;
   &lt;li&gt;24、说明：选择从10到15的记录 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;top&lt;/strong&gt; 5 *     &lt;strong&gt;from&lt;/strong&gt; (    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;top&lt;/strong&gt; 15 *     &lt;strong&gt;from&lt;/strong&gt;    &lt;strong&gt;table&lt;/strong&gt;    &lt;strong&gt;order&lt;/strong&gt;    &lt;strong&gt;by&lt;/strong&gt; id     &lt;strong&gt;asc&lt;/strong&gt;) table_别名     &lt;strong&gt;order&lt;/strong&gt;    &lt;strong&gt;by&lt;/strong&gt; id     &lt;strong&gt;desc&lt;/strong&gt;
&lt;/li&gt;
   &lt;li&gt;三、技巧 &lt;/li&gt;
   &lt;li&gt;1、1=1，1=2的使用，在SQL语句组合时用的较多 &lt;/li&gt;
   &lt;li&gt;
“    &lt;strong&gt;where&lt;/strong&gt; 1=1” 是表示选择全部 “    &lt;strong&gt;where&lt;/strong&gt; 1=2”全部不选， 
&lt;/li&gt;
   &lt;li&gt;如： &lt;/li&gt;
   &lt;li&gt;
if @strWhere !=&amp;apos;&amp;apos;
&lt;/li&gt;
   &lt;li&gt;    &lt;strong&gt;begin&lt;/strong&gt;&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;set&lt;/strong&gt; @strSQL = &amp;apos;select count(*) as Total from [&amp;apos; + @tblName + &amp;apos;] where &amp;apos; + @strWhere 
&lt;/li&gt;
   &lt;li&gt;    &lt;strong&gt;end&lt;/strong&gt;&lt;/li&gt;
   &lt;li&gt;    &lt;strong&gt;else&lt;/strong&gt;&lt;/li&gt;
   &lt;li&gt;    &lt;strong&gt;begin&lt;/strong&gt;&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;set&lt;/strong&gt; @strSQL = &amp;apos;select count(*) as Total from [&amp;apos; + @tblName + &amp;apos;]&amp;apos;
&lt;/li&gt;
   &lt;li&gt;    &lt;strong&gt;end&lt;/strong&gt;&lt;/li&gt;
   &lt;li&gt;我们可以直接写成 &lt;/li&gt;
   &lt;li&gt;错误！未找到目录项。 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;set&lt;/strong&gt; @strSQL = &amp;apos;select count(*) as Total from [&amp;apos; + @tblName + &amp;apos;] where 1=1 安定 &amp;apos;+ @strWhere 2、收缩数据库 
&lt;/li&gt;
   &lt;li&gt;--重建索引 &lt;/li&gt;
   &lt;li&gt;DBCC REINDEX &lt;/li&gt;
   &lt;li&gt;DBCC INDEXDEFRAG &lt;/li&gt;
   &lt;li&gt;--收缩数据和日志 &lt;/li&gt;
   &lt;li&gt;DBCC SHRINKDB &lt;/li&gt;
   &lt;li&gt;DBCC SHRINKFILE &lt;/li&gt;
   &lt;li&gt;3、压缩数据库 &lt;/li&gt;
   &lt;li&gt;dbcc shrinkdatabase(dbname) &lt;/li&gt;
   &lt;li&gt;4、转移数据库给新用户以已存在用户权限 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;exec&lt;/strong&gt; sp_change_users_login &amp;apos;update_one&amp;apos;,&amp;apos;newname&amp;apos;,&amp;apos;oldname&amp;apos;
&lt;/li&gt;
   &lt;li&gt;go &lt;/li&gt;
   &lt;li&gt;5、检查备份集 &lt;/li&gt;
   &lt;li&gt;
RESTORE VERIFYONLY     &lt;strong&gt;from&lt;/strong&gt; disk=&amp;apos;E:\dvbbs.bak&amp;apos;
&lt;/li&gt;
   &lt;li&gt;6、修复数据库 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;ALTER&lt;/strong&gt;    &lt;strong&gt;DATABASE&lt;/strong&gt; [dvbbs]     &lt;strong&gt;SET&lt;/strong&gt; SINGLE_USER 
&lt;/li&gt;
   &lt;li&gt;GO &lt;/li&gt;
   &lt;li&gt;
DBCC CHECKDB(&amp;apos;dvbbs&amp;apos;,repair_allow_data_loss)     &lt;strong&gt;WITH&lt;/strong&gt; TABLOCK 
&lt;/li&gt;
   &lt;li&gt;GO &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;ALTER&lt;/strong&gt;    &lt;strong&gt;DATABASE&lt;/strong&gt; [dvbbs]     &lt;strong&gt;SET&lt;/strong&gt; MULTI_USER 
&lt;/li&gt;
   &lt;li&gt;GO &lt;/li&gt;
   &lt;li&gt;7、日志清除 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;SET&lt;/strong&gt; NOCOUNT     &lt;strong&gt;ON&lt;/strong&gt;
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;DECLARE&lt;/strong&gt; @LogicalFileName sysname, 
&lt;/li&gt;
   &lt;li&gt;
@MaxMinutes     &lt;strong&gt;INT&lt;/strong&gt;, 
&lt;/li&gt;
   &lt;li&gt;
@NewSize     &lt;strong&gt;INT&lt;/strong&gt;
&lt;/li&gt;
   &lt;li&gt;
&lt;/li&gt;   &lt;li&gt;
USE tablename -- 要操作的数据库名 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;SELECT&lt;/strong&gt; @LogicalFileName = &amp;apos;tablename_log&amp;apos;, -- 日志文件名 
&lt;/li&gt;
   &lt;li&gt;
@MaxMinutes = 10, -- Limit on time allowed to wrap log. 
&lt;/li&gt;
   &lt;li&gt;
@NewSize = 1 -- 你想设定的日志文件的大小(M) 
&lt;/li&gt;
   &lt;li&gt;Setup / initialize &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;DECLARE&lt;/strong&gt; @OriginalSize     &lt;strong&gt;int&lt;/strong&gt;
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;SELECT&lt;/strong&gt; @OriginalSize =     &lt;strong&gt;size&lt;/strong&gt;
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;FROM&lt;/strong&gt; sysfiles 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;WHERE&lt;/strong&gt;    &lt;strong&gt;name&lt;/strong&gt; = @LogicalFileName 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;SELECT&lt;/strong&gt;&amp;apos;Original Size of &amp;apos; + db_name() + &amp;apos; LOG is &amp;apos; + 
&lt;/li&gt;
   &lt;li&gt;
CONVERT(    &lt;strong&gt;VARCHAR&lt;/strong&gt;(30),@OriginalSize) + &amp;apos; 8K pages or &amp;apos; + 
&lt;/li&gt;
   &lt;li&gt;
CONVERT(    &lt;strong&gt;VARCHAR&lt;/strong&gt;(30),(@OriginalSize*8/1024)) + &amp;apos;MB&amp;apos;
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;FROM&lt;/strong&gt; sysfiles 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;WHERE&lt;/strong&gt;    &lt;strong&gt;name&lt;/strong&gt; = @LogicalFileName 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;CREATE&lt;/strong&gt;    &lt;strong&gt;TABLE&lt;/strong&gt; DummyTrans 
&lt;/li&gt;
   &lt;li&gt;
(DummyColumn     &lt;strong&gt;char&lt;/strong&gt; (8000) notnull) 
&lt;/li&gt;
   &lt;li&gt;
&lt;/li&gt;   &lt;li&gt;
    &lt;strong&gt;DECLARE&lt;/strong&gt; @Counter     &lt;strong&gt;INT&lt;/strong&gt;, 
&lt;/li&gt;
   &lt;li&gt;@StartTime DATETIME, &lt;/li&gt;
   &lt;li&gt;
@TruncLog     &lt;strong&gt;VARCHAR&lt;/strong&gt;(255) 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;SELECT&lt;/strong&gt; @StartTime = GETDATE(), 
&lt;/li&gt;
   &lt;li&gt;
@TruncLog = &amp;apos;BACKUP LOG &amp;apos; + db_name() + &amp;apos; WITH TRUNCATE_ONLY&amp;apos;
&lt;/li&gt;
   &lt;li&gt;DBCC SHRINKFILE (@LogicalFileName, @NewSize) &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;EXEC&lt;/strong&gt; (@TruncLog) 
&lt;/li&gt;
   &lt;li&gt;-- Wrap the log if necessary. &lt;/li&gt;
   &lt;li&gt;
WHILE @MaxMinutes &amp;gt; DATEDIFF (mi, @StartTime, GETDATE()) -- time has not expired 
&lt;/li&gt;
   &lt;li&gt;
AND @OriginalSize = (    &lt;strong&gt;SELECT&lt;/strong&gt;    &lt;strong&gt;size&lt;/strong&gt;    &lt;strong&gt;FROM&lt;/strong&gt; sysfiles     &lt;strong&gt;WHERE&lt;/strong&gt;    &lt;strong&gt;name&lt;/strong&gt; = @LogicalFileName) 
&lt;/li&gt;
   &lt;li&gt;
AND (@OriginalSize * 8 /1024) &amp;gt; @NewSize 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;BEGIN&lt;/strong&gt;-- Outer loop. 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;SELECT&lt;/strong&gt; @Counter = 0 
&lt;/li&gt;
   &lt;li&gt;
WHILE ((@Counter &amp;lt; @OriginalSize / 16) AND (@Counter &amp;lt; 50000)) 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;BEGIN&lt;/strong&gt;-- update 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;INSERT&lt;/strong&gt; DummyTrans     &lt;strong&gt;VALUES&lt;/strong&gt; (&amp;apos;Fill Log&amp;apos;)     &lt;strong&gt;DELETE&lt;/strong&gt; DummyTrans 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;SELECT&lt;/strong&gt; @Counter = @Counter + 1 
&lt;/li&gt;
   &lt;li&gt;    &lt;strong&gt;END&lt;/strong&gt;&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;EXEC&lt;/strong&gt; (@TruncLog) 
&lt;/li&gt;
   &lt;li&gt;    &lt;strong&gt;END&lt;/strong&gt;&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;SELECT&lt;/strong&gt;&amp;apos;Final Size of &amp;apos; + db_name() + &amp;apos; LOG is &amp;apos; + 
&lt;/li&gt;
   &lt;li&gt;
CONVERT(    &lt;strong&gt;VARCHAR&lt;/strong&gt;(30),    &lt;strong&gt;size&lt;/strong&gt;) + &amp;apos; 8K pages or &amp;apos; + 
&lt;/li&gt;
   &lt;li&gt;
CONVERT(    &lt;strong&gt;VARCHAR&lt;/strong&gt;(30),(    &lt;strong&gt;size&lt;/strong&gt;*8/1024)) + &amp;apos;MB&amp;apos;
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;FROM&lt;/strong&gt; sysfiles 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;WHERE&lt;/strong&gt;    &lt;strong&gt;name&lt;/strong&gt; = @LogicalFileName 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;DROP&lt;/strong&gt;    &lt;strong&gt;TABLE&lt;/strong&gt; DummyTrans 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;SET&lt;/strong&gt; NOCOUNT     &lt;strong&gt;OFF&lt;/strong&gt;
&lt;/li&gt;
   &lt;li&gt;8、说明：更改某个表 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;exec&lt;/strong&gt; sp_changeobjectowner &amp;apos;tablename&amp;apos;,&amp;apos;dbo&amp;apos;
&lt;/li&gt;
   &lt;li&gt;9、存储更改全部表 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;CREATE&lt;/strong&gt;    &lt;strong&gt;PROCEDURE&lt;/strong&gt; dbo.User_ChangeObjectOwnerBatch 
&lt;/li&gt;
   &lt;li&gt;
@OldOwner     &lt;strong&gt;as&lt;/strong&gt; NVARCHAR(128), 
&lt;/li&gt;
   &lt;li&gt;
@NewOwner     &lt;strong&gt;as&lt;/strong&gt; NVARCHAR(128) 
&lt;/li&gt;
   &lt;li&gt;    &lt;strong&gt;AS&lt;/strong&gt;&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;DECLARE&lt;/strong&gt; @    &lt;strong&gt;Name&lt;/strong&gt;    &lt;strong&gt;as&lt;/strong&gt; NVARCHAR(128) 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;DECLARE&lt;/strong&gt; @Owner     &lt;strong&gt;as&lt;/strong&gt; NVARCHAR(128) 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;DECLARE&lt;/strong&gt; @OwnerName     &lt;strong&gt;as&lt;/strong&gt; NVARCHAR(128) 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;DECLARE&lt;/strong&gt; curObject     &lt;strong&gt;CURSOR&lt;/strong&gt;    &lt;strong&gt;FOR&lt;/strong&gt;
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt;&amp;apos;Name&amp;apos; =     &lt;strong&gt;name&lt;/strong&gt;, 
&lt;/li&gt;
   &lt;li&gt;
&amp;apos;Owner&amp;apos; = user_name(uid) 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;from&lt;/strong&gt; sysobjects 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;where&lt;/strong&gt; user_name(uid)=@OldOwner 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;order&lt;/strong&gt;    &lt;strong&gt;by&lt;/strong&gt;    &lt;strong&gt;name&lt;/strong&gt;
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;OPEN&lt;/strong&gt; curObject 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;FETCH&lt;/strong&gt;    &lt;strong&gt;NEXT&lt;/strong&gt;    &lt;strong&gt;FROM&lt;/strong&gt; curObject     &lt;strong&gt;INTO&lt;/strong&gt; @    &lt;strong&gt;Name&lt;/strong&gt;, @Owner 
&lt;/li&gt;
   &lt;li&gt;WHILE(@@FETCH_STATUS=0) &lt;/li&gt;
   &lt;li&gt;    &lt;strong&gt;BEGIN&lt;/strong&gt;&lt;/li&gt;
   &lt;li&gt;if @Owner=@OldOwner &lt;/li&gt;
   &lt;li&gt;    &lt;strong&gt;begin&lt;/strong&gt;&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;set&lt;/strong&gt; @OwnerName = @OldOwner + &amp;apos;.&amp;apos; + rtrim(@    &lt;strong&gt;Name&lt;/strong&gt;) 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;exec&lt;/strong&gt; sp_changeobjectowner @OwnerName, @NewOwner 
&lt;/li&gt;
   &lt;li&gt;    &lt;strong&gt;end&lt;/strong&gt;&lt;/li&gt;
   &lt;li&gt;-- select @name,@NewOwner,@OldOwner &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;FETCH&lt;/strong&gt;    &lt;strong&gt;NEXT&lt;/strong&gt;    &lt;strong&gt;FROM&lt;/strong&gt; curObject     &lt;strong&gt;INTO&lt;/strong&gt; @    &lt;strong&gt;Name&lt;/strong&gt;, @Owner 
&lt;/li&gt;
   &lt;li&gt;    &lt;strong&gt;END&lt;/strong&gt;&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;close&lt;/strong&gt; curObject 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;deallocate&lt;/strong&gt; curObject 
&lt;/li&gt;
   &lt;li&gt;GO &lt;/li&gt;
   &lt;li&gt;
&lt;/li&gt;   &lt;li&gt;10、SQL SERVER中直接循环写入数据 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;declare&lt;/strong&gt; @i     &lt;strong&gt;int&lt;/strong&gt;
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;set&lt;/strong&gt; @i=1 
&lt;/li&gt;
   &lt;li&gt;while @i&amp;lt;30 &lt;/li&gt;
   &lt;li&gt;    &lt;strong&gt;begin&lt;/strong&gt;&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;insert&lt;/strong&gt;    &lt;strong&gt;into&lt;/strong&gt; test (userid)     &lt;strong&gt;values&lt;/strong&gt;(@i) 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;set&lt;/strong&gt; @i=@i+1 
&lt;/li&gt;
   &lt;li&gt;    &lt;strong&gt;end&lt;/strong&gt;&lt;/li&gt;
   &lt;li&gt;案例： &lt;/li&gt;
   &lt;li&gt;有如下表，要求就裱中所有沒有及格的成績，在每次增長0.1的基礎上，使他們剛好及格: &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;Name&lt;/strong&gt; score 
&lt;/li&gt;
   &lt;li&gt;Zhangshan 80 &lt;/li&gt;
   &lt;li&gt;Lishi 59 &lt;/li&gt;
   &lt;li&gt;Wangwu 50 &lt;/li&gt;
   &lt;li&gt;Songquan 69 &lt;/li&gt;
   &lt;li&gt;
while((    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;min&lt;/strong&gt;(score)     &lt;strong&gt;from&lt;/strong&gt; tb_table)&amp;lt;60) 
&lt;/li&gt;
   &lt;li&gt;    &lt;strong&gt;begin&lt;/strong&gt;&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;update&lt;/strong&gt; tb_table     &lt;strong&gt;set&lt;/strong&gt; score =score*1.01 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;where&lt;/strong&gt; score&amp;lt;60 
&lt;/li&gt;
   &lt;li&gt;
if (    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;min&lt;/strong&gt;(score)     &lt;strong&gt;from&lt;/strong&gt; tb_table)&amp;gt;60 
&lt;/li&gt;
   &lt;li&gt;break &lt;/li&gt;
   &lt;li&gt;    &lt;strong&gt;else&lt;/strong&gt;&lt;/li&gt;
   &lt;li&gt;    &lt;strong&gt;continue&lt;/strong&gt;&lt;/li&gt;
   &lt;li&gt;    &lt;strong&gt;end&lt;/strong&gt;&lt;/li&gt;
   &lt;li&gt;
&lt;/li&gt;   &lt;li&gt;数据开发-经典 &lt;/li&gt;
   &lt;li&gt;
&lt;/li&gt;   &lt;li&gt;1.按姓氏笔画排序: &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;Select&lt;/strong&gt; *     &lt;strong&gt;From&lt;/strong&gt; TableName     &lt;strong&gt;Order&lt;/strong&gt;    &lt;strong&gt;By&lt;/strong&gt; CustomerName     &lt;strong&gt;Collate&lt;/strong&gt; Chinese_PRC_Stroke_ci_as //从少到多 
&lt;/li&gt;
   &lt;li&gt;2.数据库加密: &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; encrypt(&amp;apos;原始密码&amp;apos;) 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; pwdencrypt(&amp;apos;原始密码&amp;apos;) 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; pwdcompare(&amp;apos;原始密码&amp;apos;,&amp;apos;加密后密码&amp;apos;) = 1--相同；否则不相同 encrypt(&amp;apos;原始密码&amp;apos;) 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; pwdencrypt(&amp;apos;原始密码&amp;apos;) 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; pwdcompare(&amp;apos;原始密码&amp;apos;,&amp;apos;加密后密码&amp;apos;) = 1--相同；否则不相同 
&lt;/li&gt;
   &lt;li&gt;3.取回表中字段: &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;declare&lt;/strong&gt; @list     &lt;strong&gt;varchar&lt;/strong&gt;(1000), 
&lt;/li&gt;
   &lt;li&gt;@sql nvarchar(1000) &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; @list=@list+&amp;apos;,&amp;apos;+b.    &lt;strong&gt;name&lt;/strong&gt;    &lt;strong&gt;from&lt;/strong&gt; sysobjects a,syscolumns b     &lt;strong&gt;where&lt;/strong&gt; a.id=b.id and a.    &lt;strong&gt;name&lt;/strong&gt;=&amp;apos;表A&amp;apos;
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;set&lt;/strong&gt; @sql=&amp;apos;select &amp;apos;+right(@list,len(@list)-1)+&amp;apos; from 表A&amp;apos;
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;exec&lt;/strong&gt; (@sql) 
&lt;/li&gt;
   &lt;li&gt;4.查看硬盘分区: &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;EXEC&lt;/strong&gt; master..xp_fixeddrives 
&lt;/li&gt;
   &lt;li&gt;5.比较A,B表是否相等: &lt;/li&gt;
   &lt;li&gt;
if (    &lt;strong&gt;select&lt;/strong&gt; checksum_agg(binary_checksum(*))     &lt;strong&gt;from&lt;/strong&gt; A) 
&lt;/li&gt;
   &lt;li&gt;= &lt;/li&gt;
   &lt;li&gt;
(    &lt;strong&gt;select&lt;/strong&gt; checksum_agg(binary_checksum(*))     &lt;strong&gt;from&lt;/strong&gt; B) 
&lt;/li&gt;
   &lt;li&gt;
print &amp;apos;相等&amp;apos;
&lt;/li&gt;
   &lt;li&gt;    &lt;strong&gt;else&lt;/strong&gt;&lt;/li&gt;
   &lt;li&gt;
print &amp;apos;不相等&amp;apos;
&lt;/li&gt;
   &lt;li&gt;6.杀掉所有的事件探察器进程: &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;DECLARE&lt;/strong&gt; hcforeach     &lt;strong&gt;CURSOR&lt;/strong&gt;    &lt;strong&gt;GLOBAL&lt;/strong&gt;    &lt;strong&gt;FOR&lt;/strong&gt;    &lt;strong&gt;SELECT&lt;/strong&gt;&amp;apos;kill &amp;apos;+RTRIM(spid)     &lt;strong&gt;FROM&lt;/strong&gt; master.dbo.sysprocesses 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;WHERE&lt;/strong&gt; program_name IN(&amp;apos;SQL profiler&amp;apos;,N&amp;apos;SQL 事件探查器&amp;apos;) 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;EXEC&lt;/strong&gt; sp_msforeach_worker &amp;apos;?&amp;apos;
&lt;/li&gt;
   &lt;li&gt;7.记录搜索: &lt;/li&gt;
   &lt;li&gt;开头到N条记录 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;Select&lt;/strong&gt;    &lt;strong&gt;Top&lt;/strong&gt; N *     &lt;strong&gt;From&lt;/strong&gt; 表 
&lt;/li&gt;
   &lt;li&gt;------------------------------- &lt;/li&gt;
   &lt;li&gt;N到M条记录(要有主索引ID) &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;Select&lt;/strong&gt;    &lt;strong&gt;Top&lt;/strong&gt; M-N *     &lt;strong&gt;From&lt;/strong&gt; 表     &lt;strong&gt;Where&lt;/strong&gt; ID in (    &lt;strong&gt;Select&lt;/strong&gt;    &lt;strong&gt;Top&lt;/strong&gt; M ID     &lt;strong&gt;From&lt;/strong&gt; 表)     &lt;strong&gt;Order&lt;/strong&gt;    &lt;strong&gt;by&lt;/strong&gt; ID     &lt;strong&gt;Desc&lt;/strong&gt;
&lt;/li&gt;
   &lt;li&gt;---------------------------------- &lt;/li&gt;
   &lt;li&gt;N到结尾记录 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;Select&lt;/strong&gt;    &lt;strong&gt;Top&lt;/strong&gt; N *     &lt;strong&gt;From&lt;/strong&gt; 表     &lt;strong&gt;Order&lt;/strong&gt;    &lt;strong&gt;by&lt;/strong&gt; ID     &lt;strong&gt;Desc&lt;/strong&gt;
&lt;/li&gt;
   &lt;li&gt;案例 &lt;/li&gt;
   &lt;li&gt;例如1：一张表有一万多条记录，表的第一个字段 RecID 是自增长字段， 写一个SQL语句， 找出表的第31到第40个记录。 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;top&lt;/strong&gt; 10 recid     &lt;strong&gt;from&lt;/strong&gt; A     &lt;strong&gt;where&lt;/strong&gt; recid notin(    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;top&lt;/strong&gt; 30 recid     &lt;strong&gt;from&lt;/strong&gt; A) 
&lt;/li&gt;
   &lt;li&gt;分析：如果这样写会产生某些问题，如果recid在表中存在逻辑索引。 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;top&lt;/strong&gt; 10 recid     &lt;strong&gt;from&lt;/strong&gt; A     &lt;strong&gt;where&lt;/strong&gt;……是从索引中查找，而后面的    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;top&lt;/strong&gt; 30 recid     &lt;strong&gt;from&lt;/strong&gt; A则在数据表中查找，这样由于索引中的顺序有可能和数据表中的不一致，这样就导致查询到的不是本来的欲得到的数据。 
&lt;/li&gt;
   &lt;li&gt;解决方案 &lt;/li&gt;
   &lt;li&gt;
1， 用    &lt;strong&gt;order&lt;/strong&gt;    &lt;strong&gt;by&lt;/strong&gt;    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;top&lt;/strong&gt; 30 recid     &lt;strong&gt;from&lt;/strong&gt; A     &lt;strong&gt;order&lt;/strong&gt;    &lt;strong&gt;by&lt;/strong&gt; ricid 如果该字段不是自增长，就会出现问题 
&lt;/li&gt;
   &lt;li&gt;
2， 在那个子查询中也加条件：    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;top&lt;/strong&gt; 30 recid     &lt;strong&gt;from&lt;/strong&gt; A     &lt;strong&gt;where&lt;/strong&gt; recid&amp;gt;-1 
&lt;/li&gt;
   &lt;li&gt;例2：查询表中的最后以条记录，并不知道这个表共有多少数据,以及表结构。 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;set&lt;/strong&gt; @s = &amp;apos;select top 1 * from T where pid not in (select top &amp;apos; + str(@count-1) + &amp;apos; pid from T)&amp;apos;
&lt;/li&gt;
   &lt;li&gt;
print @s     &lt;strong&gt;exec&lt;/strong&gt; sp_executesql @s 
&lt;/li&gt;
   &lt;li&gt;9：获取当前数据库中的所有用户表 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;Name&lt;/strong&gt;    &lt;strong&gt;from&lt;/strong&gt; sysobjects     &lt;strong&gt;where&lt;/strong&gt; xtype=&amp;apos;u&amp;apos;and status&amp;gt;=0 
&lt;/li&gt;
   &lt;li&gt;10：获取某一个表的所有字段 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;name&lt;/strong&gt;    &lt;strong&gt;from&lt;/strong&gt; syscolumns     &lt;strong&gt;where&lt;/strong&gt; id=object_id(&amp;apos;表名&amp;apos;) 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;name&lt;/strong&gt;    &lt;strong&gt;from&lt;/strong&gt; syscolumns     &lt;strong&gt;where&lt;/strong&gt; id in (    &lt;strong&gt;select&lt;/strong&gt; id     &lt;strong&gt;from&lt;/strong&gt; sysobjects     &lt;strong&gt;where&lt;/strong&gt; type = &amp;apos;u&amp;apos;and    &lt;strong&gt;name&lt;/strong&gt; = &amp;apos;表名&amp;apos;) 
&lt;/li&gt;
   &lt;li&gt;两种方式的效果相同 &lt;/li&gt;
   &lt;li&gt;11：查看与某一个表相关的视图、存储过程、函数 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; a.*     &lt;strong&gt;from&lt;/strong&gt; sysobjects a, syscomments b     &lt;strong&gt;where&lt;/strong&gt; a.id = b.id and b.text like&amp;apos;%表名%&amp;apos;
&lt;/li&gt;
   &lt;li&gt;12：查看当前数据库中所有存储过程 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt;    &lt;strong&gt;name&lt;/strong&gt;    &lt;strong&gt;as&lt;/strong&gt; 存储过程名称     &lt;strong&gt;from&lt;/strong&gt; sysobjects     &lt;strong&gt;where&lt;/strong&gt; xtype=&amp;apos;P&amp;apos;
&lt;/li&gt;
   &lt;li&gt;13：查询用户创建的所有数据库 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; *     &lt;strong&gt;from&lt;/strong&gt; master..sysdatabases D     &lt;strong&gt;where&lt;/strong&gt; sid notin(    &lt;strong&gt;select&lt;/strong&gt; sid     &lt;strong&gt;from&lt;/strong&gt; master..syslogins     &lt;strong&gt;where&lt;/strong&gt;    &lt;strong&gt;name&lt;/strong&gt;=&amp;apos;sa&amp;apos;) 
&lt;/li&gt;
   &lt;li&gt;或者 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; dbid,     &lt;strong&gt;name&lt;/strong&gt;    &lt;strong&gt;AS&lt;/strong&gt; DB_NAME     &lt;strong&gt;from&lt;/strong&gt; master..sysdatabases     &lt;strong&gt;where&lt;/strong&gt; sid &amp;lt;&amp;gt; 0x01 
&lt;/li&gt;
   &lt;li&gt;14：查询某一个表的字段和数据类型 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; column_name,data_type     &lt;strong&gt;from&lt;/strong&gt; information_schema.columns 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;where&lt;/strong&gt; table_name = &amp;apos;表名&amp;apos;
&lt;/li&gt;
   &lt;li&gt;15：不同服务器数据库之间的数据操作 &lt;/li&gt;
   &lt;li&gt;--创建链接服务器 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;exec&lt;/strong&gt; sp_addlinkedserver &amp;apos;ITSV &amp;apos;, &amp;apos; &amp;apos;, &amp;apos;SQLOLEDB &amp;apos;, &amp;apos;远程服务器名或ip地址 &amp;apos;
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;exec&lt;/strong&gt; sp_addlinkedsrvlogin &amp;apos;ITSV &amp;apos;, &amp;apos;false &amp;apos;,null, &amp;apos;用户名 &amp;apos;, &amp;apos;密码 &amp;apos;
&lt;/li&gt;
   &lt;li&gt;--查询示例 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; *     &lt;strong&gt;from&lt;/strong&gt; ITSV.数据库名.dbo.表名 
&lt;/li&gt;
   &lt;li&gt;--导入示例 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; *     &lt;strong&gt;into&lt;/strong&gt; 表     &lt;strong&gt;from&lt;/strong&gt; ITSV.数据库名.dbo.表名 
&lt;/li&gt;
   &lt;li&gt;--以后不再使用时删除链接服务器 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;exec&lt;/strong&gt; sp_dropserver &amp;apos;ITSV &amp;apos;, &amp;apos;droplogins &amp;apos;
&lt;/li&gt;
   &lt;li&gt;
&lt;/li&gt;   &lt;li&gt;--连接远程/局域网数据(openrowset/openquery/opendatasource) &lt;/li&gt;
   &lt;li&gt;--1、openrowset &lt;/li&gt;
   &lt;li&gt;--查询示例 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; *     &lt;strong&gt;from&lt;/strong&gt; openrowset( &amp;apos;SQLOLEDB &amp;apos;, &amp;apos;sql服务器名 &amp;apos;; &amp;apos;用户名 &amp;apos;; &amp;apos;密码 &amp;apos;,数据库名.dbo.表名) 
&lt;/li&gt;
   &lt;li&gt;--生成本地表 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; *     &lt;strong&gt;into&lt;/strong&gt; 表     &lt;strong&gt;from&lt;/strong&gt; openrowset( &amp;apos;SQLOLEDB &amp;apos;, &amp;apos;sql服务器名 &amp;apos;; &amp;apos;用户名 &amp;apos;; &amp;apos;密码 &amp;apos;,数据库名.dbo.表名) 
&lt;/li&gt;
   &lt;li&gt;
&lt;/li&gt;   &lt;li&gt;--把本地表导入远程表 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;insert&lt;/strong&gt; openrowset( &amp;apos;SQLOLEDB &amp;apos;, &amp;apos;sql服务器名 &amp;apos;; &amp;apos;用户名 &amp;apos;; &amp;apos;密码 &amp;apos;,数据库名.dbo.表名) 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; *    &lt;strong&gt;from&lt;/strong&gt; 本地表 
&lt;/li&gt;
   &lt;li&gt;--更新本地表 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;update&lt;/strong&gt; b 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;set&lt;/strong&gt; b.列A=a.列A 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;from&lt;/strong&gt; openrowset( &amp;apos;SQLOLEDB &amp;apos;, &amp;apos;sql服务器名 &amp;apos;; &amp;apos;用户名 &amp;apos;; &amp;apos;密码 &amp;apos;,数据库名.dbo.表名)    &lt;strong&gt;as&lt;/strong&gt; a     &lt;strong&gt;inner&lt;/strong&gt;join 本地表 b 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;on&lt;/strong&gt; a.column1=b.column1 
&lt;/li&gt;
   &lt;li&gt;--openquery用法需要创建一个连接 &lt;/li&gt;
   &lt;li&gt;--首先创建一个连接创建链接服务器 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;exec&lt;/strong&gt; sp_addlinkedserver &amp;apos;ITSV &amp;apos;, &amp;apos; &amp;apos;, &amp;apos;SQLOLEDB &amp;apos;, &amp;apos;远程服务器名或ip地址 &amp;apos;
&lt;/li&gt;
   &lt;li&gt;--查询 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; * 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;FROM&lt;/strong&gt; openquery(ITSV, &amp;apos;SELECT * FROM 数据库.dbo.表名 &amp;apos;) 
&lt;/li&gt;
   &lt;li&gt;--把本地表导入远程表 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;insert&lt;/strong&gt; openquery(ITSV, &amp;apos;SELECT * FROM 数据库.dbo.表名 &amp;apos;) 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; *     &lt;strong&gt;from&lt;/strong&gt; 本地表 
&lt;/li&gt;
   &lt;li&gt;--更新本地表 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;update&lt;/strong&gt; b 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;set&lt;/strong&gt; b.列B=a.列B 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;FROM&lt;/strong&gt; openquery(ITSV, &amp;apos;SELECT * FROM 数据库.dbo.表名 &amp;apos;)     &lt;strong&gt;as&lt;/strong&gt; a 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;inner&lt;/strong&gt;join 本地表 b     &lt;strong&gt;on&lt;/strong&gt; a.列A=b.列A 
&lt;/li&gt;
   &lt;li&gt;
&lt;/li&gt;   &lt;li&gt;--3、opendatasource/openrowset &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;SELECT&lt;/strong&gt; * 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;FROM&lt;/strong&gt; opendatasource( &amp;apos;SQLOLEDB &amp;apos;, &amp;apos;Data Source=ip/ServerName;User ID=登陆名;Password=密码 &amp;apos; ).test.dbo.roy_ta 
&lt;/li&gt;
   &lt;li&gt;--把本地表导入远程表 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;insert&lt;/strong&gt; opendatasource( &amp;apos;SQLOLEDB &amp;apos;, &amp;apos;Data Source=ip/ServerName;User ID=登陆名;Password=密码 &amp;apos;).数据库.dbo.表名 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; *     &lt;strong&gt;from&lt;/strong&gt; 本地表 
&lt;/li&gt;
   &lt;li&gt;SQL Server基本函数 &lt;/li&gt;
   &lt;li&gt;SQL Server基本函数 &lt;/li&gt;
   &lt;li&gt;1.字符串函数 长度与分析用 &lt;/li&gt;
   &lt;li&gt;1,datalength(Char_expr) 返回字符串包含字符数,但不包含后面的空格 &lt;/li&gt;
   &lt;li&gt;
2,substring(expression,start,length) 取子串，字符串的下标是从“1”，start为起始位置，length为字符串长度，实际应用中以len(expression)取得其长度 
&lt;/li&gt;
   &lt;li&gt;
3,right(char_expr,int_expr) 返回字符串右边第int_expr个字符，还用left于之相反 
&lt;/li&gt;
   &lt;li&gt;
4,isnull( check_expression , replacement_value )如果check_expression為空，則返回replacement_value的值，不為空，就返回check_expression字符操作类 
&lt;/li&gt;
   &lt;li&gt;5,Sp_addtype 自定義數據類型 &lt;/li&gt;
   &lt;li&gt;
例如：    &lt;strong&gt;EXEC&lt;/strong&gt; sp_addtype birthday, datetime, &amp;apos;NULL&amp;apos;
&lt;/li&gt;
   &lt;li&gt;
6,    &lt;strong&gt;set&lt;/strong&gt; nocount {    &lt;strong&gt;on&lt;/strong&gt;|    &lt;strong&gt;off&lt;/strong&gt;} 
&lt;/li&gt;
   &lt;li&gt;
使返回的结果中不包含有关受 Transact-SQL 语句影响的行数的信息。如果存储过程中包含的一些语句并不返回许多实际的数据，则该设置由于大量减少了网络流量，因此可显著提高性能。    &lt;strong&gt;SET&lt;/strong&gt; NOCOUNT 设置是在执行或运行时设置，而不是在分析时设置。 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;SET&lt;/strong&gt; NOCOUNT 为     &lt;strong&gt;ON&lt;/strong&gt; 时，不返回计数（表示受 Transact-SQL 语句影响的行数）。 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;SET&lt;/strong&gt; NOCOUNT 为     &lt;strong&gt;OFF&lt;/strong&gt; 时，返回计数 
&lt;/li&gt;
   &lt;li&gt;常识 &lt;/li&gt;
   &lt;li&gt;
&lt;/li&gt;   &lt;li&gt;
在SQL查询中：    &lt;strong&gt;from&lt;/strong&gt;后最多可以跟多少张表或视图：256 
&lt;/li&gt;
   &lt;li&gt;
在SQL语句中出现     &lt;strong&gt;Order&lt;/strong&gt;    &lt;strong&gt;by&lt;/strong&gt;,查询时，先排序，后取 
&lt;/li&gt;
   &lt;li&gt;在SQL中，一个字段的最大容量是8000，而对于nvarchar(4000),由于nvarchar是Unicode码。 &lt;/li&gt;
   &lt;li&gt;
&lt;/li&gt;   &lt;li&gt;SQLServer2000同步复制技术实现步骤 &lt;/li&gt;
   &lt;li&gt;一、 预备工作 &lt;/li&gt;
   &lt;li&gt;1.发布服务器,订阅服务器都创建一个同名的windows用户,并设置相同的密码,做为发布快照文件夹的有效访问用户 &lt;/li&gt;
   &lt;li&gt;--管理工具 &lt;/li&gt;
   &lt;li&gt;--计算机管理 &lt;/li&gt;
   &lt;li&gt;--用户和组 &lt;/li&gt;
   &lt;li&gt;--右键用户 &lt;/li&gt;
   &lt;li&gt;--新建用户 &lt;/li&gt;
   &lt;li&gt;--建立一个隶属于administrator组的登陆windows的用户（SynUser） &lt;/li&gt;
   &lt;li&gt;2.在发布服务器上,新建一个共享目录,做为发布的快照文件的存放目录,操作: &lt;/li&gt;
   &lt;li&gt;
我的电脑--D:\ 新建一个目录,名为: PUB 
&lt;/li&gt;
   &lt;li&gt;--右键这个新建的目录 &lt;/li&gt;
   &lt;li&gt;--属性--共享 &lt;/li&gt;
   &lt;li&gt;--选择&amp;quot;共享该文件夹&amp;quot; &lt;/li&gt;
   &lt;li&gt;--通过&amp;quot;权限&amp;quot;按纽来设置具体的用户权限,保证第一步中创建的用户(SynUser) 具有对该文件夹的所有权限 &lt;/li&gt;
   &lt;li&gt;
&lt;/li&gt;   &lt;li&gt;--确定 &lt;/li&gt;
   &lt;li&gt;3.设置SQL代理(SQLSERVERAGENT)服务的启动用户(发布/订阅服务器均做此设置) &lt;/li&gt;
   &lt;li&gt;
开始--程序--管理工具--服务 
&lt;/li&gt;
   &lt;li&gt;--右键SQLSERVERAGENT &lt;/li&gt;
   &lt;li&gt;--属性--登陆--选择&amp;quot;此账户&amp;quot; &lt;/li&gt;
   &lt;li&gt;--输入或者选择第一步中创建的windows登录用户名（SynUser） &lt;/li&gt;
   &lt;li&gt;--&amp;quot;密码&amp;quot;中输入该用户的密码 &lt;/li&gt;
   &lt;li&gt;4.设置SQL Server身份验证模式,解决连接时的权限问题(发布/订阅服务器均做此设置) &lt;/li&gt;
   &lt;li&gt;企业管理器 &lt;/li&gt;
   &lt;li&gt;--右键SQL实例--属性 &lt;/li&gt;
   &lt;li&gt;--安全性--身份验证 &lt;/li&gt;
   &lt;li&gt;--选择&amp;quot;SQL Server 和 Windows&amp;quot; &lt;/li&gt;
   &lt;li&gt;--确定 &lt;/li&gt;
   &lt;li&gt;5.在发布服务器和订阅服务器上互相注册 &lt;/li&gt;
   &lt;li&gt;企业管理器 &lt;/li&gt;
   &lt;li&gt;--右键SQL Server组 &lt;/li&gt;
   &lt;li&gt;--新建SQL Server注册... &lt;/li&gt;
   &lt;li&gt;--下一步--可用的服务器中,输入你要注册的远程服务器名 --添加 &lt;/li&gt;
   &lt;li&gt;--下一步--连接使用,选择第二个&amp;quot;SQL Server身份验证&amp;quot; &lt;/li&gt;
   &lt;li&gt;--下一步--输入用户名和密码（SynUser） &lt;/li&gt;
   &lt;li&gt;--下一步--选择SQL Server组,也可以创建一个新组 &lt;/li&gt;
   &lt;li&gt;--下一步--完成 &lt;/li&gt;
   &lt;li&gt;6.对于只能用IP,不能用计算机名的,为其注册服务器别名（此步在实施中没用到） &lt;/li&gt;
   &lt;li&gt;(在连接端配置,比如,在订阅服务器上配置的话,服务器名称中输入的是发布服务器的IP) &lt;/li&gt;
   &lt;li&gt;
开始--程序--Microsoft SQL Server--客户端网络实用工具 
&lt;/li&gt;
   &lt;li&gt;--别名--添加 &lt;/li&gt;
   &lt;li&gt;--网络库选择&amp;quot;tcp/ip&amp;quot;--服务器别名输入SQL服务器名 &lt;/li&gt;
   &lt;li&gt;--连接参数--服务器名称中输入SQL服务器ip地址 &lt;/li&gt;
   &lt;li&gt;--如果你修改了SQL的端口,取消选择&amp;quot;动态决定端口&amp;quot;,并输入对应的端口号 &lt;/li&gt;
   &lt;li&gt;二、 正式配置 &lt;/li&gt;
   &lt;li&gt;1、配置发布服务器 &lt;/li&gt;
   &lt;li&gt;打开企业管理器，在发布服务器（B、C、D）上执行以下步骤: &lt;/li&gt;
   &lt;li&gt;(1) 从[工具]下拉菜单的[复制]子菜单中选择[配置发布、订阅服务器和分发]出现配置发布和分发向导 &lt;/li&gt;
   &lt;li&gt;(2) [下一步] 选择分发服务器 可以选择把发布服务器自己作为分发服务器或者其他sql的服务器（选择自己） &lt;/li&gt;
   &lt;li&gt;(3) [下一步] 设置快照文件夹 &lt;/li&gt;
   &lt;li&gt;采用默认\\servername\Pub &lt;/li&gt;
   &lt;li&gt;(4) [下一步] 自定义配置 &lt;/li&gt;
   &lt;li&gt;可以选择:是,让我设置分发数据库属性启用发布服务器或设置发布设置 &lt;/li&gt;
   &lt;li&gt;否,使用下列默认设置（推荐） &lt;/li&gt;
   &lt;li&gt;(5) [下一步] 设置分发数据库名称和位置 采用默认值 &lt;/li&gt;
   &lt;li&gt;(6) [下一步] 启用发布服务器 选择作为发布的服务器 &lt;/li&gt;
   &lt;li&gt;(7) [下一步] 选择需要发布的数据库和发布类型 &lt;/li&gt;
   &lt;li&gt;(8) [下一步] 选择注册订阅服务器 &lt;/li&gt;
   &lt;li&gt;(9) [下一步] 完成配置 &lt;/li&gt;
   &lt;li&gt;2、创建出版物 &lt;/li&gt;
   &lt;li&gt;发布服务器B、C、D上 &lt;/li&gt;
   &lt;li&gt;(1)从[工具]菜单的[复制]子菜单中选择[创建和管理发布]命令 &lt;/li&gt;
   &lt;li&gt;(2)选择要创建出版物的数据库，然后单击[创建发布] &lt;/li&gt;
   &lt;li&gt;(3)在[创建发布向导]的提示对话框中单击[下一步]系统就会弹出一个对话框。对话框上的内容是复制的三个类型。我们现在选第一个也就是默认的快照发布(其他两个大家可以去看看帮助) &lt;/li&gt;
   &lt;li&gt;(4)单击[下一步]系统要求指定可以订阅该发布的数据库服务器类型, &lt;/li&gt;
   &lt;li&gt;SQLSERVER允许在不同的数据库如 orACLE或ACCESS之间进行数据复制。 &lt;/li&gt;
   &lt;li&gt;
但是在这里我们选择运行&amp;quot;SQL SERVER 2000&amp;quot;的数据库服务器 
&lt;/li&gt;
   &lt;li&gt;(5)单击[下一步]系统就弹出一个定义文章的对话框也就是选择要出版的表 &lt;/li&gt;
   &lt;li&gt;注意: 如果前面选择了事务发布 则再这一步中只能选择带有主键的表 &lt;/li&gt;
   &lt;li&gt;(6)选择发布名称和描述 &lt;/li&gt;
   &lt;li&gt;(7)自定义发布属性 向导提供的选择: &lt;/li&gt;
   &lt;li&gt;是 我将自定义数据筛选,启用匿名订阅和或其他自定义属性 &lt;/li&gt;
   &lt;li&gt;否 根据指定方式创建发布 （建议采用自定义的方式） &lt;/li&gt;
   &lt;li&gt;(8)[下一步] 选择筛选发布的方式 &lt;/li&gt;
   &lt;li&gt;(9)[下一步] 可以选择是否允许匿名订阅 &lt;/li&gt;
   &lt;li&gt;1)如果选择署名订阅,则需要在发布服务器上添加订阅服务器 &lt;/li&gt;
   &lt;li&gt;方法: [工具]-&amp;gt;[复制]-&amp;gt;[配置发布、订阅服务器和分发的属性]-&amp;gt;[订阅服务器] 中添加 &lt;/li&gt;
   &lt;li&gt;否则在订阅服务器上请求订阅时会出现的提示:改发布不允许匿名订阅 &lt;/li&gt;
   &lt;li&gt;如果仍然需要匿名订阅则用以下解决办法 &lt;/li&gt;
   &lt;li&gt;[企业管理器]-&amp;gt;[复制]-&amp;gt;[发布内容]-&amp;gt;[属性]-&amp;gt;[订阅选项] 选择允许匿名请求订阅 &lt;/li&gt;
   &lt;li&gt;2)如果选择匿名订阅,则配置订阅服务器时不会出现以上提示 &lt;/li&gt;
   &lt;li&gt;(10)[下一步] 设置快照 代理程序调度 &lt;/li&gt;
   &lt;li&gt;(11)[下一步] 完成配置 &lt;/li&gt;
   &lt;li&gt;当完成出版物的创建后创建出版物的数据库也就变成了一个共享数据库 &lt;/li&gt;
   &lt;li&gt;有数据 &lt;/li&gt;
   &lt;li&gt;
srv1.库名..author有字段:id,    &lt;strong&gt;name&lt;/strong&gt;,phone, 
&lt;/li&gt;
   &lt;li&gt;
srv2.库名..author有字段:id,    &lt;strong&gt;name&lt;/strong&gt;,telphone,adress 
&lt;/li&gt;
   &lt;li&gt;
&lt;/li&gt;   &lt;li&gt;要求： &lt;/li&gt;
   &lt;li&gt;srv1.库名..author增加记录则srv1.库名..author记录增加 &lt;/li&gt;
   &lt;li&gt;srv1.库名..author的phone字段更新，则srv1.库名..author对应字段telphone更新 &lt;/li&gt;
   &lt;li&gt;--*/ &lt;/li&gt;
   &lt;li&gt;
&lt;/li&gt;   &lt;li&gt;--大致的处理步骤 &lt;/li&gt;
   &lt;li&gt;--1.在 srv1 上创建连接服务器,以便在 srv1 中操作 srv2,实现同步 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;exec&lt;/strong&gt; sp_addlinkedserver &amp;apos;srv2&amp;apos;,&amp;apos;&amp;apos;,&amp;apos;SQLOLEDB&amp;apos;,&amp;apos;srv2的sql实例名或ip&amp;apos;
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;exec&lt;/strong&gt; sp_addlinkedsrvlogin &amp;apos;srv2&amp;apos;,&amp;apos;false&amp;apos;,null,&amp;apos;用户名&amp;apos;,&amp;apos;密码&amp;apos;
&lt;/li&gt;
   &lt;li&gt;go &lt;/li&gt;
   &lt;li&gt;--2.在 srv1 和 srv2 这两台电脑中,启动 msdtc(分布式事务处理服务),并且设置为自动启动 &lt;/li&gt;
   &lt;li&gt;
。我的电脑--控制面板--管理工具--服务--右键 Distributed Transaction Coordinator--属性--启动--并将启动类型设置为自动启动 
&lt;/li&gt;
   &lt;li&gt;go &lt;/li&gt;
   &lt;li&gt;
&lt;/li&gt;   &lt;li&gt;
&lt;/li&gt;   &lt;li&gt;--然后创建一个作业定时调用上面的同步处理存储过程就行了 &lt;/li&gt;
   &lt;li&gt;
&lt;/li&gt;   &lt;li&gt;企业管理器 &lt;/li&gt;
   &lt;li&gt;--管理 &lt;/li&gt;
   &lt;li&gt;--SQL Server代理 &lt;/li&gt;
   &lt;li&gt;--右键作业 &lt;/li&gt;
   &lt;li&gt;--新建作业 &lt;/li&gt;
   &lt;li&gt;--&amp;quot;常规&amp;quot;项中输入作业名称 &lt;/li&gt;
   &lt;li&gt;--&amp;quot;步骤&amp;quot;项 &lt;/li&gt;
   &lt;li&gt;--新建 &lt;/li&gt;
   &lt;li&gt;--&amp;quot;步骤名&amp;quot;中输入步骤名 &lt;/li&gt;
   &lt;li&gt;--&amp;quot;类型&amp;quot;中选择&amp;quot;Transact-SQL 脚本(TSQL)&amp;quot; &lt;/li&gt;
   &lt;li&gt;--&amp;quot;数据库&amp;quot;选择执行命令的数据库 &lt;/li&gt;
   &lt;li&gt;--&amp;quot;命令&amp;quot;中输入要执行的语句: exec p_process &lt;/li&gt;
   &lt;li&gt;--确定 &lt;/li&gt;
   &lt;li&gt;--&amp;quot;调度&amp;quot;项 &lt;/li&gt;
   &lt;li&gt;--新建调度 &lt;/li&gt;
   &lt;li&gt;--&amp;quot;名称&amp;quot;中输入调度名称 &lt;/li&gt;
   &lt;li&gt;--&amp;quot;调度类型&amp;quot;中选择你的作业执行安排 &lt;/li&gt;
   &lt;li&gt;--如果选择&amp;quot;反复出现&amp;quot; &lt;/li&gt;
   &lt;li&gt;--点&amp;quot;更改&amp;quot;来设置你的时间安排 &lt;/li&gt;
   &lt;li&gt;
&lt;/li&gt;   &lt;li&gt;
&lt;/li&gt;   &lt;li&gt;然后将SQL Agent服务启动,并设置为自动启动,否则你的作业不会被执行 &lt;/li&gt;
   &lt;li&gt;
&lt;/li&gt;   &lt;li&gt;设置方法: &lt;/li&gt;
   &lt;li&gt;
我的电脑--控制面板--管理工具--服务--右键 SQLSERVERAGENT--属性--启动类型--选择&amp;quot;自动启动&amp;quot;--确定. 
&lt;/li&gt;
   &lt;li&gt;
&lt;/li&gt;   &lt;li&gt;
&lt;/li&gt;   &lt;li&gt;--3.实现同步处理的方法2,定时同步 &lt;/li&gt;
   &lt;li&gt;
&lt;/li&gt;   &lt;li&gt;--在srv1中创建如下的同步处理存储过程 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;create&lt;/strong&gt; proc p_process 
&lt;/li&gt;
   &lt;li&gt;    &lt;strong&gt;as&lt;/strong&gt;&lt;/li&gt;
   &lt;li&gt;--更新修改过的数据 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;update&lt;/strong&gt; b     &lt;strong&gt;set&lt;/strong&gt;    &lt;strong&gt;name&lt;/strong&gt;=i.    &lt;strong&gt;name&lt;/strong&gt;,telphone=i.telphone 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;from&lt;/strong&gt; srv2.库名.dbo.author b,author i 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;where&lt;/strong&gt; b.id=i.id and
&lt;/li&gt;
   &lt;li&gt;
(b.    &lt;strong&gt;name&lt;/strong&gt; &amp;lt;&amp;gt; i.    &lt;strong&gt;name&lt;/strong&gt;or b.telphone &amp;lt;&amp;gt; i.telphone) 
&lt;/li&gt;
   &lt;li&gt;
&lt;/li&gt;   &lt;li&gt;--插入新增的数据 &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;insert&lt;/strong&gt; srv2.库名.dbo.author(id,    &lt;strong&gt;name&lt;/strong&gt;,telphone) 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; id,    &lt;strong&gt;name&lt;/strong&gt;,telphone     &lt;strong&gt;from&lt;/strong&gt; author i 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;where&lt;/strong&gt;not exists( 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; *     &lt;strong&gt;from&lt;/strong&gt; srv2.库名.dbo.author     &lt;strong&gt;where&lt;/strong&gt; id=i.id) 
&lt;/li&gt;
   &lt;li&gt;
&lt;/li&gt;   &lt;li&gt;--删除已经删除的数据(如果需要的话) &lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;delete&lt;/strong&gt; b 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;from&lt;/strong&gt; srv2.库名.dbo.author b 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;where&lt;/strong&gt;not exists( 
&lt;/li&gt;
   &lt;li&gt;
    &lt;strong&gt;select&lt;/strong&gt; *     &lt;strong&gt;from&lt;/strong&gt; author     &lt;strong&gt;where&lt;/strong&gt; id=b.id) 
&lt;/li&gt;
   &lt;li&gt;go &lt;/li&gt;
&lt;/ol&gt;
  &lt;p&gt; &lt;/p&gt;
&lt;/div&gt;
          
           &lt;br /&gt; &lt;br /&gt;
          
             &lt;a href="http://dwphts520.iteye.com/blog/1992945#comments"&gt;已有   &lt;strong&gt;0&lt;/strong&gt; 人发表留言，猛击-&amp;gt;&amp;gt;  &lt;strong&gt;这里&lt;/strong&gt;&amp;lt;&amp;lt;-参与讨论&lt;/a&gt;
          
           &lt;br /&gt; &lt;br /&gt; &lt;br /&gt;
ITeye推荐
 &lt;br /&gt;
 &lt;ul&gt;  &lt;li&gt;   &lt;a href="http://www.iteye.com/clicks/433" target="_blank"&gt;—软件人才免语言低担保 赴美带薪读研！— &lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;
 &lt;br /&gt; &lt;br /&gt; &lt;br /&gt;
          
        &lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/47158-sql-%E7%BB%8F%E5%85%B8-%E8%AF%AD%E5%8F%A5</guid>
      <pubDate>Fri, 20 Dec 2013 14:37:40 CST</pubDate>
    </item>
    <item>
      <title>一道经典的sql面试题不同的写法</title>
      <link>https://itindex.net/detail/45140-%E7%BB%8F%E5%85%B8-sql-%E9%9D%A2%E8%AF%95</link>
      <description>&lt;p&gt;用一条SQL语句   查询出每门课都大于80分的学生姓名，表( #test）如下：  &lt;br /&gt;
    &lt;br /&gt;
Name Course Mark  &lt;br /&gt;
张三 语文 81  &lt;br /&gt;
张三 数学 75  &lt;br /&gt;
李四 语文 76  &lt;br /&gt;
李四 数学 90  &lt;br /&gt;
王五 英语 100  &lt;br /&gt;
王五 语文 81&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;create table #test  &lt;br /&gt;
(  &lt;br /&gt;
Name varchar(10),  &lt;br /&gt;
Course varchar(10),  &lt;br /&gt;
Mark float  &lt;br /&gt;
)&lt;/p&gt;
 &lt;p&gt;insert into #test  &lt;br /&gt;
select &amp;apos;张三&amp;apos;, &amp;apos;语文&amp;apos;, 81 union  &lt;br /&gt;
select &amp;apos;张三&amp;apos;, &amp;apos;数学&amp;apos;, 75 union  &lt;br /&gt;
select &amp;apos;李四&amp;apos;, &amp;apos;语文&amp;apos;, 76 union  &lt;br /&gt;
select &amp;apos;李四&amp;apos;, &amp;apos;数学&amp;apos;, 90 union   &lt;br /&gt;
select &amp;apos;王五&amp;apos;, &amp;apos;英语&amp;apos;, 100 union   &lt;br /&gt;
select &amp;apos;王五&amp;apos;, &amp;apos;语文&amp;apos;, 81  &lt;br /&gt;
&lt;/p&gt;
 &lt;p&gt;方法A select distinct Name  &lt;br /&gt;
from #test A  &lt;br /&gt;
where not exists(select Course  &lt;br /&gt;
 from #test  &lt;br /&gt;
 where Mark &amp;lt; 80 and Name = A.Name)&lt;/p&gt;
 &lt;p&gt;方法B&lt;/p&gt;
 &lt;p&gt;select * from #test a where mark &amp;gt; 80 and (select count(*) from #test where name=a.name)= (select count(*) from #test where name=a.name and mark &amp;gt; 80)  &lt;br /&gt;
&lt;/p&gt;
 &lt;p&gt;方法C&lt;/p&gt;
 &lt;p&gt;select distinct name from #test a where not exists(select * from #test where a.name=name and mark&amp;lt;80) （我认为这种较好）&lt;/p&gt;
 &lt;p&gt;方法D&lt;/p&gt;
 &lt;p&gt;select distinct name from  #test  where   &lt;br /&gt;
name not in (  &lt;br /&gt;
select name from #test where mark&amp;lt;=80  &lt;br /&gt;
)&lt;/p&gt;
 &lt;p&gt;方法E&lt;/p&gt;
 &lt;p&gt;select name,min(mark) from #test group by name having min(mark)&amp;gt;80   &lt;br /&gt;
-----66666  &lt;br /&gt;
DECLARE @test table (  Name varchar(10),  Course varchar(10),  Mark float)    &lt;br /&gt;
insert into @test  select   &amp;apos;张三  &amp;apos;,   &amp;apos;语文  &amp;apos;, 81  &lt;br /&gt;
 union select   &amp;apos;张三  &amp;apos;,   &amp;apos;数学  &amp;apos;, 75   &lt;br /&gt;
union select   &amp;apos;李四  &amp;apos;,   &amp;apos;语文  &amp;apos;, 76  &lt;br /&gt;
 union select   &amp;apos;李四  &amp;apos;,   &amp;apos;数学  &amp;apos;, 90  &lt;br /&gt;
 union  select   &amp;apos;王五  &amp;apos;,   &amp;apos;英语  &amp;apos;, 100  &lt;br /&gt;
 union  select   &amp;apos;王五  &amp;apos;,   &amp;apos;语文  &amp;apos;, 81     &lt;br /&gt;
SELECT NAME FROM @test GROUP BY name HAVING count(*)=count(case when mark&amp;gt;=80 then 1 else null end) 或者    &lt;br /&gt;
SELECT NAME FROM @test GROUP BY name HAVING count(*)=sum(case when mark&amp;gt;=80 then 1 else 0 end)  &lt;br /&gt;
&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;---方法F&lt;/p&gt;
 &lt;p&gt;select name from #test group  by name having min(mark)&amp;gt;80   &lt;br /&gt;
  &lt;br /&gt;
&lt;/p&gt;

 &lt;div&gt;
    作者：wanglei_samrtfish 发表于2013-8-5 21:12:50   &lt;a href="http://blog.csdn.net/wanglei_samrtfish/article/details/9772571"&gt;原文链接&lt;/a&gt;
&lt;/div&gt;
 &lt;div&gt;
    阅读：8 评论：0   &lt;a href="http://blog.csdn.net/wanglei_samrtfish/article/details/9772571#comments" target="_blank"&gt;查看评论&lt;/a&gt;
&lt;/div&gt;

&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/45140-%E7%BB%8F%E5%85%B8-sql-%E9%9D%A2%E8%AF%95</guid>
      <pubDate>Mon, 05 Aug 2013 21:12:50 CST</pubDate>
    </item>
    <item>
      <title>《少年派的奇幻漂流》10句经典台词（中英语）</title>
      <link>https://itindex.net/detail/40882-%E5%B0%91%E5%B9%B4-%E5%A5%87%E5%B9%BB-%E6%BC%82%E6%B5%81</link>
      <description>&lt;p&gt;  &lt;a href="http://chenguixiang.com/wp-content/uploads/2012/11/lifepi.jpg"&gt;   &lt;img alt="" height="337" src="http://chenguixiang.com/wp-content/uploads/2012/11/lifepi.jpg" title="lifepi" width="600"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;
 &lt;p&gt;All of life is an act of letting go, but what hurts the most is not taking a moment to say goodbye.  &lt;br /&gt;
人生也许就是不断地放下，然而令人痛心的是，我都没能好好地与他们道别。&lt;/p&gt;
 &lt;p&gt;When you understand life and self are not used to overcome but to get along! You will understand some things although not reasonable, but you must believe, they are strong, you must rely on!  &lt;br /&gt;
当你明白.人生和自我都不是用来战胜而是用来相处的!你就会明白有些东西虽然并不合理,但你必须相信,那些东西并不牢固,你必须依靠!&lt;/p&gt;
 &lt;p&gt;Pi: “Religion is a house with many rooms.” Writer: “But no room for doubt?”Pi: “Oh yes! On every floor.”  &lt;br /&gt;
派：“信仰就像一座房屋，可以有很多楼层、很多房间。”作家：“那有怀疑的空间么？”派：“当然，怀疑在每一层都占了几间。”&lt;/p&gt;
 &lt;p&gt;I must say a word about fear. It is life’s only true opponent. Only fear can defeat life.  &lt;br /&gt;
这里必须说说恐惧，它是生活惟一真正的对手，因为只有恐惧才能打败生活。&lt;/p&gt;
 &lt;p&gt;Suspected enormous effect, it makes the religion activity.  &lt;br /&gt;
怀疑作用巨大，它使信仰永葆活力。&lt;/p&gt;
 &lt;p&gt;If every unfolding we experience takes us further along in life, then, we are truly experiencing what life is offering...  &lt;br /&gt;
如果我们在人生中体验的每一次转变都让我们在生活中走得更远，那么，我们就真正的体验到了生活想让我们体验的东西。&lt;/p&gt;
 &lt;p&gt;I&amp;apos;m grateful. It&amp;apos;s the plain truth: without Richard Parker, I wouldn&amp;apos;t be alive today to tell you my story.  &lt;br /&gt;
我非常感恩。说实话，如果没有理查德·帕克，我也不可能活到今天跟你讲述我的故事。&lt;/p&gt;
 &lt;p&gt;Pi: “Which story do you prefer? ” Writer: “The one with the tiger.” Pi: “And so it goes with God.”  &lt;br /&gt;
派：“两个故事你更喜欢哪一个？”作家：“我喜欢有老虎那个，因为那个故事更精彩。”派：“所以，你跟随上帝。”&lt;/p&gt;
 &lt;p&gt;Have taken place, why must be meaningful.  &lt;br /&gt;
发生了就发生了，为什么一定要有意义。&lt;/p&gt;
 &lt;p&gt;Then Richard Parker, companion of my torment, awful, fierce thing that kept me alive, moved forward and disappeared forever from my life.  &lt;br /&gt;
然后，那个让我生存下来的理查德·帕克，那个让我痛苦、使我害怕的凶狠的伙伴，径直向前走没有回头，永远消失在我的生命里。&lt;/p&gt;
 &lt;div&gt;
  &lt;a href="http://feeds.feedburner.com/~ff/xiangge?a=29ZRqyA8Rmo:1IpGTOOtKWw:yIl2AUoC8zA"&gt;   &lt;img border="0" src="http://feeds.feedburner.com/~ff/xiangge?d=yIl2AUoC8zA"&gt;&lt;/img&gt;&lt;/a&gt;   &lt;a href="http://feeds.feedburner.com/~ff/xiangge?a=29ZRqyA8Rmo:1IpGTOOtKWw:V_sGLiPBpWU"&gt;   &lt;img border="0" src="http://feeds.feedburner.com/~ff/xiangge?i=29ZRqyA8Rmo:1IpGTOOtKWw:V_sGLiPBpWU"&gt;&lt;/img&gt;&lt;/a&gt;   &lt;a href="http://feeds.feedburner.com/~ff/xiangge?a=29ZRqyA8Rmo:1IpGTOOtKWw:F7zBnMyn0Lo"&gt;   &lt;img border="0" src="http://feeds.feedburner.com/~ff/xiangge?i=29ZRqyA8Rmo:1IpGTOOtKWw:F7zBnMyn0Lo"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt; &lt;img height="1" src="http://feeds.feedburner.com/~r/xiangge/~4/29ZRqyA8Rmo" width="1"&gt;&lt;/img&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category>学无止境 我喜欢的 英语 人生 学习</category>
      <guid isPermaLink="true">https://itindex.net/detail/40882-%E5%B0%91%E5%B9%B4-%E5%A5%87%E5%B9%BB-%E6%BC%82%E6%B5%81</guid>
      <pubDate>Fri, 30 Nov 2012 12:12:22 CST</pubDate>
    </item>
    <item>
      <title>经典网页设计：20例简洁精美的着陆页面设计</title>
      <link>https://itindex.net/detail/40869-%E7%BB%8F%E5%85%B8-%E7%BD%91%E9%A1%B5%E8%AE%BE%E8%AE%A1-%E7%BE%8E%E7%9A%84</link>
      <description>&lt;p&gt;　　在互联网营销中，着陆页（Landing Page）有时被称为引导页或者首要捕获用户页，可以简单划分为参考型引导页、交易型引导页和压缩型引导页。与普通的网页不同，着陆页需要完成特殊的使命，它需要把访问者引导到他们想去的网页，着陆页并不是目标页，而只是引导访问者到目标页的一个中间页面。&lt;/p&gt; &lt;p&gt;　　着陆页面的设计和优化涉及多个学科，它需要融合各种不同的知识和观点。所以您还有必要掌握   &lt;a href="http://www.cnblogs.com/lhb25/category/279316.html" target="_blank"&gt;   &lt;strong&gt;Web&lt;/strong&gt;&lt;/a&gt; 设计、人类心理学、广告撰写、统计学、可用性、团队建设和科学方法等其他领域的知识。下面向大家分享20例简洁精美的着陆页面设计，希望能够带给你一些灵感。&lt;/p&gt; &lt;h3&gt;您可能还喜欢  &lt;p&gt;&lt;/p&gt;  &lt;div&gt;   &lt;ul&gt;    &lt;li&gt;     &lt;a href="http://www.cnblogs.com/lhb25/archive/2012/10/19/10-free-html-admin-templates.html" target="_blank"&gt;10套精美的免费网站后台管理系统模板&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;     &lt;a href="http://www.cnblogs.com/lhb25/archive/2012/01/13/25-outstanding-single-page-website-designs.html" target="_blank"&gt;25个优秀的国外单页网站设计作品欣赏&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;     &lt;a href="http://www.cnblogs.com/lhb25/archive/2011/11/03/html5-business-websites-inpiration.html" target="_blank"&gt;10个精美的 HTML5 商业网站设计案例&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;     &lt;a href="http://www.cnblogs.com/lhb25/archive/2011/12/06/fresh-best-inspirational-website-designs.html" target="_blank"&gt;30佳别出心裁的企业网站设计优秀作品&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;     &lt;a href="http://www.cnblogs.com/lhb25/archive/2012/05/16/parallax-scrolling-effect-web-design.html" target="_blank"&gt;35个立体动感的视差滚动效果网站作品&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;01. We Are Int&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;center&gt;   &lt;p&gt;    &lt;a href="http://www.weareint.io/" target="_blank"&gt;     &lt;img alt="" src="http://pic002.cnblogs.com/images/2012/36987/2012112915380416.jpg"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;/center&gt;  &lt;center&gt;&lt;/center&gt;  &lt;center&gt;&lt;/center&gt;  &lt;center&gt;&lt;/center&gt;  &lt;center&gt;&lt;/center&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;02. 5 Eme Gauche&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;center&gt;   &lt;a href="http://www.5emegauche.com/" target="_blank" title="20 Simple and Beautiful Landing Pages"&gt;    &lt;img alt="20 Simple and Beautiful Landing Pages" src="http://pic002.cnblogs.com/images/2012/36987/2012112915264912.jpg"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/center&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;03. Vlog.it&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;center&gt;   &lt;a href="http://www.vlog.it/" target="_blank" title="20 Simple and Beautiful Landing Pages"&gt;    &lt;img alt="20 Simple and Beautiful Landing Pages" src="http://pic002.cnblogs.com/images/2012/36987/2012112915264949.jpg"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/center&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;04. Arbel-Designs&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;center&gt;   &lt;a href="http://www.arbel-designs.com/" target="_blank" title="20 Simple and Beautiful Landing Pages"&gt;    &lt;img alt="20 Simple and Beautiful Landing Pages" src="http://pic002.cnblogs.com/images/2012/36987/2012112915263935.jpg"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/center&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;05. Whiteboard&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;center&gt;   &lt;a href="http://www.whiteboard.is/" target="_blank" title="20 Simple and Beautiful Landing Pages"&gt;    &lt;img alt="20 Simple and Beautiful Landing Pages" src="http://pic002.cnblogs.com/images/2012/36987/2012112915264974.jpg"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/center&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;06. The Penthouse Project&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;center&gt;   &lt;a href="http://www.thepenthouseproject.com/" target="_blank" title="20 Simple and Beautiful Landing Pages"&gt;    &lt;img alt="20 Simple and Beautiful Landing Pages" src="http://pic002.cnblogs.com/images/2012/36987/2012112915263974.jpg"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/center&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;07. Dynamit&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;center&gt;   &lt;a href="http://www.dynamit.us/" target="_blank" title="20 Simple and Beautiful Landing Pages"&gt;    &lt;img alt="20 Simple and Beautiful Landing Pages" src="http://pic002.cnblogs.com/images/2012/36987/2012112915263952.jpg"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/center&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;08. Humaan&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;center&gt;   &lt;a href="http://www.humaan.com.au/" target="_blank" title="20 Simple and Beautiful Landing Pages"&gt;    &lt;img alt="20 Simple and Beautiful Landing Pages" src="http://pic002.cnblogs.com/images/2012/36987/2012112915263947.jpg"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/center&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;09. Square Factor&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;center&gt;   &lt;a href="http://www.squarefactor.com/" target="_blank" title="20 Simple and Beautiful Landing Pages"&gt;    &lt;img alt="20 Simple and Beautiful Landing Pages" src="http://pic002.cnblogs.com/images/2012/36987/2012112915263939.jpg"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/center&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;10. X-Prime Groupe&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;center&gt;   &lt;a href="http://www.xprimegroupe.com/" target="_blank" title="20 Simple and Beautiful Landing Pages"&gt;    &lt;img alt="20 Simple and Beautiful Landing Pages" src="http://pic002.cnblogs.com/images/2012/36987/2012112915263979.jpg"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/center&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;11. Psych &amp;amp; Psych&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;center&gt;   &lt;p&gt;    &lt;a href="http://www.psychnpsych.com/" target="_blank"&gt;     &lt;img alt="" src="http://pic002.cnblogs.com/images/2012/36987/2012112915275531.jpg"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;/center&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;12. Pulp Fingers&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;center&gt;   &lt;a href="http://www.pulpfingers.com/" target="_blank" title="20 Simple and Beautiful Landing Pages"&gt;    &lt;img alt="20 Simple and Beautiful Landing Pages" src="http://pic002.cnblogs.com/images/2012/36987/2012112915263957.jpg"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/center&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;13. Captain Dash&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;center&gt;   &lt;a href="http://www.captaindash.com/" target="_blank" title="20 Simple and Beautiful Landing Pages"&gt;    &lt;img alt="20 Simple and Beautiful Landing Pages" src="http://pic002.cnblogs.com/images/2012/36987/2012112915264934.jpg"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/center&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;14. Rally Interactive&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;center&gt;   &lt;a href="http://beta.rallyinteractive.com/" target="_blank" title="20 Simple and Beautiful Landing Pages"&gt;    &lt;img alt="20 Simple and Beautiful Landing Pages" src="http://pic002.cnblogs.com/images/2012/36987/2012112915263989.jpg"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/center&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;15. Able Brewing&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;center&gt;   &lt;a href="http://www.ablebrewing.com/" target="_blank" title="20 Simple and Beautiful Landing Pages"&gt;    &lt;img alt="20 Simple and Beautiful Landing Pages" src="http://pic002.cnblogs.com/images/2012/36987/2012112915263966.jpg"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/center&gt;  &lt;center&gt;梦想天空博客关注   &lt;a href="http://www.cnblogs.com/lhb25/" target="_blank"&gt;前端开发&lt;/a&gt;技术，展示最新   &lt;a href="http://www.cnblogs.com/lhb25/tag/HTML5/" target="_blank"&gt;HTML5&lt;/a&gt;和   &lt;a href="http://www.cnblogs.com/lhb25/category/146075.html" target="_blank"&gt;CSS3&lt;/a&gt;应用，分享实用的   &lt;a href="http://www.cnblogs.com/lhb25/category/277997.html" target="_blank"&gt;jQuery&lt;/a&gt;插件，推荐   &lt;a href="http://www.cnblogs.com/lhb25/category/279316.html" target="_blank"&gt;网页设计&lt;/a&gt;案例&lt;/center&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;16. Never Bland&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;center&gt;   &lt;p&gt;    &lt;a href="http://www.neverbland.com/" target="_blank"&gt;     &lt;img alt="" src="http://pic002.cnblogs.com/images/2012/36987/2012112915243963.jpg"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;/center&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;17. Social Design House&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;center&gt;   &lt;a href="http://socialdesignhouse.com/" target="_blank" title="20 Simple and Beautiful Landing Pages"&gt;    &lt;img alt="20 Simple and Beautiful Landing Pages" src="http://pic002.cnblogs.com/images/2012/36987/2012112915263966.jpg"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/center&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;18. Full Stop Interactive&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;center&gt;   &lt;p&gt;    &lt;a href="http://www.fullstopinteractive.com/" target="_blank"&gt;     &lt;img alt="" src="http://pic002.cnblogs.com/images/2012/36987/2012112915283050.jpg"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;/center&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;19. Breakfast&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;center&gt;   &lt;a href="http://www.studiobreakfast.be/" target="_blank" title="20 Simple and Beautiful Landing Pages"&gt;    &lt;img alt="20 Simple and Beautiful Landing Pages" src="http://pic002.cnblogs.com/images/2012/36987/2012112915263927.jpg"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/center&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;20. Poco People&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;center&gt;   &lt;a href="http://www.pocopeople.com.au/" target="_blank" title="20 Simple and Beautiful Landing Pages"&gt;    &lt;img alt="20 Simple and Beautiful Landing Pages" src="http://pic002.cnblogs.com/images/2012/36987/2012112915263992.jpg"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/center&gt;  &lt;p&gt; &lt;/p&gt;&lt;/h3&gt; &lt;h3&gt;您可能还喜欢  &lt;p&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;    &lt;a href="http://www.cnblogs.com/lhb25/archive/2011/09/02/outstanding-admin-panels-part-two.html" target="_blank"&gt;34个漂亮的应用程序后台管理系统界面&lt;/a&gt;&lt;/li&gt;   &lt;li&gt;    &lt;a href="http://www.cnblogs.com/lhb25/archive/2011/08/09/awesome-html5-and-javascript-effects.html" target="_blank"&gt;8个惊艳的 HTML5 和 JavaScript 特效&lt;/a&gt;&lt;/li&gt;   &lt;li&gt;    &lt;a href="http://www.cnblogs.com/lhb25/archive/2011/05/31/2056103.html" target="_blank"&gt;60款很酷的 jQuery 幻灯片演示和下载&lt;/a&gt;&lt;/li&gt;   &lt;li&gt;    &lt;a href="http://www.cnblogs.com/lhb25/archive/2011/10/30/html5-portfolio-great-examples.html" target="_blank"&gt;16个精美的HTML5作品集网站设计案例&lt;/a&gt;&lt;/li&gt;   &lt;li&gt;    &lt;a href="http://www.cnblogs.com/lhb25/archive/2012/10/19/10-free-html-admin-templates.html" target="_blank"&gt;10套精美的免费网站后台管理系统模板&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;本文链接：   &lt;a href="http://www.webdesignersblog.net/design/20-simple-and-beautiful-landing-pages/" target="_blank"&gt;20 Simple and Beautiful Landing Pages&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;编译来源：   &lt;a href="http://www.cnblogs.com/lhb25/" target="_blank"&gt;梦想天空 ◆ 关注前端开发技术 ◆ 分享网页设计资源&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;hide&lt;/p&gt;  &lt;img alt="" height="1" src="http://www.cnblogs.com/lhb25/aggbug/2770610.html?type=1" width="1"&gt;&lt;/img&gt;  &lt;p&gt;   &lt;a href="http://www.cnblogs.com/lhb25/archive/2012/11/29/20-simple-and-beautiful-landing-pages.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;&lt;/h3&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/40869-%E7%BB%8F%E5%85%B8-%E7%BD%91%E9%A1%B5%E8%AE%BE%E8%AE%A1-%E7%BE%8E%E7%9A%84</guid>
      <pubDate>Thu, 29 Nov 2012 15:31:00 CST</pubDate>
    </item>
    <item>
      <title>mysql保存中文乱码的原因和解决办法（首发经典实用版）</title>
      <link>https://itindex.net/detail/39762-mysql-%E4%B8%AD%E6%96%87%E4%B9%B1%E7%A0%81-%E5%8E%9F%E5%9B%A0</link>
      <description>&lt;p&gt;    当你遇到这个mysql保存中文乱码问题的时候，期待找到mysql保存中文乱码的原因和解决办法（首发经典实用版）这样一篇能解决问题的文章是多么激动人心。&lt;/p&gt;
 &lt;p&gt;    也许30%的程序员会选择自己百度，结果发现网友已经贴了很多类似“mysql 中文乱码”、“php mysql 中文乱码”、“mysql5.5中文乱码”、“mysql 乱码”、“mysql乱码问题”、“mysql jsp 乱码”、“mysql jdbc 乱码”、“mysql 查询乱码”、“mysql 导入数据乱码”等一系列问题，到底哪个是自己要找的能解决自己问题的呀？15%的程序员一看就懵了，剩下15%的程序员自己摸索或求教别人了。70%的程序员干脆不干了，干不动咱还是程序员，这种浪费生命的事情让别人干去把，呵呵。&lt;/p&gt;
 &lt;p&gt;    其实mysql的乱码问题，说复杂也非常地负责，说简单简单的不行！区别就在于明白mysql乱码的本质原因，本文就从这个角度目的让煞笔程序员都掌握如何处理这个乱码问题。&lt;/p&gt;
 &lt;p&gt;    （1）网站本身的编码。这不多说了，自己看看设置对了没，比如我设置的GBK就检查下编码是不是GBK。（一般通过文件右击属性来看，或建立工程的时候来统一设置）&lt;/p&gt;
 &lt;p&gt;    （2）数据库连接字符串的编码。比如java中我连接mysql的相关语句如下：&lt;/p&gt;
 &lt;p&gt; public static String driverName = &amp;quot;com.mysql.jdbc.Driver&amp;quot;;  &lt;br /&gt;
 public static String userName = &amp;quot;root&amp;quot;;  &lt;br /&gt;
 public static String userPasswd = &amp;quot;123456&amp;quot;;  &lt;br /&gt;
 public static String dbName = &amp;quot;myBook&amp;quot;;  &lt;br /&gt;
 public static String url = &amp;quot;jdbc:mysql://localhost/&amp;quot; + dbName + &amp;quot;?user=&amp;quot;  &lt;br /&gt;
   + userName + &amp;quot;&amp;amp;password=&amp;quot; + userPasswd  &lt;br /&gt;
   + &amp;quot;&amp;amp;useUnicode=true  &lt;strong&gt;&amp;amp;characterEncoding=GBK&lt;/strong&gt;&amp;quot;;&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;。。。。。&lt;/p&gt;
 &lt;p&gt;Class.forName(driverName).newInstance();  &lt;br /&gt;
    connection = (Connection) DriverManager.getConnection(url);&lt;/p&gt;
 &lt;p&gt;     如上面的代码中，加粗的就是我要说的部分，可以设置为你想要的字符串类型，这里设置的是GBK，这仅仅是java语言的示例，其他语言asp、php原理是一样的都有这样的数据库字符串链接关于字符集的配置，不会就查查手册或百度一下，这个很容易找到，如果百度还找不到，那360干他也对。&lt;/p&gt;
 &lt;p&gt;    （3）mysql的字符集设置。&lt;/p&gt;
 &lt;p&gt;    这个是重点了，一般都是在这里搞错而出现了mysql乱码。&lt;/p&gt;
 &lt;p&gt;    mysql编码设置可以分为三种设置：数据库的编码、表的编码、和字段的编码。&lt;/p&gt;
 &lt;p&gt;    a、数据库的编码：&lt;/p&gt;
 &lt;p&gt;    在sqlyog工具中操作把，右击数据库点击更改数据库，如图&lt;/p&gt;
 &lt;p&gt;   &lt;img alt="" src="http://img.my.csdn.net/uploads/201209/18/1347973902_1973.jpg"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;      &lt;img alt="" src="http://img.my.csdn.net/uploads/201209/18/1347973969_6929.jpg"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;     设置就可以了，煞笔不煞笔，简单不简单。&lt;/p&gt;
 &lt;p&gt;    b、表的编码：&lt;/p&gt;
 &lt;p&gt;    mysql很扯淡的是，表级别也设置了编码，说说咋设置把&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;
 &lt;p&gt;  &lt;img alt="" src="http://img.my.csdn.net/uploads/201209/18/1347974065_1958.jpg"&gt;&lt;/img&gt;。&lt;/p&gt;
 &lt;p&gt;     右击要修改编码的表，点击更改表如上图，点了以后如下图：&lt;/p&gt;
 &lt;p&gt;       &lt;img alt="" src="http://img.my.csdn.net/uploads/201209/18/1347974135_8595.jpg"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;    点  &lt;strong&gt;高级属性&lt;/strong&gt;，表的字符编码设置很煞笔很简单，看到了把。记得修改完毕后，一定要点击“Alter”才行呀！这个按钮很容易被忽略，操蛋的sqlyog呀！&lt;/p&gt;
 &lt;p&gt;    c、字段的编码：&lt;/p&gt;
 &lt;p&gt;    mysql确实很扯淡，字段都有编码设置，还是上面的更改表，不过不点高级属性了。看图：&lt;/p&gt;
 &lt;p&gt;      &lt;img alt="" src="http://img.my.csdn.net/uploads/201209/18/1347974338_8031.jpg"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;     坑爹的默认不显示，对就是在右下角呢！看到了把，把对号取消把，取消后你看到了下图：&lt;/p&gt;
 &lt;p&gt;      &lt;img alt="" src="http://img.my.csdn.net/uploads/201209/18/1347974413_4999.jpg"&gt;&lt;/img&gt;&lt;/p&gt;
 &lt;p&gt;    终于看到了字段后面跟的字符编码设置，他奶奶的熊，终于都找全了。设置把。记得修改完毕后，一定要点击“Alter”才行呀！这个按钮很容易被忽略，操蛋的sqlyog呀！&lt;/p&gt;
 &lt;p&gt;    &lt;/p&gt;
 &lt;p&gt;    对于mysql保存中文乱码的原因和解决办法（首发经典实用版）的总结：（1）程序员都不是煞笔，是软件做的煞笔，软件没有按照产品去做，易用性不好所以才导致大家找不到，以后的软件一定要把程序员当对用户体验要求极高得用户才能牛逼。（2）程序员有点煞笔，遇到问题头疼的要死，脑细胞都死了很多，经常遇到这样的事情解决不了还打击自信心，解决的了还是买不起房子，你说我们图了什么呢？当初的梦想是什么呢？沉思中。  &lt;br /&gt;
   &lt;/p&gt;
 &lt;p&gt;   &lt;br /&gt;
&lt;/p&gt;
 &lt;p&gt; &lt;/p&gt;

         &lt;div&gt;
            作者：androidjiaocheng 发表于2012-9-18 21:19:41   &lt;a href="http://blog.csdn.net/androidjiaocheng/article/details/7993487"&gt;原文链接&lt;/a&gt;
        &lt;/div&gt;
         &lt;div&gt;
            阅读：0 评论：0   &lt;a href="http://blog.csdn.net/androidjiaocheng/article/details/7993487#comments" target="_blank"&gt;查看评论&lt;/a&gt;
        &lt;/div&gt;
        
&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/39762-mysql-%E4%B8%AD%E6%96%87%E4%B9%B1%E7%A0%81-%E5%8E%9F%E5%9B%A0</guid>
      <pubDate>Tue, 18 Sep 2012 21:19:41 CST</pubDate>
    </item>
    <item>
      <title>经典网页设计：精心设计的 iPhone 和 Android 应用程序网站</title>
      <link>https://itindex.net/detail/41173-%E7%BB%8F%E5%85%B8-%E7%BD%91%E9%A1%B5%E8%AE%BE%E8%AE%A1-%E8%AE%BE%E8%AE%A1</link>
      <description>&lt;p&gt;　　这篇文章和大家分享一组精心设计的 iPhone 和 Android 应用程序网站。在一个应用程序的网站，从醒目的图像到有趣的标题和产品信息等等，你可以找到很多的灵感。今天的文章中收集的这些设计精美的应用程序网站为我们的网站设计和制作提供了各种各样的思路，都是真正优秀和杰出的设计，值得借鉴和学习。&lt;/p&gt; &lt;h3&gt;您可能感兴趣的相关文章  &lt;p&gt;&lt;/p&gt;  &lt;div&gt;   &lt;ul&gt;    &lt;li&gt;     &lt;a href="http://www.cnblogs.com/lhb25/archive/2012/10/19/10-free-html-admin-templates.html" target="_blank"&gt;10套精美的免费网站后台管理系统模板&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;     &lt;a href="http://www.cnblogs.com/lhb25/archive/2012/11/15/20-trendy-contact-form-designs-to-inspire.html" target="_blank"&gt;推荐20例与众不同的网页联系表单设计&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;     &lt;a href="http://www.cnblogs.com/lhb25/archive/2012/09/20/30-single-page-portfolio-websites.html" target="_blank"&gt;分享30个独具匠心的单页网站设计案例&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;     &lt;a href="http://www.cnblogs.com/lhb25/archive/2011/07/21/restaurant-websites-inspiration.html" target="_blank"&gt;25个国外优秀的餐饮网站设计案例欣赏&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;     &lt;a href="http://www.cnblogs.com/lhb25/archive/2011/12/13/21-inspiring-blog-designs.html" target="_blank"&gt;20个独具创意的优秀个人博客设计案例&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;    &lt;a href="http://www.thefontain.com/apps" target="_blank"&gt;Fontain&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Fontain 是一款生活应用，能够帮助你随时分享生活中遇到的精彩。&lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;    &lt;a href="http://www.thefontain.com/apps" target="_blank"&gt;     &lt;img alt="&amp;#31934;&amp;#24515;&amp;#35774;&amp;#35745;&amp;#30340;iPhone&amp;#21644;Android&amp;#24212;&amp;#29992;&amp;#31243;&amp;#24207;&amp;#32593;&amp;#31449;" src="http://pic002.cnblogs.com/images/2012/36987/2012121714084639.jpg" width="550"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;    &lt;a href="http://flipboard.com/" target="_blank"&gt;Flipboard&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Flipboard 是一款新的 iPad 应用程序，可以将用户喜欢的 Twitter 消息和网站以杂志的形式输出。&lt;/p&gt;  &lt;p&gt;   &lt;a href="http://flipboard.com/" target="_blank"&gt;    &lt;img alt="&amp;#31934;&amp;#24515;&amp;#35774;&amp;#35745;&amp;#30340;iPhone&amp;#21644;Android&amp;#24212;&amp;#29992;&amp;#31243;&amp;#24207;&amp;#32593;&amp;#31449;" src="http://pic002.cnblogs.com/images/2012/36987/2012121714084780.jpg" width="550"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;    &lt;a href="https://squareup.com/wallet#explore" target="_blank"&gt;Square Wallet&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Square Wallet 是一款非常便捷的手机支付应用，不需要携带任何的现金或者银行卡。&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://squareup.com/wallet#explore" target="_blank"&gt;    &lt;img alt="&amp;#31934;&amp;#24515;&amp;#35774;&amp;#35745;&amp;#30340;iPhone&amp;#21644;Android&amp;#24212;&amp;#29992;&amp;#31243;&amp;#24207;&amp;#32593;&amp;#31449;" src="http://pic002.cnblogs.com/images/2012/36987/2012121714084753.jpg" width="550"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;    &lt;a href="http://evernote.com/skitch/" target="_blank"&gt;Evernote – Skitch&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;用很少的注释，形状和草图，让你的想法和观点快速变成了现实。&lt;/p&gt;  &lt;p&gt;   &lt;a href="http://evernote.com/skitch/" target="_blank"&gt;    &lt;img alt="&amp;#31934;&amp;#24515;&amp;#35774;&amp;#35745;&amp;#30340;iPhone&amp;#21644;Android&amp;#24212;&amp;#29992;&amp;#31243;&amp;#24207;&amp;#32593;&amp;#31449;" src="http://pic002.cnblogs.com/images/2012/36987/2012121714084731.jpg" width="550"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;    &lt;a href="http://summly.com/" target="_blank"&gt;Summly&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Summly 的目标是使新闻阅读变得更加简单，把长篇大论的新闻压缩为简短的摘要，让用户能快速消化信息。&lt;/p&gt;  &lt;p&gt;   &lt;a href="http://summly.com/" target="_blank"&gt;    &lt;img alt="&amp;#31934;&amp;#24515;&amp;#35774;&amp;#35745;&amp;#30340;iPhone&amp;#21644;Android&amp;#24212;&amp;#29992;&amp;#31243;&amp;#24207;&amp;#32593;&amp;#31449;" src="http://pic002.cnblogs.com/images/2012/36987/2012121714084793.jpg" width="550"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;    &lt;a href="http://www.mdotapp.com/" target="_blank"&gt;M.dot&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;在你的 iPhone 手机上轻松创建和维护移动网站，不需要编程基础。&lt;/p&gt;  &lt;p&gt;   &lt;a href="http://www.mdotapp.com/" target="_blank"&gt;    &lt;img alt="" src="http://pic002.cnblogs.com/images/2012/36987/2012121714094874.jpg" width="550"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;    &lt;a href="http://www.statnutapp.com/" target="_blank"&gt;Statnut&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;社交网络聚合应用 StatNut 让你在一款应用中查看所有的社交网络状态信息。&lt;/p&gt;  &lt;p&gt;   &lt;a href="http://www.statnutapp.com/" target="_blank"&gt;    &lt;img alt="&amp;#31934;&amp;#24515;&amp;#35774;&amp;#35745;&amp;#30340;iPhone&amp;#21644;Android&amp;#24212;&amp;#29992;&amp;#31243;&amp;#24207;&amp;#32593;&amp;#31449;" src="http://pic002.cnblogs.com/images/2012/36987/2012121714084752.jpg" width="550"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;    &lt;a href="http://madewithover.com/" target="_blank"&gt;Over&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;给你的照片添加漂亮的个性化文字装饰并分享到 Facebook、Twitter、Instagram 和 Tumblr。&lt;/p&gt;  &lt;p&gt;   &lt;a href="http://madewithover.com/" target="_blank"&gt;    &lt;img alt="&amp;#31934;&amp;#24515;&amp;#35774;&amp;#35745;&amp;#30340;iPhone&amp;#21644;Android&amp;#24212;&amp;#29992;&amp;#31243;&amp;#24207;&amp;#32593;&amp;#31449;" src="http://pic002.cnblogs.com/images/2012/36987/2012121714084722.jpg" width="550"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;    &lt;a href="http://www.kelvinapp.com/" target="_blank"&gt;Kelvin&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;在手机设置天气预报从来没有如此容易，Kelvin 值得拥有。&lt;/p&gt;  &lt;p&gt;   &lt;a href="http://www.kelvinapp.com/" target="_blank"&gt;    &lt;img alt="&amp;#31934;&amp;#24515;&amp;#35774;&amp;#35745;&amp;#30340;iPhone&amp;#21644;Android&amp;#24212;&amp;#29992;&amp;#31243;&amp;#24207;&amp;#32593;&amp;#31449;" src="http://pic002.cnblogs.com/images/2012/36987/2012121714084788.jpg" width="550"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;    &lt;a href="https://cheddarapp.com/" target="_blank"&gt;Cheddar&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;一个待办事项管理应用，让你可以有条不紊的工作和生活。&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://cheddarapp.com/" target="_blank"&gt;    &lt;img alt="&amp;#31934;&amp;#24515;&amp;#35774;&amp;#35745;&amp;#30340;iPhone&amp;#21644;Android&amp;#24212;&amp;#29992;&amp;#31243;&amp;#24207;&amp;#32593;&amp;#31449;" src="http://pic002.cnblogs.com/images/2012/36987/2012121714084780.jpg" width="550"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;    &lt;a href="https://path.com/" target="_blank"&gt;Path&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Path 是个人的社交网络，是分享生活和与家人和朋友保持联系的最好的方式。&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://path.com/" target="_blank"&gt;    &lt;img alt="&amp;#31934;&amp;#24515;&amp;#35774;&amp;#35745;&amp;#30340;iPhone&amp;#21644;Android&amp;#24212;&amp;#29992;&amp;#31243;&amp;#24207;&amp;#32593;&amp;#31449;" src="http://pic002.cnblogs.com/images/2012/36987/2012121714084758.jpg" width="550"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;    &lt;a href="http://fxc.am/" target="_blank"&gt;FxCamera&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;FxCamera 让你可以通过几个简单的步骤拍摄出各种效果精美的照片。&lt;/p&gt;  &lt;p&gt;   &lt;a href="http://fxc.am/" target="_blank"&gt;    &lt;img alt="&amp;#31934;&amp;#24515;&amp;#35774;&amp;#35745;&amp;#30340;iPhone&amp;#21644;Android&amp;#24212;&amp;#29992;&amp;#31243;&amp;#24207;&amp;#32593;&amp;#31449;" src="http://pic002.cnblogs.com/images/2012/36987/2012121714084726.jpg" width="550"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;    &lt;a href="https://www.weddingpartyapp.com/" target="_blank"&gt;Wedding Party&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;在你婚礼上捕捉那些令人感动的幸福瞬间，相信你的客人会喜欢它！&lt;/p&gt;  &lt;p&gt;   &lt;a href="https://www.weddingpartyapp.com/" target="_blank"&gt;    &lt;img alt="&amp;#31934;&amp;#24515;&amp;#35774;&amp;#35745;&amp;#30340;iPhone&amp;#21644;Android&amp;#24212;&amp;#29992;&amp;#31243;&amp;#24207;&amp;#32593;&amp;#31449;" src="http://pic002.cnblogs.com/images/2012/36987/2012121714084744.jpg" width="550"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;    &lt;a href="http://www.rdio.com/apps/" target="_blank"&gt;rdio&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Rdio 让音乐无所不在，拥有众多的客户端，桌面版、移动版，就连你的客厅播放器都可以使用。&lt;/p&gt;  &lt;p&gt;   &lt;a href="http://www.rdio.com/apps/" target="_blank"&gt;    &lt;img alt="&amp;#31934;&amp;#24515;&amp;#35774;&amp;#35745;&amp;#30340;iPhone&amp;#21644;Android&amp;#24212;&amp;#29992;&amp;#31243;&amp;#24207;&amp;#32593;&amp;#31449;" src="http://pic002.cnblogs.com/images/2012/36987/2012121714085963.jpg" width="550"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;strong&gt;    &lt;a href="http://static.freshbyt.es/" target="_blank"&gt;Static&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;提供来自 Twitter、Gribbble、Github、Google Analytics和Instagram的统计数据快速预览。&lt;/p&gt;  &lt;p&gt;   &lt;a href="http://static.freshbyt.es/" target="_blank"&gt;    &lt;img alt="" src="http://pic002.cnblogs.com/images/2012/36987/2012121714083525.jpg" width="550"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;/h3&gt; &lt;h3&gt;您可能感兴趣的相关文章  &lt;p&gt;&lt;/p&gt;  &lt;p&gt; &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;    &lt;a href="http://www.cnblogs.com/lhb25/archive/2012/10/19/10-free-html-admin-templates.html" target="_blank"&gt;10套精美的免费网站后台管理系统模板&lt;/a&gt;&lt;/li&gt;   &lt;li&gt;    &lt;a href="http://www.cnblogs.com/lhb25/archive/2011/07/21/restaurant-websites-inspiration.html" target="_blank"&gt;25个国外优秀的餐饮网站设计案例欣赏&lt;/a&gt;&lt;/li&gt;   &lt;li&gt;    &lt;a href="http://www.cnblogs.com/lhb25/archive/2011/05/30/2062333.html" target="_blank"&gt;25个非常漂亮的旅游网站设计作品欣赏&lt;/a&gt;&lt;/li&gt;   &lt;li&gt;    &lt;a href="http://www.cnblogs.com/lhb25/archive/2012/11/22/15-websites-using-the-grid-system.html" target="_blank"&gt;推荐15个使用网格系统的精美网站作品&lt;/a&gt;&lt;/li&gt;   &lt;li&gt;    &lt;a href="http://www.cnblogs.com/lhb25/archive/2011/04/03/2001356.html" target="_blank"&gt;分享25个优秀的活动邀请网站设计案例&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;  &lt;p&gt; &lt;/p&gt;  &lt;p&gt;本文链接：   &lt;a href="http://www.cnblogs.com/lhb25/archive/2012/12/16/beautiful-iphone-and-android-app-websites.html" target="_blank"&gt;经典网页设计：精美的iPhone和Android App网站&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;编译来源：   &lt;a href="http://www.cnblogs.com/lhb25/" target="_blank"&gt;梦想天空 ◆ 关注前端开发技术 ◆ 分享网页设计资源&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;hide&lt;/p&gt;  &lt;img alt="" height="1" src="http://www.cnblogs.com/lhb25/aggbug/2790495.html?type=1" width="1"&gt;&lt;/img&gt;  &lt;p&gt;   &lt;a href="http://www.cnblogs.com/lhb25/archive/2012/12/17/beautiful-iphone-and-android-app-websites.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;&lt;/h3&gt;&lt;div&gt; &lt;a href="https://itindex.net/"  title="IT 资讯"&gt;&lt;img src="https://itindex.net/images/iconWarning.gif" title="IT 资讯" border="0"/&gt; &lt;/a&gt;</description>
      <category />
      <guid isPermaLink="true">https://itindex.net/detail/41173-%E7%BB%8F%E5%85%B8-%E7%BD%91%E9%A1%B5%E8%AE%BE%E8%AE%A1-%E8%AE%BE%E8%AE%A1</guid>
      <pubDate>Mon, 17 Dec 2012 14:15:00 CST</pubDate>
    </item>
  </channel>
</rss>

