2015-05-19 3 views
5

Sto cercando una raccolta per memorizzare la coppia valore chiave, in cui il valore deve essere restituito in base alla condizione chiave startswith.
per es. per la raccolta dati: (a,123) (ab,234) (abcd,5434)coppia di valori-chiave java con ricerca chiavi come "startswith"

Se lo faccio map.get(a) mi dovrebbe dare gamma di {123,234,5434}, allo stesso modo se lo faccio map.get(ab) mi dovrebbe dare {234,5434} ma non {123} in questo caso.

Quindi, cerca tutti i valori che hanno una chiave con corrispondenza esatta o inizia con.
Qualche suggerimento? se c'è qualcosa già disponibile o se posso scrivere qualcosa?
Grazie!

+13

Suona un po 'come un [trie] (http://en.wikipedia.org/wiki/Trie). – Kevin

+1

In particolare, è possibile utilizzare Apache Commons Collections ['Trie'] (https://commons.apache.org/proper/commons-collections/javadocs/api-release/org/apache/commons/collections4/Trie.html) che può fare esattamente quello che vuoi. Hanno un'implementazione ['PatriciaTrie'] (https://commons.apache.org/proper/commons-collections/javadocs/api-release/org/apache/commons/collections4/trie/PatriciaTrie.html) –

risposta

5

È possibile farlo con TreeMap<String,Integer> utilizzando il metodo tailMap, e l'iterazione il risultato, mentre il tasto corrisponda all'ingresso:

TreeMap<String,Integer> map = new TreeMap<String,Integer>(); 
map.put("a", 123); 
map.put("ab", 234); 
map.put("abcd", 5434); 
String myKey = "ab"; 
for (Map.Entry<String,Integer> e : map.tailMap(myKey).entrySet()) { 
    if (!e.getKey().startsWith(myKey)) { 
     break; 
    } 
    System.out.println(e.getValue()); 
} 

Demo.

1

Utilizzare un TreeMap, e creare uno speciale iteratore che mappa sopra la TreeMap e ricerche per il modello di stringa che si sta cercando

+1

ma wouldn ' Questo approccio è una ricerca temporale lineare ... che tipo di sconfigge lo scopo di mantenere le coppie chiave-valore in una mappa? –

+1

ovviamente il tempo di ricerca dipenderà dal numero di elementi che corrispondono alla stringa. Ma usando la struttura TreeMap, puoi eliminare rapidamente molti elementi. Ad esempio, se hai un albero da 1 milione di elementi (anche la distribuzione della prima lettera) se la tua stringa di ricerca inizia con "a", scendi a circa 31250 elementi (su un milione) in soli 5 movimenti di ramo. – ControlAltDel

+0

+1 concordato. Sarà lineare, ma non necessariamente O (keyset.size()). Nella maggior parte dei casi, sarà lineare nella dimensione di un sottoinsieme molto più piccolo. –

1

solo un piccolo tocco sulla soluzione di dasblinkenlight: Java 8 flusso di API fornisce un bel tocco sul loop:

TreeMap<String,Integer> map = new TreeMap<String,Integer>(); 
    map.put("a", 123); 
    map.put("ab", 234); 
    map.put("abcd", 5434); 
    String myKey = "ab"; 

    Collection<Integer> matchValues = map.tailMap(myKey).entrySet() 
     .stream() 
     .filter(e -> e.getKey().startsWith(myKey)) 
     .map(e -> e.getValue()) 
     .collect(Collectors.toList()); 
+0

concordo, naturalmente, non ho abbastanza rep per commentare ... –

+0

è 50. Ero al di sotto di quel numero al momento. –

0

seguito il commento di Slanec, ho guardato PatriciaTrie da Apache Commons Collections4 e lo fa davvero un metodo che fa esattamente quello OP chiedeva:

import org.apache.commons.collections4.*; 
import org.apache.commons.collections4.trie.*; 

Trie<String,Integer> t = new PatriciaTrie<>(); 
t.put("a", 123); 
t.put("ab", 234); 
t.put("abcd", 5434); 
System.out.println(t.prefixMap("ab").values());