一个文件中两个单词的概率分布使用java8
The probability distribution of two words in a file using java 8
我需要包含两个单词的行数。为此,我编写了以下代码:
输入文件包含1000 lines
和大约4,000 words
,大约需要4个小时。
Java
中是否有可以更快地完成此操作的库?
我可以使用 Appache Lucene
或 Stanford Core NLP
来实现此代码以减少 运行 时间吗?
ArrayList<String> reviews = new ArrayList<String>();
ArrayList<String> terms = new ArrayList<String>();
Map<String,Double> pij = new HashMap<String,Double>();
BufferedReader br = null;
FileReader fr = null;
try
{
fr = new FileReader("src/reviews-preprocessing.txt");
br = new BufferedReader(fr);
String line;
while ((line= br.readLine()) != null)
{
for(String term : line.split(" "))
{
if(!terms.contains(term))
terms.add(term);
}
reviews.add(line);
}
}
catch (IOException e) { e.printStackTrace();}
finally
{
try
{
if (br != null)
br.close();
if (fr != null)
fr.close();
}
catch (IOException ex) { ex.printStackTrace();}
}
long Count = reviews.size();
for(String term_i : terms)
{
for(String term_j : terms)
{
if(!term_i.equals(term_j))
{
double p = (double) reviews.parallelStream().filter(s -> s.contains(term_i) && s.contains(term_j)).count();
String key = String.format("%s_%s", term_i,term_j);
pij.put(key, p/Count);
}
}
}
你第一个获取不同单词的循环依赖于 ArrayList.contains
,它具有线性时间复杂度,而不是使用 Set
。因此,如果我们假设 nd 个不同的词,它的时间复杂度已经是“行数”×nd.
然后,您正在创建 nd×nd 单词组合,并检查所有 1,000 行是否存在这些组合。换句话说,如果我们只假设有 100 个不同的词,那么您将执行 1,000×100 + 100×100×1,000 = 10,100,000 次操作,如果我们假设有 500 个不同的词,我们已经在谈论 250,500,000 次了。
相反,您应该只创建一行中实际存在的组合并将它们收集到地图中。这将只处理那些实际存在的组合,你可以通过只检查每个“a_b”/“b_a”组合中的任何一个来改进它,因为两者的概率是相同的。然后,你只执行“行数”ד每行字数”ד每行字数” 操作,换句话说,在您的案例中大约有 16,000 次操作。
下面的方法将一行中的所有单词组合在一起,只保留“a_b”/“b_a”组合中的一个,并消除重复,因此每个组合都可以算作一行。
static Stream<String> allCombinations(String line) {
String[] words = line.split(" ");
return Arrays.stream(words)
.flatMap(word1 ->
Arrays.stream(words)
.filter(words2 -> word1.compareTo(words2)<0)
.map(word2 -> word1+'_'+word2))
.distinct();
}
这个方法可以用
List<String> lines = Files.readAllLines(Paths.get("src/reviews-preprocessing.txt"));
double ratio = 1.0/lines.size();
Map<String, Double> pij = lines.stream()
.flatMap(line -> allCombinations(line))
.collect(Collectors.groupingBy(Function.identity(),
Collectors.summingDouble(x->ratio)));
它 运行 在几秒钟内通过我的“War and Peace”副本,不需要任何并行处理尝试。不出意外,“and_the”是概率最高的组合。
你可以考虑换行
String[] words = line.split(" ");
至
String[] words = line.toLowerCase().split("\W+");
概括代码以处理不同的输入,处理多个空格或其他标点字符并忽略大小写。
我需要包含两个单词的行数。为此,我编写了以下代码:
输入文件包含1000 lines
和大约4,000 words
,大约需要4个小时。
Java
中是否有可以更快地完成此操作的库?
我可以使用 Appache Lucene
或 Stanford Core NLP
来实现此代码以减少 运行 时间吗?
ArrayList<String> reviews = new ArrayList<String>();
ArrayList<String> terms = new ArrayList<String>();
Map<String,Double> pij = new HashMap<String,Double>();
BufferedReader br = null;
FileReader fr = null;
try
{
fr = new FileReader("src/reviews-preprocessing.txt");
br = new BufferedReader(fr);
String line;
while ((line= br.readLine()) != null)
{
for(String term : line.split(" "))
{
if(!terms.contains(term))
terms.add(term);
}
reviews.add(line);
}
}
catch (IOException e) { e.printStackTrace();}
finally
{
try
{
if (br != null)
br.close();
if (fr != null)
fr.close();
}
catch (IOException ex) { ex.printStackTrace();}
}
long Count = reviews.size();
for(String term_i : terms)
{
for(String term_j : terms)
{
if(!term_i.equals(term_j))
{
double p = (double) reviews.parallelStream().filter(s -> s.contains(term_i) && s.contains(term_j)).count();
String key = String.format("%s_%s", term_i,term_j);
pij.put(key, p/Count);
}
}
}
你第一个获取不同单词的循环依赖于 ArrayList.contains
,它具有线性时间复杂度,而不是使用 Set
。因此,如果我们假设 nd 个不同的词,它的时间复杂度已经是“行数”×nd.
然后,您正在创建 nd×nd 单词组合,并检查所有 1,000 行是否存在这些组合。换句话说,如果我们只假设有 100 个不同的词,那么您将执行 1,000×100 + 100×100×1,000 = 10,100,000 次操作,如果我们假设有 500 个不同的词,我们已经在谈论 250,500,000 次了。
相反,您应该只创建一行中实际存在的组合并将它们收集到地图中。这将只处理那些实际存在的组合,你可以通过只检查每个“a_b”/“b_a”组合中的任何一个来改进它,因为两者的概率是相同的。然后,你只执行“行数”ד每行字数”ד每行字数” 操作,换句话说,在您的案例中大约有 16,000 次操作。
下面的方法将一行中的所有单词组合在一起,只保留“a_b”/“b_a”组合中的一个,并消除重复,因此每个组合都可以算作一行。
static Stream<String> allCombinations(String line) {
String[] words = line.split(" ");
return Arrays.stream(words)
.flatMap(word1 ->
Arrays.stream(words)
.filter(words2 -> word1.compareTo(words2)<0)
.map(word2 -> word1+'_'+word2))
.distinct();
}
这个方法可以用
List<String> lines = Files.readAllLines(Paths.get("src/reviews-preprocessing.txt"));
double ratio = 1.0/lines.size();
Map<String, Double> pij = lines.stream()
.flatMap(line -> allCombinations(line))
.collect(Collectors.groupingBy(Function.identity(),
Collectors.summingDouble(x->ratio)));
它 运行 在几秒钟内通过我的“War and Peace”副本,不需要任何并行处理尝试。不出意外,“and_the”是概率最高的组合。
你可以考虑换行
String[] words = line.split(" ");
至
String[] words = line.toLowerCase().split("\W+");
概括代码以处理不同的输入,处理多个空格或其他标点字符并忽略大小写。