我想通读一个文本文档,然后仅将唯一单词添加到“ Word”对象的数组列表中。看来我现在拥有的代码根本没有在wordList arraylist中输入任何单词。
public ArrayList<Word> wordList = new ArrayList<Word>();
String fileName, word;
int counter;
Scanner reader = null;
Scanner scanner = new Scanner(System.in);
try {
reader = new Scanner(new FileInputStream(fileName));
}
catch(FileNotFoundException e) {
System.out.println("The file could not be found. The program will now exit.");
System.exit(0);
}
while (reader.hasNext()) {
word = reader.next().toLowerCase();
for (Word value : wordList) {
if(value.getValue().contains(word)) {
Word newWord = new Word(word);
wordList.add(newWord);
}
}
counter++;
}
public class Word {
String value;
int frequency;
public Word(String v) {
value = v;
frequency = 1;
}
public String getValue() {
return value;
}
public String toString() {
return value + " " + frequency;
}
}
答案 0 :(得分:2)
好的,让我们从修复当前代码开始。您遇到的问题是,仅在一个新单词对象已经存在时才将其添加到列表中。相反,当不存在新的Word对象时,您需要添加一个,否则增加频率。这是为此的示例修复程序:
ArrayList<Word> wordList = new ArrayList<Word>();
String fileName, word;
Scanner reader = null;
Scanner scanner = new Scanner(System.in);
try {
reader = new Scanner(new FileInputStream(fileName));
}
catch(FileNotFoundException e) {
System.out.println("The file could not be found. The program will now exit.");
System.exit(0);
}
while (reader.hasNext()) {
word = reader.next().toLowerCase();
boolean wordExists = false;
for (Word value : wordList) {
// We have seen the word before so increase frequency.
if(value.getValue().equals(word)) {
value.frequency++;
wordExists = true;
break;
}
}
// This is the first time we have seen the word!
if (!wordExists) {
Word newValue = new Word(word);
newValue.frequency = 1;
wordList.add(newValue);
}
}
}
但是,这是一个非常糟糕的解决方案(O(n ^ 2)运行时)。相反,我们应该使用称为Map的数据结构,这将使我们的运行时间降低到(O(n))
ArrayList<Word> wordList = new ArrayList<Word>();
String fileName, word;
int counter;
Scanner reader = null;
Scanner scanner = new Scanner(System.in);
try {
reader = new Scanner(new FileInputStream(fileName));
}
catch(FileNotFoundException e) {
System.out.println("The file could not be found. The program will now exit.");
System.exit(0);
}
Map<String, Integer> frequencyMap = new HashMap<String, Integer>();
while (reader.hasNext()) {
word = reader.next().toLowerCase();
// This is equivalent to searching every word in the list via hashing (O(1))
if(!frequencyMap.containsKey(word)) {
frequencyMap.put(word, 1);
} else {
// We have already seen the word, increase frequency.
frequencyMap.put(word, frequencyMap.get(word) + 1);
}
}
// Convert our map of word->frequency to a list of Word objects.
for(Map.Entry<String, Integer> entry : frequencyMap.entrySet()) {
Word word = new Word(entry.getKey());
word.frequency = entry.getValue();
wordList.add(word);
}
}
答案 1 :(得分:0)
您的for-each循环正在wordList
上进行迭代,但这是一个空的ArrayList,因此您的代码将永远不会到达wordList.add(newWord);
行
答案 2 :(得分:0)
我很高兴您可能想批评为什么算法不起作用,或者这是一个更大问题的例子,但是如果您只想计算发生次数,那么可以采用一种更简单的方法
使用Java 8中的流,您可以将其简化为一种方法-在文件中创建Stream
行,将其小写,然后使用Collector
对其进行计数。
public static void main(final String args[]) throws IOException
{
final File file = new File(System.getProperty("user.home") + File.separator + "Desktop" + File.separator + "myFile.txt");
for (final Entry<String, Long> entry : countWordsInFile(file).entrySet())
{
System.out.println(entry);
}
}
public static Map<String, Long> countWordsInFile(final File file) throws IOException
{
return Files.lines(file.toPath()).map(String::toLowerCase).collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
}
到目前为止,我对Streams
并没有做任何事情,因此欢迎任何批评。