问候,
介绍现在,我们有一个TextProcessor,一个LibraryBuilder以及一个Library
本身。 上周您阅读时,图书馆有能力产生文字
以一种简单的方式。 我们还简要提到了BookMark,它代表了
单段文字。 我们尚未看到它的实现。 这是
本周文章部分的主题。
书签实施由于书签与图书馆紧密结合,因此我决定实施
书签作为嵌套的非静态类。 这允许实现
使用所有图书馆,包括图书馆的私人部分。 我创造性地命名
该类为BookMarkImpl。 因为它是一个嵌套类,所以它在内部定义
库类的定义如下:
public class Library {
...
private class BookMarkImpl implements BookMark {
...
}
}
注意这是一个私有类,即Library类之外没有人
对这门课一无所知。 仅BookMark界面是已知的
除天秤座以外的其他所有东西,也就是说,它了解这一类。
另请注意,我没有将其设置为Serializable类,因为如果您进行序列化
这个小类的实例,您可以立即序列化整个库
反对,这不是我想要的。 就像您要的一样
少许香蕉,并附有整个大猩猩。
BookMarkImpl类只有一个私有int成员,段落号p。
这是定义的第一部分:
private class BookMarkImpl implements BookMark {
private int p;
private BookMarkImpl(int p) {
if (p < 0 || p >= paragraphs.length)
throw new IndexOutOfBoundsException(
"paragraph : !(0 <= "+p+" < "+paragraphs.length);
this.p= p;
}
甚至此类的构造方法都是私有的,以确保只有一个库
对象可以直接构造BookMarkImpl。 在上一篇文章中
您看到图书馆可以将书签分发给外界,因此
段落编号可能不正确。 这就是BookMarkImpl类保护的原因
本身会通过抛出IndexOutOfBoundsException来避免此类错误,如果
参数不代表有效的段落编号。
BookMarkImpl实现了一种方便使用的便捷方法:
private Library getLibrary() { return Library.this; }
它将这个小方法用于其equals()方法,如下所示:
public boolean equals(Object obj) {
if (obj == null || !(obj instanceof BookMarkImpl)) return false;
BookMarkImpl that= (BookMarkImpl)obj;
return this.getLibrary() == that.getLibrary() &&
this.p == that.p;
}
如果两个BookMarkImpls引用相同的段落,则认为它们相等
存储在同一个库中。
当然,hashCode()方法与equals()方法一起使用。 这很简单:
public int hashCode() { return p; }
它还能返回什么?
这两种小方法使此类非常适合
存储在地图或集中。
给定单个段落编号,BookMarkImpl可以返回绝对
组,书籍,章节,当然还有段落编号本身。 这是怎么
完成了:
public int getGroupNumber() {
int c= Library.this.getIndex(chapters, p);
int b= Library.this.getIndex(books, c);
return Library.this.getIndex(groups, b);
}
public int getBookNumber() {
int c= Library.this.getIndex(chapters, p);
return Library.this.getIndex(books, c);
}
public int getChapterNumber() {
return Library.this.getIndex(chapters, p);
}
public int getParagraphNumber() {
return p;
}
注意大量使用了在库中定义的getIndex()方法
本身。 我们在上一篇文章中看到了它的定义。 不仅可以
BookMarkImpl返回绝对数字,也可以返回相对
索引号,即相对于该组的书号
段落是“成员”等。方法如下:
public int getRelativeBook() {
int b= getBookNumber();
return b-groups[getGroupNumber()].getIndex();
}
public int getRelativeChapter() {
int c= getChapterNumber();
return c-books[getBookNumber()].getIndex();
}
public int getRelativeParagraph() {
return p-chapters[Library.this.getIndex(chapters, p)].getIndex();
}
当然没有getRelativeGroup()方法,因为组是顶层
图书馆的组织结构,它们被简单地编号为0、1、2 ...等。
再次观察getIndex()方法的使用。
BookMarkImpl还可以返回属于其段落号的文本;
不仅是段落本身的文字,还包括章节,书本和
该段所属的组:
public String getGroup() {
return groups[getGroupNumber()].getName();
}
public String getBook() {
return books[getBookNumber()].getName();
}
public String getChapter() {
return chapters[getChapterNumber()].getName();
}
public String getParagraph() {
return Library.this.decompress(paragraphs[p]);
}
请注意,如何使用Library类中定义的decompress()方法来
产生段落的实际文本。 这些方法使用以前的
给定定义的方法来检索正确的绝对数
单段编号。
一个库支持属于段落的“符号”。 用户自由
添加,更改或删除自己想要的任何符号。 这就是BookMarkImpl的方式
提供所需的功能:
public void putNote(String note) { notesMap.put(p, note); }
public String getNote() { return notesMap.get(p); }
它只是从封装的Library对象中检索notesMap,然后
返回或设置属于书签的适当标记
段。
最后,BookMarkImpl实现了toString()方法:
public String toString() {
return getGroup()+sep+
getBook()+sep+
getChapter()+sep+
getRelativeParagraph()+sep+
getParagraph();
}
此方法使用以前的方法来检索属于的所有文本
它代表的段落。 'sep'变量是在
库类本身,是在组,书籍,
章和段落文本。 这是在Library类中完成的方法:
private static final String SEP= "\t";
...
private String sep= SEP;
...
public void setSeparator(String sep) { this.sep= sep; }
public String getSeparator() { return sep; }
这就是全部的Java 101:如您所见,有一个默认的分隔符SEP,
用户可以获取并设置由toString()方法使用的分隔符
BookMarkImpl对象。 BookMarkImpl定义了BookMark的所有方法
界面,这是用户对该嵌套类的全部了解:它实现了
此界面。
结束语在本文的一部分中,我们已经看到了BookMark接口的实现。
书签还将用于本文的下一部分:查询。
Query实现了这个小项目的有趣部分,即它使我们能够
使用正则表达式以一种非常灵活的方式查询整个文本,然后
多很多。
我希望下周再见,
亲切的问候,
乔斯
From: https://bytes.com/topic/java/insights/688224-text-retrieval-systems-5-bookmark-implementation