词频统计

  解题思路描述。

Ok!假设你现在已经完成了类似于PSP表格的东西。假设现在也对问题的需求非常清楚,当然,这是一个技术需求。在实际应用中,往往是业务需求,甚至其他需求,这就牵涉到需求分析了,这里也不是我们要体现的重点。

下面具体描述设计和实现阶段:

  1. 首先,如果你学过C++或者其他面向对象的语言,比如java,c#等等,你应该有一个最基本的思想:面向对象的思想。如果你还不善于用面向对象的思维去思考问题,其实很多时候你解决一些问题都会陷入逻辑中!

中间一旦出现一些小BUG,你就会一直在纠结logic。这里提一个额外话题就是:很多人用面向对象的语言,写出来的全篇代码却是面向过程的。我本科阶段其实经常犯这样的错误。披着面向对象的假皮。    

其实,很多设计问题就是:现实世界的实体和属性在软件系统中是怎么表现和交换信息的?

  1. 进入设计阶段,首先你应该思考的是有哪些类,这个类是怎么设计的。类的设计还是有一些原则的,比如:单一职责原则啊..等等很多啦。因为本身题目需求就是一个“数据流风格”的题目,因此大多数类都是处理类,也就是Service类。

根据“数据流风格”的设计,Service类和Service类之间可以用一种Buffer来组织,因此在我这里,我使用内存的Buffer,也就是List定义成Static的。

构件:文件处理ServiceList<Map<String,Inter>>排序ServiceList输出Service

连接件:内存StaticList

 

  1. 以上是根据题目需求,选择的设计风格。其实这是《软件体系结构的设计》,如果你对各种风格不太熟悉,可以去了解一下。当然在这里推荐我导师尚建嘎教授的书《软件体系结构与设计实用教程》,里面第三章详细讲解了各种风格,包括数据流风格,独立构件风格,层次风格,虚拟机呀,等等。其实在这个问题的设计中,很显然就是数据流风格。但是在实际生产环境中,用的最多的可能是独立构件风格呀,层次风格,SOA呀。肯定是混合着用啊。当然对应到邹欣的《构件之法-现代软件工程》228页。其实就有“表达数据的流动”这种概念。
  2. 说了这么多,你肯能会想问:逻辑去哪呢? 其实,有面向对象的思维。你首先应该考虑的是顶层设计,软件体系结构的设计。然后到具体的类,具体的方法去思考逻辑。比如这里。FileToListService这个类,你就要具体去思考:

1)如何读取文件?

2)读取到的文件如何解析?用正则还是?实际在编写的时候,比如我和鞠老师就生产出了isNum(),isZ()等等函数,

3)解析之后如何存在List里面? (Java之间可以add,因为list我们定义为Static,很好用)

再比如ListSortService这个类,如果去思考:

1)JavaSDK原生态提供的函数,还是? 你有没有新的算法?

2)根据你实际的参数的这种数据结构,你有没有新的算法去优化这种时间。JavaSDK提供的原生SDK,是一种普遍性的算法,就像快排一样,大多数情况下性能很好,但参数的数据结构有时候并不适合快排。只能说它的“熵”很大。

  1. 实际上,熟悉设计模式的小伙伴,可以很清楚的知道,之所以把List定义成static,是因为我使用的“单例模式”,这样有效的利用地缓存,千万别把List放在硬盘上,因为电脑最耗时的便是IO操作,你可以用JProfiler 分析一下。

 

二.模块的接口定义及实现。

  1. 其实这个问题的思路就是,你选择了“数据流风格”,你就一定要很清楚你当前的构件的职责是什么,也就是“单一职责原则”。比如FileToListService,它的职责就是:文件--》静态列表。然后再具体思考逻辑,得出实现,

 

三.如何体现模块的独立性。

我想这确实有必要描述一下数据流风格。

以下是引用《软件体系结构与设计实用教程》尚建嘎.

1原理与结构.

数据流风格的直观结构如下图所示:系统在数据到达时即被激活,无数据时不工作,数据流风格中数据的可用性决定着处理(计算单元)是否执行。数据在各处理之间有序的移动,在纯数据流系统中,处理之间除了数据交换,没有任何其他的交互。

数据流风格的基本构件(component)是处理,构件的接口包括输入端口和输出端口,构件在工作时从输入端口读取数据(road),经过计算/处理(comp),向输出端口写数据。

数据流风格的连接件(connector)即数据流,它是一个特殊的构件,具有读和写的两个接口,如图。数据流负责把数据从一个处理的输出端口(I)传送到另一个处理的输入端口(O),这种传输是单向的,通常是异步,有缓冲的。

 

我们的题目的处理方式就是典型的,数据流风格下的“管道--过滤器风格”;

过滤器(数据处理单元,构件)就是各个Service类,管道(连接件)就是定义在内存的staticList

过滤器能够当作一个黑盒子,这种功能上分离能够增强一些质量属性,如信息隐藏,高内聚,可修改性,和可重用性。

过滤器和其他构件以一种有限的方式进行交互,这种连接的简单保证了低耦合的特性.

由于过滤器的进程与系统其他组件是隔离的,这使得管道 过滤器系统能够并行地运行于多处理器上,或运行于一个处理器产生的多个线程上,从而提高效率.

然而,在管道 过滤器系统中,问题被分解为一系列的步骤,使用这种风格难以实现整体交 互的应用程序。但是在解决我们这个问题是完全足够的

 

 

/关键代码分析

//统计行数
一行一行读入文件,所以每行读入次数加一,但要注意去除空白行
再将分割好的单词与正则表达式匹配以便统计词频

 

//单词的词频统计
如果已有相同的单词,则词频加1
否则创建一个<key,value>以保存新的单词

 

//value的大小进行排序并输出词频最高的前十个
按字典序大小进行排序,当结果少于10个时全部输出,当结果多于10个时输出前10个结果

 

原文地址:https://www.cnblogs.com/CugYzc/p/9689898.html