Java 计算文件中出现的任意数量的字符数?

Java 计算文件中出现的任意数量的字符数?,java,Java,我找到了几种方法来计算Java文件中单个字符的出现次数。我的问题很简单:是否有任何方法可以同时计算文件中列表中任何字符的出现次数,或者我必须循环遍历每个字符 澄清一下,我想要的东西相当于: 对于文件中的每个字符,如果列表“abcdefg”中的字符增加1 背景: 我在计算一个文件中的谓词,我能想到的最好的方法是搜索,==,等等的出现情况。我相信java列表接口有一个Contains()方法,因此可以执行以下操作 if(someList.Contains('<')) { x++ }

我找到了几种方法来计算Java文件中单个字符的出现次数。我的问题很简单:是否有任何方法可以同时计算文件中列表中任何字符的出现次数,或者我必须循环遍历每个字符

澄清一下,我想要的东西相当于: 对于文件中的每个字符,如果列表“abcdefg”中的字符增加1

背景:
我在计算一个文件中的谓词,我能想到的最好的方法是搜索,==,等等的出现情况。

我相信java列表接口有一个
Contains()
方法,因此可以执行以下操作

if(someList.Contains('<'))
{
    x++
}
if(someList.Contains)(“使用
映射
并遍历文件。对于您测试的每个字符,查看它是否在映射中。如果不是,则使用值1添加它,否则获取当前值,增加它并将其放回。同时测试
树映射
哈希映射
,以查看哪个最适合您。现在您有了完整的直方图,可以轻松地加上有趣的总数

更新:看到您对查找序列感兴趣。如果您想以良好的性能完成这项工作,我将使用类似于lex的工具,但用于Java。快速的google让我想到了这一点:定义您感兴趣的标记应该是直截了当的,然后计算它们应该非常简单

更新2:我忍不住玩它。下面是一个使用上述工具似乎有效的示例(免责声明:我没有使用该工具,因此这可能是完全错误的…):

导入java.lang.System;
导入java.util.Map;
导入java.util.TreeMap;
类样本{
publicstaticvoidmain(字符串argv[])抛出java.io.IOException{
Map Map=newtreemap();
Yylex yy=新的Yylex(System.in);
YYT;
而((t=yy.yylex())!=null){
字符串文本=t.mText;
如果(!text.isEmpty()){
整数i=map.get(文本);
如果(i==null){
地图放置(文本,1);
}
否则{
map.put(text,map.get(text)+1);
}
}
} 
系统输出打印项次(map);
}
}
YY类令牌{
公共字符串多行文字;
Yytoken(字符串文本){
多行文字=文本;
}
公共字符串toString(){
return“Token:+mText;
}
}
%%
其他=(.|[\r\n])
%% 
“,”{return(new Yytoken(yytext());}
“:”{return(newyytoken(yytext());}
“;”{return(新的Yytoken(yytext());}
({return(newyytoken(yytext());}
“{return(new Yytoken(yytext());}”
“[”{return(newyytoken(yytext());}
“]”{return(新的Yytoken(yytext());}
{{return(新的Yytoken(yytext());}
“}”{return(新的Yytoken(yytext());}
“{return(new Yytoken(yytext());}
“+”{return(newyytoken(yytext());}
“-”{return(newyytoken(yytext());}
“*”{return(newyytoken(yytext());}
“/”{return(新的Yytoken(yytext());}
“=”{return(new Yytoken(yytext());}
“{return(new Yytoken(yytext());}
“{return(new Yytoken(yytext());}
“>=”{return(new Yytoken(yytext());}
“&”{return(newyytoken(yytext());}
“|”{return(新的Yytoken(yytext());}
“:=”{return(new Yytoken(yytext());}
“#”{return(新的Yytoken(yytext());}
{OTHER}{return(new Yytoken(“”);}
到“
同时统计文件中列表中任何字符的出现次数”
”:

  • 您可以使用哈希表,其中键是字符,值是您看到该字符的次数
  • 每次读取字符时,检查它是否在哈希表中:
    • 如果是,则将其值增加1
    • 如果不是,则将键、值对添加到哈希表中,值初始化为1

如果您关心的字符集很小(例如示例中的
“abcdefg”
,==”
),一个switch语句就足够了,而不是使用哈希表来解决问题一个简单的方法是使用数组:

final int[] occurs = new int[65536];
for (char c : file) occurs[c]++;
如果您知道不会遇到太多奇异的字符,可以减小阵列的大小。

  • 阅读
由于要计算多于1个字符(=,!=,=)的谓词,因此需要一个字符,以便查看下一个字符以确定实际谓词

  • 发生频率
如果你能负担得起额外的依赖项,那么我的建议是使用它来计算频率。如果你不能,那么你可以使用映射或基于数组的计数器(如果你的谓词集是有限的,我更喜欢这样,因为这样可以简化代码)

  • 并行化
使用上述方法更简单,因为您可以在一次传递中获得频率。如果您的文件很大,或者需要计算多个文件中的频率,那么您可以选择使用java执行器将其并行化。

如果我理解正确,您希望不仅查找单个字符的出现次数,而且查找短字符序列(即字符串)的出现次数,例如
=
。在这种情况下,
映射
不够,您需要
映射
来存储每个字符串的计数

您也可以使用a,它基本上是一个很好的接口,用于知道它包含重复(相同)元素多少次的集合

我相信谓词/运算符/任何要计数的短字符串的数量都已定义,您可以定义一个数组/一个列表来存储您感兴趣的所有谓词,例如:

List<String> operators = Arrays.asList("==", "<=", ">=", "<", ">");
然后以与此类似的方式使用此方法:

Scanner scanner = new Scanner(new File("input.txt"));
while (scanner.hasNextLine()) {
    String line = scanner.nextLine();
    for (String operator : operators) {
        int oldOccurences = counts.get(operator);
        counts.put(operator, oldOccurences + occurrences(line, operator));
    }
}

您至少可以使用
树集
而不是列表来提高性能。因此,将字符列表添加到一个集合中(甚至可以测试
哈希集
),然后针对文件中的每个字符查看它是否存在于集合中。这将大大提高性能
Map<String, Integer> counts = new HashMap<>();
for (String operator : operators)
    counts.put(operator, 0);
static int occurrences(String source, String subString) {
    int count = 0;
    int index = source.indexOf(subString);

    while (index != -1) {
        count++;
        index = source.indexOf(subString, index + 1);
    }
    return count;
}
Scanner scanner = new Scanner(new File("input.txt"));
while (scanner.hasNextLine()) {
    String line = scanner.nextLine();
    for (String operator : operators) {
        int oldOccurences = counts.get(operator);
        counts.put(operator, oldOccurences + occurrences(line, operator));
    }
}