首先我想到了一个类来封装您需要从文本中提取的数据。您需要单个单词,并且对于每个单词,您都需要计算该单词在整个文本中出现的次数以及该单词出现的页面列表。于是我写了如下WordRef类。
import java.util.LinkedList;
import java.util.Objects;
public class WordRef {
/** Number of times 'word' occurs in the text. */
private int occurrences;
/** The actual word. */
private String word;
/** List of page numbers where 'word' appears. */
private LinkedList<Integer> pages;
/**
* Creates and returns instance of this class.
*
* @param word - the actual word.
*/
public WordRef(String word) {
Objects.requireNonNull(word, "null word");
this.word = word;
occurrences = 1;
pages = new LinkedList<Integer>();
}
/** Increment the number of occurrences of 'word'. */
public void addOccurrence() {
occurrences++;
}
/**
* Add 'page' to the list of pages containing 'word'.
*
* @param page - number of page to add.
*/
public void addPage(Integer page) {
if (!pages.contains(page)) {
pages.add(page);
}
}
/**
* @return Number of occurrences of 'word'.
*/
public int getOccurrences() {
return occurrences;
}
/**
* @return The actual 'word'.
*/
public String getWord() {
return word;
}
/**
* Two 'WordRef' instances are equal if they both contain the exact, same word.
*/
public boolean equals(Object obj) {
boolean equal = false;
if (obj != null) {
Class<?> objClass = obj.getClass();
if (objClass.equals(getClass())) {
WordRef other = (WordRef) obj;
String otherWord = other.getWord();
equal = word.equals(otherWord);
}
}
return equal;
}
/**
* Equal 'WordRef' instances should each return the same hash code.
*/
public int hashCode() {
return word.hashCode();
}
/**
* Returns a string representation of this instance.
*/
public String toString() {
return String.format("%s {%d} %s", word, occurrences, pages);
}
}
注意LinkedList 的元素必须是对象,因此使用Integer 而不是int,因为int 是一个原语。另请注意,我们需要确定两个 WordRef 实例是否包含相同的单词。因此类WordRef 包含方法equals() 并且根据类java.lang.Object 的javadoc,如果一个类覆盖了方法equals(),那么它也应该覆盖方法hashCode()。
现在是读取文本并处理它的代码。在您的问题中,您将所有代码放在名为loadBook() 的方法中。但是,为了创建minimal, reproducible example,我编写了一个单独的类,并将文本读取和处理代码放入方法main() 以及一些辅助方法中。这是该类的代码。
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class AliceTxt {
private static final int PAGE = 3;
private static final Pattern REGEX = Pattern.compile("\\b\\w+\\b");
private static LinkedList<WordRef> wordRefs;
private static List<String> getWords(String line) {
if (line == null) {
line = "";
}
Matcher matcher = REGEX.matcher(line);
List<String> words = new ArrayList<>();
while (matcher.find()) {
words.add(matcher.group());
}
return words;
}
private static void updateWordRefs(List<String> words, int page) {
if (words != null) {
for (String word : words) {
WordRef wordRef = new WordRef(word);
int index = wordRefs.indexOf(wordRef);
if (index < 0) {
wordRefs.add(wordRef);
}
else {
wordRef = wordRefs.get(index);
wordRef.addOccurrence();
}
wordRef.addPage(Integer.valueOf(page));
}
}
}
public static void main(String[] args) {
Path path1 = Paths.get("alice.txt");
try (BufferedReader reader = Files.newBufferedReader(path1, Charset.defaultCharset())) {
wordRefs = new LinkedList<>();
String line = reader.readLine();
int countLines = 0;
int page;
while (line != null) {
page = (countLines / PAGE) + 1;
if (line.length() > 0) {
// Don't count empty lines.
countLines++;
}
List<String> words = getWords(line);
updateWordRefs(words, page);
line = reader.readLine();
}
wordRefs.forEach(System.out::println);
}
catch (IOException xIo) {
xIo.printStackTrace();
}
}
}
上面的类使用另一个LinkedList 将文本中所有不同的单词保存为单独的WordRef 对象。请注意,在上面的代码中,单词是区分大小写的,这意味着 So 和 so 被视为单独的单词。如果您希望单词不区分大小写,即 So 和 so 应被视为同一个单词,请使用 java.util.regex.Pattern
类中的以下方法
private static final Pattern REGEX = Pattern.compile("\\b\\w+\\b", Pattern.CASE_INSENSITIVE);
以下是根据我的comment to your question 中的描述运行上述代码的输出,说明您希望输出如何显示以及您确认是正确的描述。
下面的每一行都以实际单词开头,然后是出现次数,然后是该单词在文本中出现的页码列表。参考类WordRef中的方法toString()。
Alice {3} [1, 3]
was {4} [1, 2, 3]
beginning {1} [1]
to {4} [1, 3]
get {1} [1]
very {2} [1, 2]
tired {1} [1]
of {6} [1, 2, 3]
sitting {1} [1]
by {2} [1, 2]
her {5} [1, 2]
sister {2} [1]
on {1} [1]
the {9} [1, 2, 3]
bank {1} [1]
and {4} [1, 2]
having {1} [1]
nothing {2} [1, 3]
do {1} [1]
once {1} [1]
or {3} [1]
twice {1} [1]
she {3} [1, 2]
had {2} [1]
peeped {1} [1]
into {1} [1]
book {2} [1]
reading {1} [1]
but {1} [1]
it {3} [1, 3]
no {1} [1]
pictures {2} [1]
conversations {2} [1]
in {3} [1, 2, 3]
what {1} [1]
is {1} [1]
use {1} [1]
a {3} [1, 2]
thought {1} [1]
without {1} [1]
So {1} [2]
considering {1} [2]
own {1} [2]
mind {1} [2]
as {2} [2]
well {1} [2]
could {1} [2]
for {1} [2]
hot {1} [2]
day {1} [2]
made {1} [2]
feel {1} [2]
sleepy {1} [2]
stupid {1} [2]
whether {1} [2]
pleasure {1} [2]
making {1} [2]
daisy {1} [2]
chain {1} [2]
would {1} [2]
be {1} [2]
worth {1} [2]
trouble {1} [2]
getting {1} [2]
up {1} [2]
picking {1} [2]
daisies {1} [2]
when {1} [2]
suddenly {1} [2]
White {1} [2]
Rabbit {2} [2, 3]
with {1} [2]
pink {1} [2]
eyes {1} [2]
ran {1} [2]
close {1} [2]
There {1} [3]
so {2} [3]
VERY {2} [3]
remarkable {1} [3]
that {1} [3]
nor {1} [3]
did {1} [3]
think {1} [3]
much {1} [3]
out {1} [3]
way {1} [3]
hear {1} [3]
say {1} [3]
itself {1} [3]
Oh {1} [3]
dear {1} [3]