从文本文件创建的字典 - contains() 总是 returns false

Dictionary Created from text file - contains() always returns false

我目前正忙于一项小型大学作业,我在使用我实现的字典 class 的 contains() 方法时遇到了一些问题 - 该方法总是 returns 错误。 class 看起来像这样:

public class LocalDictionary {
    private ArrayList<String> wordsSet;

    public LocalDictionary() throws IOException {
        String wordListContents = new String(Files.readAllBytes(Paths.get("words.txt")));

        wordsSet = new ArrayList<>();
        String[] words = wordListContents.split("\n");
        for (int i = 0; i < words.length; i++) {
            wordsSet.add(words[i].toLowerCase());
        }
    }

    public boolean contains(String word) {
        return wordsSet.contains(word.toLowerCase());
    }
}

字典从中获取单词的 "words.txt" 文件可在 https://raw.githubusercontent.com/dwyl/english-words/master/words_alpha.txt 获得,但这里是它的外观片段:

zinked
zinkenite
zinky
zinkiferous
zinkify
zinkified
zinkifies
zinkifying
zinnia
zinnias
zinnwaldite
zinober
zinsang
zinzar
zinziberaceae

我已确定 "words.txt" 中的单词包含在 'wordsSet' 中,但无法弄清楚为什么 contains 方法 returns 对于似乎在 ArrayList 中的单词为 false。

非常感谢任何帮助。

Trim for 循环中的每一行,然后再添加它。该行中的每个单词之后似乎都有一些额外的 space 。

for (int i = 0; i < words.length; i++) {
    wordsSet.add(words[i].toLowerCase());
}

for (int i = 0; i < words.length; i++) {
    wordsSet.add(words[i].trim().toLowerCase());
}

这可以使用 wordsSet.get(1).length() 进行验证。根据您的文件,第一行是 'aa',但这会打印 3 而不是 2,这是因为每个单词后面都有一个额外的 space,需要在添加到列表之前对其进行修剪。

您的 contains() 方法没有问题。

尝试 BufferedReader,我尝试并为我工作(我删除了一些无用的行)。在您的使用中,您正在从文件中读取所有字节,将会有额外的字节。

public class LocalDictionary {
    private ArrayList<String> wordsSet = new ArrayList<>();

    public LocalDictionary() throws Exception {

        //dont forget to absolute path to here. click righ click to file and copy path
        File file = new File("C:\Users\higuys\IdeaProjects\try\src\words.txt");
        BufferedReader br = new BufferedReader(new FileReader(file));

        String line;
        while ((line = br.readLine()) != null)
            //trim and tolowercase and add to list.
            wordsSet.add(line.trim().toLowerCase());

    }

    public boolean contains(String word) {
        return wordsSet.contains(word.toLowerCase());
    }
}

您的问题看起来是 OS 相关的分线器处理不当,在这里,

String[] words = wordListContents.split("\n");

在字典的字符串中留下额外的字符。并非所有 OS 都使用“\n”来分隔行,因此您应该编写代码来考虑到这一点。

一个选项是让Java告诉你使用什么行分隔符,然后使用它:

String lineSeparator = System.getProperty("line.separator");
String[] words = wordListContents.split(lineSeparator);

虽然在我看来最简单的是使用文件来获取所有行,例如:

private List<String> wordsSet1;
private ArrayList<String> wordsSet2;

public TestDictionary(String path) throws IOException {
    // my code:
    wordsSet1 = Files.readAllLines(Paths.get(path));

通过使用文件 readAllLines,您让 Java select 正确的分行器。

将你的代码与我的进行比较:

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

import save.MyColorFoo;

public class TestDictionary {
    // public static final String TXT_PATH = "src/pkg1/words.txt";
    // TODO: change this to your correct path
    public static final String TXT_PATH = "words.txt";
    private List<String> wordsSet1;
    private ArrayList<String> wordsSet2;

    public TestDictionary(String path) throws IOException {
        // my code:
        wordsSet1 = Files.readAllLines(Paths.get(path));

        // his code
        String wordListContents = new String(Files.readAllBytes(Paths.get(path)));

        wordsSet2 = new ArrayList<>();
        String[] words = wordListContents.split("\n");
        for (int i = 0; i < words.length; i++) {
            wordsSet2.add(words[i].toLowerCase());
        }

    }

    public boolean myContains(String word) {
        return wordsSet1.contains(word.toLowerCase());
    }

    public boolean hisContains(String word) {
        return wordsSet2.contains(word.toLowerCase());
    }

    public static void main(String[] args) {
        try {
            TestDictionary testDictionary = new TestDictionary(TXT_PATH);

            String testWord = "zinky";
            System.out.println("My List contains \"zinky\":  " + testDictionary.myContains(testWord));
            System.out.println("His List contains \"zinky\": " + testDictionary.hisContains(testWord));

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

如果您不确定原始文本文件是否全部为小写字母然后需要降低它们,那么您可以使用 Streams 来帮助您:

wordsSet1 = Files.readAllLines(Paths.get(path))
        .stream().map(s -> s.toLowerCase())
        .collect(Collectors.toList());