`
langyu
  • 浏览: 888853 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

给新人的一些题目

    博客分类:
  • java
阅读更多
/*
* @Author: dennyy99@gmail.com
* @Date: 2012-04-02
*/


   好吧,我是有点热心了。看到ItEye上满屏的框架名词的确让人有些悲愤!如果我是一个准备学点Java用来开拓人生的新人,在出入ItEye多次后,可能见过最多的名词是SSH。这不能怪这个氛围,因为招聘要求上也是这样写的。所以许许多多的新人开始追求对SSH的一夜速成:去培训机构、搭环境、跑通例子后义无反顾地陷入到SSH的漩涡中。

    揠苗助长,应该是一个很合适的总结吧。还没搞清楚为什么有SSH,它的设计主旨是什么前就开始使用它,怎样听都让人感觉不靠谱。更可怕的是,千万不要让初学者认为这就是Java的基础呀!不然没有打好基础,对以后的职业发展不利的,你们觉着是吗?

    现实问题是:在学校老师会出师让大家做着玩,如果没有老师带,初学者想找个感兴趣的项目的机会都没有。我也是看到网上有人咨询启蒙项目的事情时,才萌生这样的想法。开发人员的成长就是需要项目的历练,这需要写很多代码,并且实际维护这些代码的产品运行。所以我来出一些适合初学者的小题目,有闲暇时间可以多做做题,长些实际经验。

    目标人群是Java初学者,必须是有兴趣,且需要有一些编程经验(无论哪种语言)。过程中遇到任何不清楚的问题请Google,对JDK不熟悉,请查阅相关文档或JDK代码。
题目的难度不算难,但需要花点时间理解我的需求。我只做一些提示,相关信息自己去Google。不要做一个懒人,高效使用Google也是开发人员基本功。期望的做题态度是:1. 自己思考,动手独立完成。2. 有些名词或想法不清楚,或是没有思路,请自行Google。3. 如果上面两步也不能解决问题,这时才可以求助于有经验的人或发贴到论坛。项目的结果才是关键,不希望纠结于小细节。不要怕犯错,不要怕写不好,不犯错是没有成长的,以后会写的越来越好。记住!结果才是关键。不建议跳着做题目,因为很多题目都是有相关性的。对编程环境没要求。程序的执行都可以从main方法开始,携带所需的参数。

    每道题目都包含“具体”的要求、提示信息或扩展训练。首要任务是完成基本的功能要求,扩展训练留作进阶或其它时间思考。为什么给具体加引号。因为做题的你可能会抱怨:怎么这个描述这么不清楚,做什么我一概没思路。这是正常的!问问这里工作过很多年的兄弟们呐,谁拿到过详细些的需求。所以希望你先试着理解我的需求,然后按你的想法来。编码过程中肯定会出现各种各样的问题,请相信自己的能力,再给自己些压力,你一定会有很多收获。事先声明:这些题目没有标准答案。


    好吧,正式看题(试试吧!)

1. 统计本地磁盘中某个目录下的所有文件数和总行数
题目要求:传入如"D:\workspace" 这样的一个目录,返回这个目录下有多少个文件,且计算这些文件的总行数。
结果示例:"Dir: D:\workspace, 1342 files, 87822 lines"

扩展训练
  • 如果传入的参数是一个文件名(不是目录名),那么你该怎么办?
  • 有在网上看过那些统计代码行数的工具软件么?没了解过的话去下载个并观摩,看能不能实现跟它一样的功能。

2. 创建指定大小的文件
题目要求:在本地磁盘上创建一个大小578MB的文件,文件内容你自己生成,可以是任何数据

扩展训练
  • 文件内容必须是一行一行的文本,内容随机生成
  • 创建十万行包含随机文本的文件
  • 要求文件中每行必须包含20列,每列一个随机字符串


3. 算出第100位斐波那契(Fibonacci)数列的值
题目要求:Fibonacci数列公式:f(0)=0, f(1)=1, f(n) = f(n-1) + f(f-2)。算出f(100)的值

提示:会出错么?会出什么错?为什么出错?根据规律来看,怎样解决呢? 用缓存可行么?


4. 审视自己的代码:编码规范
    初试手脚,感觉很不错吧。有让其它人看过你写的代码么,他们怎样评价呢? 别人看你的代码时,第一眼不是看到具体的逻辑,而是代码的组织结构和命名。清晰的代码结构和良好的命名,可以让读代码的人很容易定位到具体的逻辑,还能保持愉悦的心情。写出来的代码就是给别人来看的,它就是程序的脸面。不好看的脸谁都感觉不舒服,可能也懒得看,最典型的例子就是三国里面的庞统。所以怎样强调程序的可读性都不为过,我们平时写程序也得遵循一定的规范。幸好这事Sun已经提前想到。

题目要求:下载Sun的编码规范(在此下载),然后详加研究,确保自己都能遵守。然后重新整理之前写过的几个例子代码。运用这些编码规范,有则改之,无则加冕。

扩展训练:体会下没有编码规范会出现哪些问题?最好是把感想写下来


5.  下载Google首页到本地
题目要求:用程序访问Google首页,并把返回的首页所有内容存储到本地磁盘的单独文件中

扩展训练:看看你存储的文件里面的内容是不是很杂乱?思考下怎样过滤无用的数据,只提取我们可以在网页上看到的信息


6. 通过Java程序打开Windows下的某个文件或是执行Linux命令
题目要求:例如指定一个Word文件路径,用程序调用来启动真正的Word程序。或是让程序来执行你所要求的Linux命令。


7. 把程序打成Jar文件
题目要求:写过好几个程序了吧,是不是一直在IDE里面用main方法来执行?现在可以把程序打成一个jar包,然后在命令行用java -jar yourjarfile.jar {param} 来执行了,毕竟这是一种较通用的方式。需要了解Jar文件的组成

扩展训练:思考下如果你的程序依赖于其它的jar文件,这时候你的程序怎样可以运行起来?


8. 从某段文本中提取想要的数据
题目要求:对于这样的一段文本:Google Maps, 提取出具体的二级域名,结果就是想得到 "maps.google.com" 这样一个字符串。这样的文本在题目5所下载的文件中很常见?那么用你的方式来试着解析

扩展训练:试着用正则表达式来解析这段文本


9. 审视自己的代码:单元测试
    写上面一些代码时是不是来回折腾了不少?想想看,如果把这样的代码交付给其它人,出错来回折腾时,其它人会怎么想。是时候考虑提高自己代码质量了!

题目要求:学习Java中单元测试的方法(JUnit的使用),对上面写过的程序完善单元测试。

扩展训练
  • 仔细想想单元测试的重要性及怎样写有效的单元测试。
  • 理解单元测试、集成测试的区别。
  • 有空可以看下 测试驱动开发(TDD)的思想


10. 创建树状结构
题目要求:树状结构都不陌生,大到国家企业的组织架构,小到你本地的那个文件系统,且在以后你的程序生涯中经常会碰到。你现在需要做的事情是仿照你本地文件系统的样子,用程序来实现一棵树。包含目录和文件。文件内容可映射到本地磁盘系统的某个具体文件。可以说,你现在要做的就是在本地文件系统之上,再构建一个虚拟的文件系统。只不过物理文件还是存在本地磁盘上。 需要的功能有:1. 可以利用题目1的程序遍历树中某个目录的信息。 2. 实现添加/删除文件、添加/删除目录,添加文件时需要传入一个stream,因为你需要将这个stream保存到本地磁盘上的。

扩展训练
  • 试试当一个目录下有一万个文件时性能怎样。
  • 测试下众多目录超过一百层,可能会有哪些错误。
  • 写一个程序,随机地操作这棵树,往里面上传文件、删除目录等各种操作。(这个模拟人工操作的程序不会太好写,但相信你有自己的办法来完成)


11. 把现实世界搬到你的程序里来
题目要求:写上个例子困难么?或是压根没思路?学习面向对象思想的主旨及相关的话题。试着分析如何将现实世界中的关系映射到程序中。这会对你做上一道题有帮助。


12. 加载别人的jar文件并运行里面的代码
题目要求:题目7里面你自己拥有了可以执行的jar文件。那么现在的情况是,如果别人提供给你这样的jar文件,你怎样通过程序来运行他的jar文件里面的代码呢?有两点你需要清楚:1. 他的jar文件在哪里。2. 运行里面的哪个类的哪个方法。所以你得学习怎样加载指定路径的jar文件,怎样通过反射来执行它。

扩展训练:如果要你执行他的类里面的private方法,程序会怎么做


13. 实现文件下载服务器
题目要求:这里就是典型的CS模型了。客户端向服务器端发送了一个文件名,如"D:\server\ineedafile.txt",服务器找到这个文件,然后把这个文件通过Socket的输出流传回给客户端,然后客户端获取到这个流后,把它保存到本地的另外一个文件里,名字就叫"D:\client\ineedafile_copy.txt"。如果服务器没找个这个文件,那么就返回一个字符串"ERROR:File not found"。

提示:有两个进程,客户端和服务器,通过Socket通信。两个进程都可以在本地机器上运行。先实现功能,我没说到的地方按你的想法来补充。


14. 实现天涯的“只看楼主”功能
题目要求:就是避免在看帖子时受到其它人的影响。题目5只是小试牛刀,这里才是你大展拳脚的地方。预先提供天涯上一个版块的网址,如莲蓬鬼话,分析它的网页结构,获得每个主题帖子的网址,然后分析帖子网页结构,把楼主的话一段段保存到本地文件里。好玩吧?省得去那些乱七八糟的天涯聚类网站看恶心的广告。

提示:1. 先实现上面的功能,对于分析网页结构,可以手工分析,或用正则表达式分析,但推荐使用开源的分析HTML的项目。2. 不要太频繁地发送大量HTTP连接。天涯本来就很慢!3. 这里考验对html地址的管理,不要让你的程序跑到其它网站或扩散到其它版块。

扩展训练
  • 主题贴一般都有好多页,怎样顺着“下一页”完整地把楼主的帖子聚合起来呢?
  • 和上一条一样,版块也是分多页的,怎样收集更多的主题帖呢?


15. 审视自己的代码:程序不按套路执行怎么办
    做完上面几道题是不是对这条感触颇深?代码按着思路写好后,太多的时候不按我们设想的执行过程来。为什么?可能的原因有:你的设想就是错的;设想挺对但代码实现错了;执行时数据有问题;执行环境与设想不一样。。。 算了,不论哪种情况,查出具体的问题所在才是当务之急。

题目要求:学习如果在你的IDE里面调试Java程序!学习断点的概念,知道怎样单步执行、跳到下一断点、进入方法、查看表达式、查看变量、查看调用栈信息等知识。这些在工作中是必备技能。出错不可怕,出错可以让人更好地成长,出错时快速排查及定位、修复问题也是你的能力体现。 所以,自信地将这里学到的代码调试功夫运用到你的开发过程中吧。

扩展训练:如果程序正运行在服务器上,如何对远程的正在运行中的代码做调试呢?仔细想想,然后Google


16. Buffer的改进
题目要求:这个题目是需要先读懂Java NIO中所带的ByteBuffer,然后自己实现一个类似的Buffer。要求是:1. Buffer可以被读线程和写线程同时操作,肯定得先写后读了,且得记着读和写的位置。2. 写线程写到Buffer末尾时,如果看到Buffer头部的一段已经被读过(读过的数据就没有用了),就可以继续把数据写到这段。3. 读线程看到写的位置比自己读的位置小,那么表示还得回头从Buffer开头继续读。4.没有数据读或没有地方写,相应线程就得阻塞。整体来看,它就是生产者/消费者的中转区,且充分利用无用的空间,减少线程等待时间。


17. 索引的理解
题目要求:这节来做一个简单的“搜索引擎”,有意思吧。题目14你已经把天涯折腾了一番,现在该换个有价值的目标了:StackOverFlow。为什么说有价值?它的大多问题对于初学者来说正适合,还可以边练英文边学到真正厉害的人那种谦逊的态度。目标是:1. 改题目14的代码,下载StackOverFlow中与Java相关的论题(它的问题在这里 http://stackoverflow.com/questions/),然后存储到本地磁盘中。2. 对下载来的这些网页内容(可能每个问题一个文件),按空格来分解成一个个的单词。在内存中建立倒排索引(关键词到文件,也可以是文件的具体行)。然后把这些索引保存到单独的文件中。3. 提供程序可以根据关键词来查询到具体的StackOverFlow问题。这是不是对你的学习更有帮助?想想你本地有这样一个工具,可以随时查到你需要知道的问题,是不是很激动

提示:1. 选择StackOverFlow一方面是因为对学习有帮助,另一方面是英文分词简单,不想涉及到中文分词让大家望而却步。2. 下载到的内容的本地管理也是你需要有创造力解决的问题,加油吧。3. 查询可以只是简单地把关键词相对应的内容筛选出来(不要出来太多呀),点到为至


18. 审视自己的代码:改代码容易么
题目要求:几道题目来回折腾了好几次。这时候你的代码容易修改么?你是很了解自己的程序,如果换个其它人,他能应付过来么?思考下如何符合功能的高内聚低耦合。把功能相同的代码抽取成公用类。目标:学习重构的知识,建立起“系统”这层概念。


19. 完善文件下载服务器
题目要求:题目13只是一个简单功能的实现。假如客户端是由其它人来写,那你总得和别人约定请求与返回的协议吧?所以本题目有如下几个功能点:1. 设计文件下载的协议,供别人使用。(请求id,版本号,数据长度,错误状态等)这涉及到协议的接收与解析,值得关注。 2. 使用NIO来搭建服务器端。 3. 用题目10创建的树状系统来代替本地文件系统。4. 返回文件时使用zero-copy。

扩展训练:思考下如何实现文件下载限速


20. 接触虚拟机
题目要求:仅仅是小折腾,不做具体研究。可以尝试的例子是:1. 创建一万个线程。 2. 创建大量超过10MB的数组。3. 创建百万到千万级别的普通对象。在这三个例子的过程中,尽量不要让main方法很快退出,持续一段时间来看效果。

提示:会出错么?有任何错误请Google解决它。这个题目的目标是对JVM异常及参数有初步的认识。

扩展训练
  • 如果出现OOM,分析原因,可以创建heap dump,用MAT来分析
  • 试试VisualVM,监控JVM运行


21. 分享你的失败过程
题目要求:在经历这些小项目后,相信你一定有很多渴望分享的错误与感触。这些分享可以更好地帮助其它人进步。写出来还表示你真的体会了!



11
3
分享到:
评论
10 楼 水何慕慕 2013-03-20  
mark 下
9 楼 a450065208 2012-04-10  
楼主,对于网页获取很有研究吗,看很多题目都是关于网页抓取及分析的,我最近在学习如何获取网页中想要的内容,不知道楼主能否教导一下学习经验。比方我,我想获取谷歌翻译页面的内容,它里面有太多其他的东西,我如果只想获得翻译后的结果,能实现吗?我看了那个页面,它好像是通过js将值写在网页中的,但是我看不到那个标签是什么?望指教啊
8 楼 langyu 2012-04-09  
不好意思,这里最好不要讨论结果!
7 楼 yangnanenana 2012-04-07  
len-len 写道


这个才是正确的结果,f(100)=354224848179261915075,呵呵,考虑long溢出的问题

是滴,溢出了
6 楼 len-len 2012-04-06  
lyaqys 写道
yangnanenana 写道
关于第三题,我用数组处理了下,用时很短,不知这样做对不对,请各位指点指点~
public static void main(String[] args) {
		long begin = System.currentTimeMillis();
		long[] results = new long[101];
		results[0] = f(0);
		results[1] = f(1);
		for(int i=2;i<101;i++){
			results[i] = results[i-1] + results[i-2];
		}
		long end = System.currentTimeMillis();
		System.out.println("time:"+(end-begin));
		System.out.println("f(100)="+results[100]);
	}


打印如下:
time:0
f(100)=3736710778780434371


其实如果只是打出第100个的话,不用数组,只要两个变量就可以了的~~

2个变量不行,至少3个,一个要作为交换的临时变量
5 楼 len-len 2012-04-06  
lyaqys 写道
yangnanenana 写道
关于第三题,我用数组处理了下,用时很短,不知这样做对不对,请各位指点指点~
public static void main(String[] args) {
		long begin = System.currentTimeMillis();
		long[] results = new long[101];
		results[0] = f(0);
		results[1] = f(1);
		for(int i=2;i<101;i++){
			results[i] = results[i-1] + results[i-2];
		}
		long end = System.currentTimeMillis();
		System.out.println("time:"+(end-begin));
		System.out.println("f(100)="+results[100]);
	}


打印如下:
time:0
f(100)=3736710778780434371


其实如果只是打出第100个的话,不用数组,只要两个变量就可以了的~~


这个才是正确的结果,f(100)=354224848179261915075,呵呵,考虑long溢出的问题
4 楼 lyaqys 2012-04-06  
yangnanenana 写道
关于第三题,我用数组处理了下,用时很短,不知这样做对不对,请各位指点指点~
public static void main(String[] args) {
		long begin = System.currentTimeMillis();
		long[] results = new long[101];
		results[0] = f(0);
		results[1] = f(1);
		for(int i=2;i<101;i++){
			results[i] = results[i-1] + results[i-2];
		}
		long end = System.currentTimeMillis();
		System.out.println("time:"+(end-begin));
		System.out.println("f(100)="+results[100]);
	}


打印如下:
time:0
f(100)=3736710778780434371


其实如果只是打出第100个的话,不用数组,只要两个变量就可以了的~~
3 楼 yangnanenana 2012-04-06  
关于第三题,我用数组处理了下,用时很短,不知这样做对不对,请各位指点指点~
public static void main(String[] args) {
		long begin = System.currentTimeMillis();
		long[] results = new long[101];
		results[0] = f(0);
		results[1] = f(1);
		for(int i=2;i<101;i++){
			results[i] = results[i-1] + results[i-2];
		}
		long end = System.currentTimeMillis();
		System.out.println("time:"+(end-begin));
		System.out.println("f(100)="+results[100]);
	}


打印如下:
time:0
f(100)=3736710778780434371
2 楼 langyu 2012-04-06  
wupuyuan 写道
看完了,每个题目都不算容易哦。

后面几个题是挺不容易的,细节很多。正好锻炼怎样做一个稳定可控的项目,呵呵
1 楼 wupuyuan 2012-04-06  
看完了,每个题目都不算容易哦。

相关推荐

Global site tag (gtag.js) - Google Analytics