现在的Java程序中用到了Stanford Parser,在程序功能完整实现后,我开始对这个Parser的使用进行加速。
  由于采用的直接嵌入式的调用,没有遇到命令行调用方式下会遇到的资源重复加载的问题。在主控程序中对Parser采用一个类(A)的静态函数来加载所需资源到该类的静态成员变量上,就得到了一个全局的常驻内存资源。哈哈,第一次采用这种方案来实现全局资源,感觉甚为不错!在类A中另写了一个静态函数来执行句法分析。在对文件的处理循环中的某个特征抽取部分,使用类A的静态句法分析函数,从而实现了全局的调用。
  加速方案我采用的主要有两种:
     - 如果pair的第二个元素和第一个元素位于同一个句子,就只parse一次。
- 在类A的parse函数中对已经parse过的句子直接加载parse结果。
第一个方法实现起来非常简单,关键是第二个。尝试了几种解决方案后我最后结合hashcode和序列化方法实现了这个功能。这里记录一下,以备查找。
  hashcode是对即将Parse的句子采用.HashCode()方法获得这个对象唯一的整数索引值,将这个索引值对应成文件名即可实现每个句子parse后对应一个唯一的文件。说起来这个hashcode函数还真是很神奇的 :)
  序列化是我在Python里面常用的技巧,想来就是将对象存入文件以及从文加载对象两步。基于原理都是一样的。但是看了一下Java中对序列化的介绍后,感觉序列化功能也是有巨大应用功能的。参考了一下如下一段讲述Java序列化方法的文章后完成了我的Parse加速。
              | 3.一般序列化实例           程序名称:SerializationDemo.java
 程序主题:实现对象的序列化和反序列化
 程序说明:该程序由实例化一个MyClass类的对象开始,该对象有三个实例变量,类型分别为String、int、double,是希望存储和恢复的信息。
 import java.io.Serializable;
 class MyClass implements Serializable {
 String s;
 int i;
 double d;
 public MyClass(String s, int i, double d) {
 this.s = s;
 this.i = i;
 this.d = d;
 }
 public String toString() {
 return "s=" + s + ";i=" + i + ";d=" + d;
 }
 }
 要想序列化对象,你必须先创建一个OutputStream,然后把它嵌进ObjectOutputStream。这时,你就能用writeObject ( )方法把对象写入OutputStream了。读的时候,你得把InputStream嵌到ObjectInputStream里面,然后再调用 readObject( )方法。
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 public class SerializationDemo {
 public static void main(String args[]) {
 FileInputStream in = null;
 FileOutputStream out = null;
 ObjectInputStream oin = null;
 ObjectOutputStream oout = null;
 MyClass object1 = new MyClass("Hello", -7, 2.7e10);
 System.out.println("object1:" + object1);
 // Object serialization
 try {
 out = new FileOutputStream("serial.txt");
 oout = new ObjectOutputStream(out);
 oout.writeObject(object1);
 oout.close();
 } catch (Exception e) {
 System.out.println("Exception during serialization:" + e);
 System.exit(0);
 }
 // Object deserialization
 try {
 MyClass object2;
 in = new FileInputStream("serial");
 oin = new ObjectInputStream(in);
 object2 = (MyClass) oin.readObject();
 oin.close();
 System.out.println("object2:" + object2);
 } catch (Exception e) {
 System.out.println("Exception during deserialization:" + e);
 System.exit(0);
 } finally {
 // …此处省略
 }
 }
 }
 结果:
 object1:s=Hello;i=-7;d=2.7E10
 object2:s=Hello;i=-7;d=2.7E10
 | 
   
   
  现在我的程序正在健步如飞的运行着,任何两个一模一样的句子都只会被parse一次。
   
  序列化和hashcode搭配起来真是不错~!
  
 
1 条评论:
您好,请问您是如何 在java程序中使用Stanford Parser api的? 我是这样用的
LexicalizedParser lexParser = new LexicalizedParser(“englishPCFG.ser.gz”);
public String parse(String sentence)
{
lexParser.parse(sentence);
String s = lexParser.getBestParse().toString();
return s;
}
,但是,当连续分析了很多句子后(多次调用parse),内存消耗非常大。希望能得到您的帮助。谢谢。我的邮箱lujun59[AT]gmail.com
发表评论