Penso che sarebbe una completa perdita di tempo utilizzare qualsiasi forma di HashMap
. Sto indovinando che stai calcolando hash multi-byte di vari dati, questi sono già hash
es, non è necessario eseguire altro hashing su di essi.
Anche se non lo si specifica, suppongo che i propri hash siano sequenze byte
. Chiaramente uno trie o uno dawg sarebbe l'ideale per archiviarli.
Suggerirei pertanto di implementare uno trie/dawg
e utilizzarlo per memorizzare tutti gli hash nel primo array. È quindi possibile utilizzare tutta la potenza di calcolo in parallelo per cercare ogni elemento nel secondo array in questo trie
. Non sarebbero richieste serrature.
Aggiunto
Ecco una semplice implementazione Dawg
bussai insieme. Sembra funzionare.
public class Dawg {
// All my children.
Dawg[] children = new Dawg[256];
// Am I a leaf.
boolean isLeaf = false;
// Add a new word.
public void add (byte[] word) {
// Finds its location, growing as necessary.
Dawg loc = find (word, 0, true);
loc.isLeaf = true;
}
// String form.
public void add (String word) {
add(word.getBytes());
}
// Returns true if word is in the dawg.
public boolean contains (byte [] word) {
// Finds its location, no growing allowed.
Dawg d = find (word, 0, false);
return d != null && d.isLeaf;
}
// String form.
public boolean contains (String word) {
return contains(word.getBytes());
}
// Find the Dawg - growing the tree as necessary if requested.
private Dawg find (byte [] word, int i, boolean grow) {
Dawg child = children[word[i]];
if (child == null) {
// Not present!
if (grow) {
// Grow the tree.
child = new Dawg();
children[word[i]] = child;
}
}
// Found it?
if (child != null) {
// More to find?
if (i < word.length - 1) {
child = child.find(word, i+1, grow);
}
}
return child;
}
public static void main (String[] args) {
Dawg d = new Dawg();
d.add("H");
d.add("Hello");
d.add("World");
d.add("Hell");
System.out.println("Hello is "+(d.contains("Hello")?"in":"out"));
System.out.println("World is "+(d.contains("World")?"in":"out"));
System.out.println("Hell is "+(d.contains("Hell")?"in":"out"));
System.out.println("Hal is "+(d.contains("Hal")?"in":"out"));
System.out.println("Hel is "+(d.contains("Hel")?"in":"out"));
System.out.println("H is "+(d.contains("H")?"in":"out"));
}
}
Aggiunto
Questo potrebbe essere un buon punto di partenza in una versione senza blocchi concorrente. Queste cose sono notoriamente difficili da testare quindi non posso garantire che funzionerà, ma a mio avviso certamente dovrebbe.
import java.util.concurrent.atomic.AtomicReferenceArray;
public class LFDawg {
// All my children.
AtomicReferenceArray<LFDawg> children = new AtomicReferenceArray<LFDawg> (256);
// Am I a leaf.
boolean isLeaf = false;
// Add a new word.
public void add (byte[] word) {
// Finds its location, growing as necessary.
LFDawg loc = find(word, 0, true);
loc.isLeaf = true;
}
// String form.
public void add (String word) {
add(word.getBytes());
}
// Returns true if word is in the dawg.
public boolean contains (byte[] word) {
// Finds its location, no growing allowed.
LFDawg d = find(word, 0, false);
return d != null && d.isLeaf;
}
// String form.
public boolean contains (String word) {
return contains(word.getBytes());
}
// Find the Dawg - growing the tree as necessary if requested.
private LFDawg find (byte[] word, int i, boolean grow) {
LFDawg child = children.get(word[i]);
if (child == null) {
// Not present!
if (grow) {
// Grow the tree.
child = new LFDawg();
if (!children.compareAndSet(word[i], null, child)) {
// Someone else got there before me. Get the one they set.
child = children.get(word[i]);
}
}
}
// Found it?
if (child != null) {
// More to find?
if (i < word.length - 1) {
child = child.find(word, i + 1, grow);
}
}
return child;
}
public static void main (String[] args) {
LFDawg d = new LFDawg();
d.add("H");
d.add("Hello");
d.add("World");
d.add("Hell");
System.out.println("Hello is " + (d.contains("Hello") ? "in" : "out"));
System.out.println("World is " + (d.contains("World") ? "in" : "out"));
System.out.println("Hell is " + (d.contains("Hell") ? "in" : "out"));
System.out.println("Hal is " + (d.contains("Hal") ? "in" : "out"));
System.out.println("Hel is " + (d.contains("Hel") ? "in" : "out"));
System.out.println("H is " + (d.contains("H") ? "in" : "out"));
}
}
Gli array sono già ordinati? In tal caso, una funzione di fusione dell'unione unica troverà i duplicati. Altrimenti potresti ordinare array1 e array2 in parallelo e fare unire i risultati. – Ingo
Con gli hash del byte vuoi dire che tutti gli hash sono nell'intervallo 0-255? – Tudor
Intendevo le sequenze di byte, ad esempio 'byte []'. Sono il risultato di una funzione hash come SHA o MD5. No, gli array non sono ordinati. Ordinare e unirle richiede O (n log n) per l'ordinamento e O (n + m) per l'unione. Speravo in una maggiore efficienza. –