存档

2011年3月 的存档

C语言知识点总结

2011年3月30日 2 条评论

有段事件没有写C程序了,有些地方有些生疏了。这两天事情比较少,准备再系统的看一边C的基础知识。这里再总结一下平时没太注意的知识要点。 1、C语言的语句块 在C语言中,任何允许出现语句的地方既可以是由;号结尾的一条语句,也可以是由{}括起来的若干条语句或声明组成的语句块(Statement Block),语句块和上一章介绍的函数体的语法相同。注意语句块的}后面不需要加;号。如果}后面加了;号,则这个;号本身又是一条新的语句了,在C语言中一个单独的;号表示一条空语句(Null Statement)。

6 int main(void)
 7 {
 8     printf("hello\n");
 9     {};  //这里相当于两个空语句了
 10
 11     int i = 0;
 12     {
 13         int i = 1;
 14         int j = 2; //每次进入语句块时为变量<code>j</code>分配存储空间,每次退出语句块时释放变量<code>j</code>的存储空间。
 15         printf("i=%d, j=%d\n",i ,j);
 16     }
 17     printf("i=%d\n", i); //can't access j here
 22     return 0;
 23 }

2、取模运算%

C99规定,如果ab是整型,b不等于0,则表达式(a/b)*b+a%b的值总是等于a。结合整数除法运算要Truncate Toward Zero,可以得到一个结论:%运算符的结果总是与被除数同号(想一想为什么)。其它编程语言对取模运算的规定各不相同,也有规定结果和除数同号的,也有不做明确规定的。

写一个函数,参数是整型变量x,功能是打印x的个位和十位:

25 void quwei(int x)
 26 {
 27     int tmp;
 28
 29     tmp = x%10;
 30     printf("个位数为:%d\n", tmp);
 31
 32     tmp = (x%100)/10;
 33     printf("十位数为:%d\n", tmp);
 34 }

3、float和double类型

7 int main()
 8 {
 9      float x = 0;  //当x定义为double时候出错,问题如何解决
 10     printf("input x:\n");
 11
 12     scanf("%f", &x);
 13
 14     printf("the x is:%f\n", x);
 15     printf("the ceil:%f\n", ceil(x));
 16     printf("the floor:%f\n", floor(x));
 17
 18 //  printf("the result is:%f\n", myround(x));
 19
 20     return 0;
 21 }

问题发现:当x定义为double类型时,上面程序错误,x读取的值有误。但是编译时需要加上-Wall选项才能发现原来是类型不匹配。

如何读取double类型变量?

4、结构体的初始化

5 int main()
 6 {
 7     //定义复数
 8     struct temp
 9     {
 10         double real;
 11         double img;
 12     };
 13
 14     double x = 2.0;
 15     //初始化复数
 16     struct temp z1 = {x, 3.0};//z1.real=2.0, z1.img=3.0
 17     struct temp z2 = {3.0,};//z2.real=3.0, z2.img=0.0
 18     struct temp z3 = {0};//z3.real=0.0, z3.img=0.0
 19
 20     return 0;
 21 }

注意:z1必须是局部变量才能用另一个变量x的值来初始化它的成员,如果是全局变量就只能用常量表达式来初始化。这也是C99的新特性,C89只允许在{}中使用常量表达式来初始化,无论是初始化全局变量还是局部变量。

{}这种语法不能用于结构体的赋值,例如这样是错误的:

20     struct temp z1;
21     z1 = {3.0, 4.0};

以前我们初始化基本类型的变量所使用的Initializer都是表达式,表达式当然也可以用来赋值,但现在这种由{}括起来的Initializer并不是表达式,所以不能用来赋值。

有些时候结构体或数组中只有某一个或某几个成员需要初始化,其它成员都用0初始化即可,用Designated Initializer语法可以针对每个成员做初始化(Memberwise Initialization),很方便。Designated Initializer是C99引入的新特性,用于初始化稀疏(Sparse)结构体和稀疏数组很方便。例如:

struct temp z1 = { .y = 4.0 }; /* z1.x=0.0, z1.y=4.0 */

结构体变量之间使用赋值运算符是允许的,用一个结构体变量初始化另一个结构体变量也是允许的,例如:

struct complex_struct z1 = { 3.0, 4.0 };
struct complex_struct z2 = z1;
z1 = z2;

同样地,z2必须是局部变量才能用变量z1的值来初始化。既然结构体变量之间可以相互赋值和初始化,也就可以当作函数的参数和返回值来传递。

struct temp add_complex(struct temp z1, struct temp z2)
 {
      z1.x = z1.x + z2.x;
      z1.y = z1.y + z2.y;
      return z1;
 }

由.运算符组成的表达式能不能做左值取决于.运算符左边的表达式能不能做左值。在上面的例子中,z是一个变量,可以做左值,因此表达式z.x也可以做左值,但表达式add_complex(z, z).x只能做右值而不能做左值,因为表达式add_complex(z, z)不能做左值。

5、枚举

4 int main()
 5 {
 6     enum my_type {RED, YELLOW};
 7     int RED = 1;
 8     printf("%d\t%d\n", RED, YELLOW);
 9
 10     return 0;
 11 }

结构体的成员名和变量名不在同一命名空间中,但枚举的成员名却和变量名在同一命名空间中,所以会出现命名冲突。以上代码是不合法的:

本文参考《Linux C编程 一站式学习》

安装和卸载Android应用程序(apk包)

2011年3月30日 没有评论

一、 安装

1. 安装第三方应用
$ adb install apk文件名

2. 安装系统应用
$ adb remount
$ adb push apk
文件名 /system/app    // apk文件名形如testme.apk

二、 卸载

1. $ adb uninstall 包名 // 包名形如com.android.testme

2. Home->设置->应用程序->管理应用程序->选择某应用程序->卸载

三、 相关文件

1. /system/app/apk文件
系统应用

2./data/app/包名.apk
第三方应用

3. /data/data/包名
此位置用于存储用户数据

4. /data/dalvik-cache/组合名.dex
dex
文件是Android 虚拟机Dalvik 支持的字节码文件格式

5. /data/data/com.android.launcher/databases/launcher.db
Launcher
Android应用程序的启动器,launcher.db是应用程序数据库。

若应用程序数据发生混乱,删掉数据库文件,并杀掉com.android.launcher进程,再使Launcher重新启动并重新生成应用程序数据库,以恢复错误
$ adb shell
$ cd /data/data/com.android.launcher/databases/
$ rm launcher.db

$ ps //
找到com.android.launcher对应的进程号
$ killall 进程号
重新进入应用列表界面(Home),此时launcher自动被重启,数据库重新生成

四、apk的格式
apk文件将AndroidManifest.xml 文件、应用程序代码(.dex 文件)、资源文件和其他文件打成一个压缩包
$ mv testme.apk xx.zip
$ mkdir tmp; cd tmp
$ unzip ../xx.zip
此时可看到apk包中的内容

使用ListView获取android联系人信息

2011年3月30日 没有评论

本文作为一个小笔记记下,站长刚开始学习Android,具体的原因还没有搞清除。就直接贴代码了:

main.xml代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="vertical" android:layout_width="fill_parent"
 android:layout_height="fill_parent">
 
 <ListView
 android:id="@+id/myListView"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 />
 
</LinearLayout>

主Activity的代码:

 

ListView myListView = (ListView)findViewById(R.id.myListView);
 
 Cursor cur = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
 null, null, null, null);
 Log.i(TAG, "获取数据库Phones的Cursor成功");
 startManagingCursor(cur);
 
 //ListAdapter是ListView和后台数据的桥梁
 ListAdapter adapter = new SimpleCursorAdapter(this,
 android.R.layout.simple_list_item_2,
 cur,
 new String[]{ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME
 , ContactsContract.CommonDataKinds.Phone.NUMBER},
 new int[] {android.R.id.text1, android.R.id.text2}
 );
 myListView.setAdapter(adapter);

运行结果如图所示:

有关讨论:

http://www.eoeandroid.com/thread-53384-1-1.html

 

 

酷壳陈皓:如何学好C++语言

2011年3月30日 没有评论

导读:作者之前发布了《如何学习C语言》,现介绍如何学习C++的相关建议。

昨天写了一篇如何学好C语言,就有人回复问我如何学好C++,所以,我把我个人的一些学习经验写在这里,希望对大家有用。首先,因为如何学好C语言中谈到了算法和系统,所以这里就只谈C++语言。

C++是最难的语言。这个世界上最难的编程语言可能非C++莫属了。你千万不要以为几天就可以学好C++,C++的学习曲线是相当BT的,你可以看 看这篇文章。C++是一门很自由的语言,自由到了有点BT和恐怖的地步。我甚至认为C++并不是一门成熟的编程语言,因为太容易犯错了。所以,你一定要在 一开始就要有很小心谨慎的态度,并把C++当成一种难以训服的猛兽来看待。

多问“为什么要这样”的问题。学习C++一定要多问几个“为什么是这样”,“凭什么要这样”的问题。比如:很多人知道C++有拷贝构造函数和初始化 列表,但你真的知道为什么要有拷贝构造函数?为什么要有初始化列表吗?为什么要有template,为什么要有 RTTI,为什么不是别的呢?难道就是为了让一门语言变得Cool一些吗?完全不是这样的,C++中的任何一个feature都有些实实在在的原因,你一 定要去了解为什么要把C++设计成这样的原因,你才能学好C++。有空看看《C++演化和设计》一书。

看书,大量的C++书。你可以按如下先后顺序阅读(下面这些书,我花了大约4-5年的时间,今天我还在随时温习)《C++ Primer》,这本初级读本可能让会你啃得很痛苦,所有的语言的特性和为什么都在里面了,好好读读。当然由C++之父写的《C++程序设计语言》也不 错。两本看一本就好了(我看的是前者)。了解C++的语法仅仅是万里长征的第一步,你还需要看看《Effective C++》和《More Effective C++》这两本书并不厚,但我从02年就一直看到现在,每次读我都有新的体会,这两本书太经典了。如果你对C语言不熟,这两本书会让你回去补C语言的课。 Think in C++同样是另一本经典之极的书,学c++必读,但是中文版的翻译的很不好,所以还是去读英文版的吧。《C++沉思录》同样非常值得一读,这里教的不是编 程,而是思考的方法,这是相当珍贵的。《Exceptional C++》和《More Exceptional C++》让你看看各种问题的解决方法和一些常见的经典错误。《Advanced C++》和《Modern C++》可以让你知道C++各种神奇的用法。《泛型编程与STL》是把C++实践到了极致的东西。很强大。STL——神一样的模板库(容器,算法和函数对 象),不得不服。

《深入探索C++对象模型》让你了解编译器下的C++是什么样的,让你了解C++的性能并不差。这个对于C++的程序员太关键了。我以前写过的《C++虚函数表解析》还有《C++对象内存布局》属于这个范畴。

和Java语言做对比。我个人以为Java对C++这个并不成熟的语言做了很多调整,规范和限制。所以,对比一 下Java和C++,想一想,为什么一些东西在C++中可以做,但在Java中却不行。比如:Java的异常是必需要catch的,不然就会编译不通过。 为什么Java不提供操作符重载?为会Java会引入接口来做多重继承?等等。Java体现着很多面向对象设计的东西,学习Java有助于你学会怎么更好 地使用C++来编程。

面向对象设计 。虽然面向对象可能是个骗局。但是我觉得面向对象设计中的一些实践非常的不错,比如,单一原则,依赖倒置原则,等等,都非常地经典。《设计模式》必需一读,《面向对象的分析和设计》可以一读。但不可以设计模式为中心来编程,而应该是用设计模式来解藕。

类库学习。看看MFC是怎么封闭Windows API的,看看ACE是怎么面向对象的,看看boost是怎么玩面向对象的,看看CPPUnit又是怎么设计的。当然,Java的JDK中有太多的设计模式,可以参考。

希望没有吓到大家,并欢迎大家补充。

原文链接:http://coolshell.cn/articles/4119.html

酷壳陈皓:如何学好C语言

2011年3月30日 2 条评论

我相信,这可能是很多朋友的问题,我以前也有这样的感觉,编程编到一定的时候,发现能力到了瓶颈,既不深,也不扎实,半吊子。比如:你长期地使用Java和.NET ,这些有虚拟机的语言对于开发便利是便利,但是对于程序员来说可能并不太好,原因有两个:

1.虚拟机屏蔽了操作系统的系统调用,以及很多底层机制。

2.大量的封装好的类库也屏蔽了很多实现细节。

一段时间后,你会发现你知其然,不知所以然。。我以前在CSDN上写过一篇《Java NIO类库Selector机制解析》,在那篇文章中我说提到过(有讥讽的语气)Java的程序员不懂底层实现,所以很难把技术学得更扎实。此时,一部分程序员会不自然地想学学底层的技术,很自然的,C语言就被提了上来。

下面是我给这位朋友的一些建议:

鼓励并为你叫好。我鼓励你想要去学C语言的想法和精神,很多人都觉得C语言好学,其实并不然,现在的这个社会更 多地去关注那些时髦的技术,而忽略了这个流行了40+年的C语言。一门技术如果能够流行40多年,这才是你需要去关注和学习的技术,而不是那些刚出来的技 术(过度炒作的技术,Windows编程史)。这才是踏踏实实的精神。

不要找借口。这一条路走下来并不容易,不要给自己找借口。我最不喜欢听到的就是“很忙,没有时间”这样的借口。 我以前在银行做项目,早9点到晚10点,周一到周六,我一样可以每天抽1个小时来看书和专研,一年下来也能精读5、6本书。我现在的工作项目和招聘任务很 紧张,刚生的小孩只有自己和老婆两人带,还需要准备讲课,但是我还是能够找到时间看文章写文章维护酷壳。所以,我可以告诉你,“时间就像乳沟,只要你肯 挤,就一定会有”。

学好C语言和系统编程。我认为,学好编程有四个方面:语言、算法和数据结构、系统调用和设计。

语言。我可以告诉你C语言有两大主题你要好好学,一个是内存管理,一个是指针!这个世界上90%以上的C/C++出的严重性错误全是和这两个有关。不要看谭浩强的那本书,那本是本烂书。推荐这本书给你《C程序设计语言(第2版·新版)》

算法和数据结构。我认为,用C语言实现算法和数据结构莫过于最爽的事情。推荐你看这本书——算法:C语言实现(第1~4部分)基础知识、数据结构、排序及搜索(原书第3版)

系统编程。Windows下推荐两本书——《Windows 程序设计 》和《Windows核心编程》,Unix/Linux下推荐两本书——《Unix高级环境编程》和《Unix网络编程卷1,套接字》《Unix网络编程 卷2,进程间通信》尤其是《Unix网络编程》这本书,一通百通,无论Windows还是Unix/Linux,都是一样的。

系统设计。关于设计方面,我全力推荐《Unix编程艺术》,看完以后,你就明白什么是真正的编程文化了。然后,当你看到Windows的Fans的某些言论时,你就知道什么叫一笑了之了。

如果你能在2-3年内精读完这些书,并全部融会贯通,那么你就明白什么是一览众山小的感觉了!我足足花了5年时间才算是真正全部读完这些书的。最后,祝你好运!努力!

原文链接:http://coolshell.cn/articles/4102.html

OpenFlow:用于NoSQL的网络协议

2011年3月29日 没有评论

 

[本文转自CSDN]Paul Baran在60年代初,Paul Baran发明了分包交换(一个通信方式的范例,将信息以封包形式个别传递于主机间,而不需事先建立通信通路)技术。分包交换技术是ARPANET的基 础,后来互联网出现了。但封包交换技术在多年之后仍是计算机网络的重要基础。不幸的是Paul Baran在上周六去世了,享年84岁。

但是正如芯片产业一样,数据库和编程语言已经进入了一个高专业性的阶段,我们可能会看到专业的网络拓扑也会这样。上周,一些互联网巨头,包括Facebook谷歌雅虎制定了开放式网络基础,这个联盟致力于促进软件定义的网络(Software-Defined Networking),该联盟的首要任务是所谓的OpenFlow协议。对于网络工程师们来说,至关重要的一点是在管理交换机时可定制固件,适合现代网络的所有设备。

在NoSQL中,像BigTable,Cassandra和HBase这些非关系数据库,它们能够帮助企业创造新的数据库体系机构。OpenFlow协议可以实现高度定制化的网络拓扑结构,并与封包交换技术与线路交换模式相结合。

我们相信OpenFlow是现今一个务实且折中的协议,一方面它允许研究人员用统一的方式在各种各样线速和高密度端口的交换机上进行试验,而另一方面供应商又不需提供交换机内部的工作原理。

德国电信,Facebook,谷歌,微软Verizon和雅虎是开放式网络基金会的主要成员。其他几个主要技术公司的成员包括像设备厂商Netgear。(李智/译)

关于Paul Baran

Paul Baran于1926年4月29日出生在波兰,但是他的家庭在1928年搬到波士顿。他在1959年获得工程学硕士学位并且在同年为RAND公司工作。后来他与Donald Davies和Leonard Kleinrock一起发明了分组交换网络。

相关阅读:OpenFlow白皮书

原文链接:OpenFlow: The NoSQL of Network Protocols

2011中国(深圳)IT领袖峰会视频:马化腾马云李彦宏巅峰对话

2011年3月29日 1 条评论

2011中国(深圳)IT领袖峰会视频:马化腾马云李彦宏巅峰对话

Hadoop 简介

2011年3月28日 没有评论

Hadoop是Apache开源组织的一个分布式计算开源框架(http://hadoop.apache.org/),在很多大型网站上都已经得到了应用,如亚马逊、Facebook和Yahoo等等。对于我来说,最近的一个使用点就是服务集成平台的日志分析。服务集成平台的日志量将会很大,而这也正好符合了分布式计算的适用场景(日志分析和索引建立就是两大应用场景)。

什么是Hadoop?

Hadoop框架中最核心的设计就是:MapReduce和HDFS。MapReduce的思想是由Google的一篇论文所提及而被广为流传的,简单的 一句话解释MapReduce就是“任务的分解与结果的汇总”。HDFS是Hadoop分布式文件系统(Hadoop Distributed File System)的缩写,为分布式计算存储提供了底层支持。

MapReduce从它名字上来看就大致可以看出个缘由,两个动词Map和Reduce,“Map(展开)”就是将一个任务分解成为多个任 务,“Reduce”就是将分解后多任务处理的结果汇总起来,得出最后的分析结果。这不是什么新思想,其实在前面提到的多线程,多任务的设计就可以找到这 种思想的影子。不论是现实社会,还是在程序设计中,一项工作往往可以被拆分成为多个任务,任务之间的关系可以分为两种:一种是不相关的任务,可以并行执 行;另一种是任务之间有相互的依赖,先后顺序不能够颠倒,这类任务是无法并行处理的。回到大学时期,教授上课时让大家去分析关键路径,无非就是找最省时的 任务分解执行方式。在分布式系统中,机器集群就可以看作硬件资源池,将并行的任务拆分,然后交由每一个空闲机器资源去处理,能够极大地提高计算效率,同时 这种资源无关性,对于计算集群的扩展无疑提供了最好的设计保证。(其实我一直认为Hadoop的卡通图标不应该是一个小象,应该是蚂蚁,分布式计算就好比 蚂蚁吃大象,廉价的机器群可以匹敌任何高性能的计算机,纵向扩展的曲线始终敌不过横向扩展的斜线)。任务分解处理以后,那就需要将处理以后的结果再汇总起 来,这就是Reduce要做的工作。

MapReduce结构示意图
图1:MapReduce结构示意图

上图就是MapReduce大致的结构图,在Map前还可能会对输入的数据有Split(分割)的过程,保证任务并行效率,在Map之后还会有Shuffle(混合)的过程,对于提高Reduce的效率以及减小数据传输的压力有很大的帮助。后面会具体提及这些部分的细节。

HDFS是分布式计算的存储基石,Hadoop的分布式文件系统和其他分布式文件系统有很多类似的特质。分布式文件系统基本的几个特点:

  1. 对于整个集群有单一的命名空间。
  2. 数据一致性。适合一次写入多次读取的模型,客户端在文件没有被成功创建之前无法看到文件存在。
  3. 文件会被分割成多个文件块,每个文件块被分配存储到数据节点上,而且根据配置会由复制文件块来保证数据的安全性。

HDFS结构示意图
图2:HDFS结构示意图

上图中展现了整个HDFS三个重要角色:NameNode、DataNode和Client。NameNode可以看作是分布式文件系统中的管理 者,主要负责管理文件系统的命名空间、集群配置信息和存储块的复制等。NameNode会将文件系统的Meta-data存储在内存中,这些信息主要包括 了文件信息、每一个文件对应的文件块的信息和每一个文件块在DataNode的信息等。DataNode是文件存储的基本单元,它将Block存储在本地 文件系统中,保存了Block的Meta-data,同时周期性地将所有存在的Block信息发送给NameNode。Client就是需要获取分布式文 件系统文件的应用程序。这里通过三个操作来说明他们之间的交互关系。

文件写入:

  1. Client向NameNode发起文件写入的请求。
  2. NameNode根据文件大小和文件块配置情况,返回给Client它所管理部分DataNode的信息。
  3. Client将文件划分为多个Block,根据DataNode的地址信息,按顺序写入到每一个DataNode块中。

文件读取:

  1. Client向NameNode发起文件读取的请求。
  2. NameNode返回文件存储的DataNode的信息。
  3. Client读取文件信息。

文件Block复制:

  1. NameNode发现部分文件的Block不符合最小复制数或者部分DataNode失效。
  2. 通知DataNode相互复制Block。
  3. DataNode开始直接相互复制。

最后再说一下HDFS的几个设计特点(对于框架设计值得借鉴):

  1. Block的放置:默认不配置。一个Block会有三份备份,一份放在NameNode指定的DataNode,另一份放在与指定 DataNode非同一Rack上的DataNode,最后一份放在与指定DataNode同一Rack上的DataNode上。备份无非就是为了数据安 全,考虑同一Rack的失败情况以及不同Rack之间数据拷贝性能问题就采用这种配置方式。
  2. 心跳检测DataNode的健康状况,如果发现问题就采取数据备份的方式来保证数据的安全性。
  3. 数据复制(场景为DataNode失败、需要平衡DataNode的存储利用率和需要平衡DataNode数据交互压力等情况):这里先说一下, 使用HDFS的balancer命令,可以配置一个Threshold来平衡每一个DataNode磁盘利用率。例如设置了Threshold为10%, 那么执行balancer命令的时候,首先统计所有DataNode的磁盘利用率的均值,然后判断如果某一个DataNode的磁盘利用率超过这个均值 Threshold以上,那么将会把这个DataNode的block转移到磁盘利用率低的DataNode,这对于新节点的加入来说十分有用。
  4. 数据交验:采用CRC32作数据交验。在文件Block写入的时候除了写入数据还会写入交验信息,在读取的时候需要交验后再读入。
  5. NameNode是单点:如果失败的话,任务处理信息将会纪录在本地文件系统和远端的文件系统中。
  6. 数据管道性的写入:当客户端要写入文件到DataNode上,首先客户端读取一个Block然后写到第一个DataNode上,然后由第一个 DataNode传递到备份的DataNode上,一直到所有需要写入这个Block的NataNode都成功写入,客户端才会继续开始写下一个 Block。
  7. 安全模式:在分布式文件系统启动的时候,开始的时候会有安全模式,当分布式文件系统处于安全模式的情况下,文件系统中的内容不允许修改也不允许删 除,直到安全模式结束。安全模式主要是为了系统启动的时候检查各个DataNode上数据块的有效性,同时根据策略必要的复制或者删除部分数据块。运行期 通过命令也可以进入安全模式。在实践过程中,系统启动的时候去修改和删除文件也会有安全模式不允许修改的出错提示,只需要等待一会儿即可。

下面综合MapReduce和HDFS来看Hadoop的结构:

Hadoop结构示意图
图3:Hadoop结构示意图

 

在Hadoop的系统中,会有一台Master,主要负责NameNode的工作以及JobTracker的工作。JobTracker的主要职责 就是启动、跟踪和调度各个Slave的任务执行。还会有多台Slave,每一台Slave通常具有DataNode的功能并负责TaskTracker的 工作。TaskTracker根据应用要求来结合本地数据执行Map任务以及Reduce任务。

说到这里,就要提到分布式计算最重要的一个设计点:Moving Computation is Cheaper than Moving Data。就是在分布式处理中,移动数据的代价总是高于转移计算的代价。简单来说就是分而治之的工作,需要将数据也分而存储,本地任务处理本地数据然后归 总,这样才会保证分布式计算的高效性。

为什么要选择Hadoop?

说完了What,简单地说一下Why。官方网站已经给了很多的说明,这里就大致说一下其优点及使用的场景(没有不好的工具,只用不适用的工具,因此选择好场景才能够真正发挥分布式计算的作用):

  1. 可扩展:不论是存储的可扩展还是计算的可扩展都是Hadoop的设计根本。
  2. 经济:框架可以运行在任何普通的PC上。
  3. 可靠:分布式文件系统的备份恢复机制以及MapReduce的任务监控保证了分布式处理的可靠性。
  4. 高效:分布式文件系统的高效数据交互实现以及MapReduce结合Local Data处理的模式,为高效处理海量的信息作了基础准备。

使用场景:个人觉得最适合的就是海量数据的分析,其实Google最早提出MapReduce也就是为了海量数 据分析。同时HDFS最早是为了搜索引擎实现而开发的,后来才被用于分布式计算框架中。海量数据被分割于多个节点,然后由每一个节点并行计算,将得出的结 果归并到输出。同时第一阶段的输出又可以作为下一阶段计算的输入,因此可以想象到一个树状结构的分布式计算图,在不同阶段都有不同产出,同时并行和串行结 合的计算也可以很好地在分布式集群的资源下得以高效的处理。

相关阅读:

  1. Hadoop中的集群配置和使用技巧――分布式计算开源框架Hadoop入门实践(二)
  2. Hadoop基本流程与应用开发――分布式计算开源框架Hadoop入门实践(三)

转自:http://www.infoq.com/cn/articles/hadoop-intro

站长收集的有关hadoop经典文章:

用 Hadoop 进行分布式数据处理,第 1 部分: 入门

分类: 叽歪生活 标签: ,

美12岁神童攻读数学博士 挑战爱因斯坦相对论

2011年3月28日 没有评论

(本文转自CSDN)据外国媒体报道,在美国有一名12岁的小男孩,他的智商比爱因斯坦还高,达170。目前,他正在印第安那大学学习,导师们正安排他攻读博士学位。这 名“神童”名叫雅各布.巴内特。他在一个星期里教自己学会了微积分、代数和几何等学科,还经常辅导自己的大学同学。现在,他开始着手挑战爱因斯坦的相对论 ——他将其命名为“爱因斯坦相对论扩展版”。

http://articles.csdn.net/uploads/allimg/110328/0911232263-0.jpg

他的母亲克里斯汀弄不清儿子到底是天才还是在胡说,于是将雅各布的学说录像寄给了普林斯顿附近的高等研究院。研究院的天体物理学家斯科特.特里梅证 实了其真实性。他在给雅各布一家的邮件里写道:“他研究的理论中,包含有几个最深奥的天体物理学和理论物理学难题。任何解决这些问题的人,都会得到诺贝尔 奖。”

克里斯汀对媒体表示,雅各布的学识一定不是遗传于自己,因为“我的数学不及格”。

不单是克里斯汀,雅各布的家人数学都不好。他就曾抱怨说:“我每次和家里人讨论数学,他们就茫然地看着我。”

报道称,雅各布患有亚斯伯格综合征和轻微的自闭症,一直到2岁才说话。他的父母为此很担心。直到他长大后,他们才知道儿子的天分。

雅各布3岁就开始玩5000片的拼图游戏,甚至研究了州公路地图,记得每一条高速路。

8岁时,他从中学毕业,参加了印第安纳大学与普渡大学印第安纳波利斯联合分校的天体物理学高级班。他的同学至少都是18岁以上的成年人,但只要他们遇到了问题,都会来找雅各布。

他的教授罗斯说,雅各布会经常在课间来找自己,问很多更详细的问题。

不过,天才总会付出一些“代价”。雅各布的父母说,他晚上很难睡好,脑海里总是出现数字。现在,他把这些时间都用来研究相对论。

原文链接:http://www.cnbeta.com/articles/138428.htm

今天买了款手机

2011年3月26日 没有评论

今天在卓越给小妹买了款手机,通过卓越联盟再省了几块大洋。

在卓越联盟中获取这个手机的代码,放在这里:

诺基亚2690(Nokia 2690)时尚直板音乐手机(银白色)

我通过上面的链接再去买手机,在原来的价位上省了几块钱哈。。

分类: 叽歪生活 标签:

A return to Good Code

2011年3月25日 没有评论

Stop doing this:

public boolean foo() {
 if (true) {
 return true;  
 }  else {  
 return false;  
 }
 }

It always amazes me when I dig into an open source project, and I see code written by supposed experts, and reviewed by seasoned professionals, and nobody slaps the wrists of the developer who shoves return statements right in the middle of a method.
Tell me, how hard is it to do this:

 public boolean foo() {  
 boolean flag = true;  
 if (true) { 
 flag=true;
 }  
 else {
 flag=false;
 }
 return flag;
 }

This is Java 101. Actually, it’s not even Java 101. It’s grade school Java. If a method returns a value, you declare that value as a variable at the start of the method. Then you do things that will give that variable the appropriate meaning. And then, on your last line of code, you return that variable to the calling program. And doing so is more than just about writing good code. It’s about being polite.
Have you ever tried to troubleshoot some code that has return statements thrown around all over the method? It’s impossible. In fact, the first step in troubleshooting such a method is to rework the darn thing so that it doesn’t have a bunch of return statements in it. And it can always be done. There is no method that can’t be re-written to have just one, single, easy to identify return statement at the end of it.
Sure, bad programmers have a million different reasons as to why they must program poorly. “I just wanted to avoid a bunch of superfluous conditional statements that the code might have to go through later on.” Well, first of all, computers are darned good at quickly evaluating a few conditional statements, so short-circuiting a method to avoid a clock cycle or two is simply ridiculous. And besides, if there’s a bunch of superfluous conditional statements that end up getting bypassed, maybe that’s a good indication that your ‘superfluous’ code should be rewritten, perhaps factored out into a different method that isn’t superfluous?
The bottom line is that there’s no excuse for writing bad code or being a lazy programmer, especially when writing good code isn’t that much more difficult. Stop writing methods with a million return statements in them. A method in Java can only return one thing, and correspondingly, a method should have only one return statement in it.

译文:

别再这样写了:

public boolean foo() {if (true) { 

return true;

}  else {

return false;

}

}

每次当我深入某个开源项目,看到大概是某个专家写的、并被有经验的专业人士审查过的这样的代码,我都会惊讶不已,竟然没有人去阻止这个开发者在这个方法里胡乱的放置返回语句。

请告诉我,把代码写成下面的样子很难吗?

public boolean foo() { 

boolean flag = true;

if (true) {

flag=true;

}

else {

flag=false;

}

return flag;

}

 

这是Java基本常识。实际上,这不仅是Java基本常识,这是小学水平的Java知识。如果你的方法返回一个值,你应该在方法的开始处把它声明做 一个变量。然后再去做一些赋予这个变量正确意义的操作。然后,在你的最后一行,把这个变量返回给调用程序。这样做不仅仅是为写出好的代码,这是一种有教养 的表现。

你是否曾试图修改过一些在方法里到处都是返回语句的程序代码?无从下手。事实上,去维护这样的代码,你第一要做的是重新组织它的结构,让它里面不再 有一大 堆的返回语句。这样才能把事情做好。没有任何一个方法是不可以写成只在末尾处有一个的、单一的、易于找到的返回语句的形式的。

的确,烂程序员总有一万个理由来说明他们为什么编写出这样糟糕的程序代码。“我只是为了避免在返回时一堆的多余的条件判断语句。”那好,首先,我告 诉你, 计算机中执行一些条件判断语句时是该死的快,你用短路一个方法来节省CPU的一两个指令操作不是显的太荒诞了吗。此外,如果这些所谓多余的条件判断语句最 终没有派上用场的话,这是否是一个有用的信号来说明你的“多余”的代码可能需要重写,也许可以把它们重构成另外一个方法,让它们显的不多余?

关键要说的是,没有任何理由可以为写糟糕的代码或当懒惰的程序员做托辞,特别是当写出好的代码并不是那么困难的情况下。不要在写出里面有成百上千个返回语句的方法了。Java里的方法只可以返回一个值,相应的,一个方法应该有且只有一个返回语句。

原文链接: A return to Good Code

分类: 叽歪生活 标签:

Java语言基础:内部类

2011年3月25日 没有评论
1.  普通内部类
  • 普通内部类的一个最简单的例子:
  1. // 外部类
  2. class OutterClass {
  3. // 内部类
  4. public class InnerClass {
  5. private int i = 0;
  6. public int getInt(){
  7. return i;
  8. }
  9. }
  10. public void proc(){
  11. InnerClass inClass = new InnerClass();
  12. System.out.println(inClass.getInt());
  13. }
  14. }
  15. public class Main {
  16. public static void main(String[] args) {
  17. OutterClass outClass = new OutterClass();
  18. outClass.proc();
  19. }
  20. }
  • 外部类可以访问内部类的私有成员,内部类也可以访问外部类的私有成员:
  1. // 外部类
  2. class OutterClass {
  3. private int mOut = 10;
  4. // 内部类
  5. public class InnerClass {
  6. private int mIn = 0;
  7. public void printOutPrivate(){
  8. // 直接打印外部类的成员
  9. System.out.println(mOut);
  10. }
  11. }
  12. public void printInPrivate(){
  13. InnerClass inClass = new InnerClass();
  14. // 直接打印内部类的私有成员
  15. System.out.println(inClass.mIn);
  16. }
  17. public void printOutPrivate(){
  18. InnerClass inClass = new InnerClass();
  19. inClass.printOutPrivate();
  20. }
  21. }
  22. public class Main {
  23. public static void main(String[] args) {
  24. OutterClass outClass = new OutterClass();
  25. outClass.printInPrivate();
  26. outClass.printOutPrivate();
  27. }
  28. }
  • 如果外部类的成员变量与内部类的成员变量名字相同,当内部类要访问外部类的该成员时,可以使用“OutClass.this.mem”来区分:
  1. // 外部类
  2. class OutterClass {
  3. private int mMem = 10;
  4. // 内部类
  5. public class InnerClass {
  6. private int mMem = 0;
  7. public void printOutPrivate(){
  8. // 直接打印外部类的成员
  9. System.out.println(OutterClass.this.mMem);
  10. }
  11. }
  12. }
  • 要创建普通内部类,必须先创建相应的外部类:
  1. // 外部类
  2. class OutterClass {
  3. private int mMem = 10;
  4. // 内部类
  5. public class InnerClass {
  6. private int mMem = 0;
  7. public void printOutPrivate(){
  8. // 直接打印外部类的成员
  9. System.out.println(OutterClass.this.mMem);
  10. }
  11. }
  12. }
  13. public class Main {
  14. public static void main(String[] args) {
  15. OutterClass outClass = new OutterClass();
  16. OutterClass.InnerClass inClass = outClass.new InnerClass();
  17. inClass.printOutPrivate();
  18. }
  19. }
也可以用下面的方式:
  1. // 外部类
  2. class OutterClass {
  3. private int mMem = 10;
  4. // 内部类
  5. public class InnerClass {
  6. private int mMem = 0;
  7. public void printOutPrivate(){
  8. // 直接打印外部类的成员
  9. System.out.println(OutterClass.this.mMem);
  10. }
  11. }
  12. public InnerClass newInnerClass() {
  13. return new InnerClass();
  14. }
  15. }
  16. public class Main {
  17. public static void main(String[] args) {
  18. OutterClass outClass = new OutterClass();
  19. OutterClass.InnerClass inClass = outClass.newInnerClass();
  20. inClass.printOutPrivate();
  21. }
  22. }
2.  静态内部类
普通内部类前面加上static修饰符,就成为静态内部类,静态内部类类似于C++的嵌套类,与普通内部类相比有如下区别:
  • 静态内部类没有指向外部类的引用,外部类对于它来说更像一个名字空间。
  • 普通内部类不能有静态成员,静态方法,或另一个静态内部类;而静态内部类可以有这一切。
  • 静态内部类可以直接创建,不必先创建外部类:
  1. // 外部类
  2. class OutterClass {
  3. private int mMem = 0;
  4. // 静态内部类
  5. static public class InnerClass {
  6. private int mMem = 0;
  7. public void printOutPrivate(){
  8. // 这是错误的
  9. // System.out.println(OutterClass.this.mMem);
  10. }
  11. }
  12. public void printInPrivate() {
  13. InnerClass inClass = new InnerClass();
  14. // 可以直接访问静态内部类的成员
  15. System.out.println(inClass.mMem);
  16. }
  17. }
  18. public class Main {
  19. public static void main(String[] args) {
  20. // 直接创建静态内部类
  21. OutterClass.InnerClass inClass = new OutterClass.InnerClass();
  22. inClass.printOutPrivate();
  23. }
  24. }
从上面描述可以看出,静态内部类与一般类没有太大区别,只不过它是放在一个类的里面,这个类相当于它的名字空间,可以防止命名冲突。
3.  局部内部类
Java可以把一个类定义在一个方法里面,甚至是一个{}块里面,它的作用域就在这个块里面:
  1. // 外部类
  2. class OutterClass {
  3. public void testLocalInner() {
  4. if (true)
  5. {
  6. class LocalInner {
  7. public void proc() {
  8. System.out.println(“hello”);
  9. }
  10. }
  11. // 可以创建使用
  12. LocalInner localInner = new LocalInner();
  13. localInner.proc();
  14. }
  15. // 错误:超出类定义的作用域
  16. LocalInner localInner = new LocalInner();
  17. localInner.proc();
  18. }
  19. }
局部内部类的一般用途是实现某个接口,并作为这个接口传出方法被使用:
  1. // 接口
  2. interface Talker {
  3. public void Talk();
  4. }
  5. // 外部类
  6. class OutterClass {
  7. public Talker getTalker() {
  8. // 现实该接口的局部内部类
  9. class SomeTalker implements Talker {
  10. public void Talk() {
  11. System.out.println(“hello”);
  12. }
  13. }
  14. // 创建类实例并作为Talker返回
  15. SomeTalker talker = new SomeTalker();
  16. return talker;
  17. }
  18. }
  19. public class Main {
  20. public static void main(String[] args) {
  21. OutterClass outClass = new OutterClass();
  22. Talker talker = outClass.getTalker();
  23. talker.Talk();
  24. }
  25. }
4.  匿名内部类
匿名内部类的语法如下:
  1. new InterfaceName(){……}; 或 new SuperclassName(){……};
它被认为是InterfaceName的实现者,或是SuperclassName的继承类,匿名内部类没有构建函数,如果SuperclassName有带参数的构造函数,必须在创建匿名内部类时带上这些参数,下面是匿名内部类最常见的使用场合:
  1. // 接口
  2. interface Talker {
  3. public void Talk();
  4. }
  5. // 外部类
  6. class OutterClass {
  7. public void Talk(Talker talker) {
  8. talker.Talk();
  9. }
  10. }
  11. public class Main {
  12. public static void main(String[] args) {
  13. OutterClass outClass = new OutterClass();
  14. // 直接生成一个匿名内部类
  15. outClass.Talk(new Talker(){
  16. public void Talk() {
  17. System.out.println(“hello”);
  18. }
  19. });
  20. }
  21. }

Java语言基础:final和static[转]

2011年3月25日 没有评论
1. final
final可以修饰类,成员方法,成员变量;表示最终的,不能修改,不能继承的:
  • final类不能被继承,类中的方法默认是final方法,但类中的成员变量不是。
  • final方法不能被子类覆盖,可以这样理解:JAVA中的普通方法等于C++的虚方法,JAVA中的final方法等于C++中的普通方法。
  • final成员表示常量,只能在声明时赋值一次,以后不能再被赋值。
public class Test {
private final String S=”final实例变量”;
private final int A=10;
}
  • final函数参数表示该参数为常量,不能在函数中改变:
public void f1(final int i){
i++; //错误:i是final类型的,值不允许改变
System.out.print(i);
}
2. static
static表示全局静态,用来修饰成员方法,成员变量,可以形成static代码块:
  • static方法与c++的静态方法类似,不必创建类实例即可使用,不能使用this和super关键字,且只能访问类中的static成员或static方法。
  • static成员变量与C++的静态成员类似,为所有类实例共用,注意JAVA没有局部静态变量。
public class Main {
static int i = 100;
}
  • static静态代码块,是在JVM加载类时就执行的代码块,只执行一次,可以用来初始化静态变量:
public class Main {
static int i = 100;
static {
i = 30;
}
public static void main(String[] args) {
// 此处i应该是30
System.out.println(i);
}
}
3. final和static一起使用
类似于C++的全局常量:
static final int j = 200;

原文:http://blog.csdn.net/linzhengqun/archive/2011/03/23/6272790.aspx

Android开发学习笔记[转]

2011年3月24日 没有评论

NoSql数据库MongoDB学习(四)JAVA连接MongoDB

2011年3月22日 没有评论

首先,我们要安装MongoDB的JAVA开发驱动:

MongoDB官方提供的驱动下载地址为:https://github.com/mongodb/mongo-java-driver/downloads

我选择的是mongo-2.5.jar 版本,然后根据官方提供的文档知道,要想用JAVA连接mongoDB只需要将驱动的jar文件加入到环境变量的classpath中即可。

(注意:我把jar文件放在d:\mongodb\目录下,在classpath中需要指定完整的文件路径:d:\mongodb\mongo-2.5.jar。我开始时候指定了d:\mongodb\,发生错误)。

其次,启动mongoDB服务器,如何启动我们已经在前面的章节中讲过了。可以参见:

NoSql数据库MongoDB学习(二)MongoDB安装

最后,我们写个测试的程序,用来连接mongodb,代码如下

import com.mongodb.*;
public class Main
{
   public static void main(String[] args)
   {
      try
      {
        //连接数据库(三种连接方式):
        //Mongo m = new Mongo();
        //Mongo m = new Mongo( "localhost" );
        //Mongo m = new Mongo( "localhost" , 27017 );
        Mongo m = new Mongo("127.0.0.1");
        //选择数据库,如果没有这个数据库的话,会自动建立
       DB db = m.getDB("book");
      //列出所有数据库名,不过发现,如果数据库里面是没有数据的话,并不会被列出来
       System.out.println("数据库列表:\n"+m.getDatabaseNames());
 
      }
      catch(Exception error)
     {
        error.printStackTrace();
     }
   }
}

程序的运行效果图: