ハードドライブからそれぞれ〜10,000行の〜1000ファイルを読み取る基本的な方法があります。また、ユーザーのすべての「説明語」を含む call の配列がString
あります。に対応するuserDescription
データ構造を持つ HashMap を作成しました。HashMap<String, HashMap<String, Integer>>
HashMap<eachUserDescriptionWords, HashMap<TweetWord, Tweet_Word_Frequency>>
ファイルは次のように編成されています。
<User=A>\t<Tweet="tweet...">\n
<User=A>\t<Tweet="tweet2...">\n
<User=B>\t<Tweet="tweet3...">\n
....
これを行う私の方法は次のとおりです。
for (File file : tweetList) {
if (file.getName().endsWith(".txt")) {
System.out.println(file.getName());
BufferedReader in;
try {
in = new BufferedReader(new FileReader(file));
String str;
while ((str = in.readLine()) != null) {
// String split[] = str.split("\t");
String split[] = ptnTab.split(str);
String user = ptnEquals.split(split[1])[1];
String tweet = ptnEquals.split(split[2])[1];
// String user = split[1].split("=")[1];
// String tweet = split[2].split("=")[1];
if (tweet.length() == 0)
continue;
if (!prevUser.equals(user)) {
description = userDescription.get(user);
if (description == null)
continue;
if (prevUser.length() > 0 && wordsCount.size() > 0) {
for (String profileWord : description) {
if (wordsCorr.containsKey(profileWord)) {
HashMap<String, Integer> temp = wordsCorr
.get(profileWord);
wordsCorr.put(profileWord,
addValues(wordsCount, temp));
} else {
wordsCorr.put(profileWord, wordsCount);
}
}
}
// wordsCount = new HashMap<String, Integer>();
wordsCount.clear();
}
setTweetWordCount(wordsCount, tweet);
prevUser = user;
}
} catch (IOException e) {
System.err.println("Something went wrong: "
+ e.getMessage());
}
}
}
ここでは、このメソッドsetTweetWord
は、1 人のユーザーのすべてのツイートの単語頻度をカウントします。メソッドは次のとおりです。
private void setTweetWordCount(HashMap<String, Integer> wordsCount,
String tweet) {
ArrayList<String> currTweet = new ArrayList<String>(
Arrays.asList(removeUnwantedStrings(tweet)));
if (currTweet.size() == 0)
return;
for (String word : currTweet) {
try {
if (word.equals("") || word.equals(null))
continue;
} catch (NullPointerException e) {
continue;
}
Integer countWord = wordsCount.get(word);
wordsCount.put(word, (countWord == null) ? 1 : countWord + 1);
}
}
wordCount
メソッド addValuesは、巨大な HashMap wordsCorr に既に存在する単語があるかどうかを確認します。そうであれば、元の HashMap 内の単語の数を増やしwordsCorr
ます。
さて、私の問題は、私が何をしてもプログラムが非常に遅いことです。このバージョンをサーバーで実行しましたが、ハードウェアはかなり優れていましたが、28 時間経過しており、スキャンされたファイルの数はわずか 450 でした。不必要なことを繰り返し行っていないかどうかを確認しようとしましたが、そのうちのいくつかを修正しました。しかし、それでもプログラムは非常に遅いです。
また、ヒープサイズを最大である 1500m に増やしました。
私が間違っているかもしれないことはありますか?
ご協力ありがとうございました!
編集:プロファイリング結果 まず第一に、コメントをくださった皆さんに本当に感謝したいと思います。プログラムの一部を変更しました。直接String.split()
およびその他の最適化の代わりに、正規表現をプリコンパイルしました。ただし、プロファイリング後、私のaddValues
方法は最も時間がかかります。だから、これが私のコードですaddValues
。ここで最適化する必要があるものはありますか? あ、startProcess
やり方も少し変えました。
private HashMap<String, Integer> addValues(
HashMap<String, Integer> wordsCount, HashMap<String, Integer> temp) {
HashMap<String, Integer> merged = new HashMap<String, Integer>();
for (String x : wordsCount.keySet()) {
Integer y = temp.get(x);
if (y == null) {
merged.put(x, wordsCount.get(x));
} else {
merged.put(x, wordsCount.get(x) + y);
}
}
for (String x : temp.keySet()) {
if (merged.get(x) == null) {
merged.put(x, temp.get(x));
}
}
return merged;
}
EDIT2:一生懸命試した後でも、プログラムは期待どおりに動作しませんでした。「遅い方法」の最適化をすべて行いましたが、うまくいきaddValues
ませんでした。そこで、最初に単語辞書を作成し、各単語にインデックスを割り当ててから処理を行うという別のパスに行きました。それがどこに行くのか見てみましょう。ご協力ありがとうございました!