java - java中有效过滤字符串

标签 java string eclipse indexing hashmap

我现在正在尝试制作类似迷你搜索引擎的东西。我的目标是在 HashMap 中索引一堆文件,但首先我需要执行一些操作,其中包括降低大写字母、删除所有不必要的单词以及删除除 a-z/A-Z 之外的所有字符。现在我的实现如下所示:

String article = "";

for (File file : dir.listFiles()) { //for each file (001.txt, 002.txt...)
        Scanner s = null;
        try {
            s = new Scanner(file);
            while (s.hasNext())
                article += s.next().toLowerCase(Locale.ROOT) + " "; //converting all characters to lower case
            article = currentWord.replaceAll(delimiters.get()," "); //removing punctuations (?, -, !, * etc...) 

            String splittedWords = article.split(" ");  //splitting each word into a string array
            for(int i = 0; i < splittedWords.length; i++) {
                s = new Scanner(stopwords);
                boolean flag = true;
                while(s.hasNextLine())
                    if (splittedWords[i].equals(s.nextLine())) { //comparing each word with all the stop words (words like a, the, already, these etc...) taken from another big txt file and removing them, because we dont need to fill our map with unnecessary words, to provide faster search times later on
                        flag = false;
                        break;
                    }
                if(flag) map.put(splittedWords[i], file.getName()); //if current word in splittedWords array does not match any stop word, put it in the hashmap        


            }
            s.close();


        } catch (FileNotFoundException e) {

            e.printStackTrace();
        }
        s.close();
        System.out.println(file);
    }

这只是我的代码中的一个 block ,它可能包含缺失的部分,我用注释粗略地解释了我的算法。使用 .contains 方法检查 stopWords 是否包含任何当前单词,尽管它是一种更快的方法,但它不会映射像“death”这样的单词,因为它包含停用词列表中的“at”。 我正在尽我最大的努力让它更有效,但我还没有取得多大进展。每个文件包含大约。每个大约 300 个单词需要大约 3 秒的时间来索引,考虑到我有一万个文件,这并不理想。关于如何改进我的算法以使其运行得更快有什么想法吗?

最佳答案

有一些改进:

首先,请不要使用new Scanner(File) 构造函数,因为它使用无缓冲 I/O。小磁盘读取操作尤其是 HDD 上的读取操作非常低效。例如,使用具有 65 KB 缓冲区的 BufferedInputStream:

try (Scanner s = new Scanner(new BufferedInputStream(new FileInputStream(f), 65536))) {
    // your code
}

第二:您的 PC 很可能具有多代码 CPU。因此您可以并行扫描多个文件。 为此,您必须确保使用多线程感知的map。将 map 的定义更改为:

Map<String,String> map = new ConcurrentHashMap<>();

然后您可以使用以下代码:

Files.list(dir.toPath()).parallel().forEach(f -> {
    try (Scanner s = new Scanner(new BufferedInputStream(Files.newInputStream(f), 65536))) {
        // your code
    } catch (IOException e) {
        e.printStackTrace();
    }
});

根据系统中的 CPU 核心,它将同时处理多个文件。特别是如果您处理大量文件,这将大大减少程序的运行时间。

最后你的实现相当复杂。您使用 Scanner 的输出创建一个新的字符串,然后再次拆分该字符串。相反,最好将 Scanner 配置为直接考虑您想要的分隔符:

try (Scanner s = new Scanner(....).useDelimiter("[ ,\\!\\-\\.\\?\\*]")) {

然后您可以直接使用 Scanner 创建的 token ,而不必构建 article 字符串并随后将其拆分。

关于java - java中有效过滤字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58788101/

相关文章:

java - 循环屏障无法实现同步

c# - 如何将 string.join 添加到 foreach 循环

android - 与proguard混淆

eclipse - 修订的键盘快捷方式 > 在 Eclipse 中 stash 修订信息

java - 有谁知道一个代表所有Java包的图表

java - 需要帮助创建一个程序来找到最轻和最重的狗

c# - 如何用字符串替换 TextBox 中的选定文本?

java - Maven:如何添加修补的依赖项

java - 为什么我的文本区域没有更新?

c++ - 当我的 std::string 调整大小时,字符缓冲区会发生什么?