Java: Optimieren Sie das Hashset für die Erkennung von Duplikaten in großem Maßstab

Ich arbeite an einem Projekt, in dem ich viele Tweets bearbeite. Das Ziel ist es, Duplikate zu entfernen, während ich sie verarbeite. Ich habe die Tweet-IDs, die als Zeichenfolgen des Formats eingehen"166471306949304320"

Ich habe eine verwendetHashSet<String> dafür, was für eine Weile gut funktioniert. Aber als ich ungefähr 10 Millionen Artikel erhalte, bin ich stark festgefahren und bekomme irgendwann einen GC-Fehler, vermutlich durch das Aufwärmen. Ich habe versucht, eine bessere Größe / Ladung mit zu definieren

tweetids = new HashSet<String>(220000,0.80F);

und das lässt es ein bisschen weiter kommen, ist aber immer noch unerträglich langsam (um etwa 10 Millionen dauert die Verarbeitung dreimal so lange). Wie kann ich das optimieren? Angesichts der Tatsache, dass ich eine ungefähre Vorstellung davon habe, wie viele Elemente sich am Ende im Set befinden sollten (in diesem Fall etwa 20 bis 22 Millionen), sollte ich ein HashSet erstellen, das nur zwei- oder dreimal nachgearbeitet wird, oder würde der Overhead für ein solches zu viele Zeitstrafen gesetzt? Funktionieren die Dinge besser, wenn ich keinen String verwende oder wenn ich eine andere HashCode-Funktion definiere (bei einer bestimmten Instanz eines Strings bin ich mir nicht sicher, wie ich vorgehen soll)? Dieser Teil des Implementierungscodes ist unten.

tweetids = new HashSet<String>(220000,0.80F); // in constructor
duplicates = 0;
...
// In loop: For(each tweet)
String twid = (String) tweet_twitter_data.get("id");
// Check that we have not processed this tweet already
if (!(tweetids.add(twid))){
    duplicates++;
    continue; 
}

LÖSUNG

Dank Ihrer Empfehlungen habe ich es gelöst. Das Problem war die Speichermenge, die für die Hash-Darstellungen benötigt wurde. zuerst,HashSet<String> war einfach riesig und unangebracht, weil dieString.hashCode() ist exorbitant für diese Skala. Als nächstes habe ich einen Trie ausprobiert, der jedoch bei etwas mehr als 1 Million Einträgen abstürzte. Die Neuzuordnung der Arrays war problematisch. Ich habe aHashSet<Long> zur besseren Wirkung und fast geschafft, aber die Geschwindigkeit sank und es stürzte schließlich auf der letzten Etappe der Verarbeitung (rund 19 Millionen). Die Lösung bestand darin, die Standardbibliothek zu verlassen und zu verwendenSchatz. Es beendete 22 Millionen Datensätze ein paar Minuten schneller, als Duplikate überhaupt nicht zu überprüfen. Die endgültige Implementierung war einfach und sah folgendermaßen aus:

import gnu.trove.set.hash.TLongHashSet;
...
    TLongHashSet tweetids; // class variable
... 
    tweetids = new TLongHashSet(23000000,0.80F); // in constructor
...
    // inside for(each record)
    String twid = (String) tweet_twitter_data.get("id");
    if (!(tweetids.add(Long.parseLong(twid)))) {
        duplicates++;
        continue; 
    }

Antworten auf die Frage(3)

Ihre Antwort auf die Frage