2009-11-23 11 views
8
public final Comparator<String> ID_IGN_CASE_COMP = new Comparator<String>() { 

     public int compare(String s1, String s2) { 
      return s1.compareToIgnoreCase(s2); 
     } 
    }; 

private Map< String, Animal > _animals = new TreeMap< String, Animal >(ID_IGN_CASE_COMP); 

Il mio problema è, come utilizzare il metodo get (id) ignorando il comparatore dato. Voglio che la mappa sia ordinata da Case Insensitive ma, voglio che sia sensibile al maiuscolo e al minuscolo quando recupero i valori con una determinata chiave.Java TreeMap (comparatore) e ottenere il metodo ignorando il comparatore

+1

Come dovrebbe funzionare? La TreeMap dovrebbe rappresentare due diversi ordini. Non può farlo. – jitter

+2

commento breve: non è necessario creare questo comparatore già esistente nella classe java.lang.String: String.CASE_INSENSITIVE_ORDER – Pierre

+0

Non vedo il problema. Otterrà il valore con il tasto String Caso in modo sensibile. – EJB

risposta

8

Penso che la risposta è semplice. Implementa il tuo comparatore che esegue un ordinamento senza distinzione tra maiuscole e minuscole ma effettua NON restituisce 0 per "A" e "a" ... ordina anche loro.

Il problema è che il comparatore restituisce 0 per il caso di confronto ("A", "a") che significa che è la stessa chiave per quanto riguarda la mappa.

Usare un comparatore come:

public final Comparator<String> ID_IGN_CASE_COMP = new Comparator<String>() { 

    public int compare(String s1, String s2) { 
     int result = s1.compareToIgnoreCase(s2); 
     if(result == 0) 
      result = s1.compareTo(s2); 
     return result; 
    } 
}; 

Allora tutti i tasti andranno in indipendentemente dal caso e "a" e "A" saranno ancora essere ordinati insieme.

In altre parole, get ("a") ti darà un valore diverso da get ("A") ... e verranno entrambi mostrati in iteratori keySet(). Saranno solo ordinati insieme.

+0

questo suona bene, grazie. Lo proverò da quando ho capito che devo tenerlo in considerazione anche quando uso il metodo put. Poiché devo distinguere anche "A" da "a". Sto per testarlo e farti sapere. – d0pe

+0

Grazie mille, ha risolto entrambi i miei problemi. Questa era solo la risposta che volevo. Grazie mille ancora una volta :) – d0pe

+0

Felice che funzionasse. A volte la risposta semplice è quella giusta. :) – PSpeed

1

Dovrai utilizzare due TreeMaps distinti per questo, con lo stesso contenuto ma diversi comparatori.

+0

Questo richiede solo troppo spazio ... Preferirei avere un set di chiavi e confrontarle, ma cercavo un modo più semplice – d0pe

1

forse farà il lavoro:

new Comparator<String>(){ 
    public int compare(String s1, String s2) 
    { 
     String s1n = s1.toLowerCase(); 
     String s2n = s2.toLowerCase(); 

     if(s1n.equals(s2n)) 
     { 
      return s1.compareTo(s2); 
     } 
     return s1n.compareTo(s2n); 
    } 
}; 
                } 
+0

+1 Devi fare lowerCase per ogni carattere, non l'intera stringa. Ma la direzione è giusta. Si comporta diversamente dal comparatore senza distinzione tra maiuscole e minuscole (i tasti "a", "A" sono uguali per il comparatore senza distinzione tra maiuscole e minuscole). –

-1

Usa floorEntry e poi higherEntry in un ciclo per trovare le voci caso-insensitively; fermati quando trovi la corrispondenza esatta della chiave.

+0

Come funziona davvero? Ricevo la parte in cui floorEntrry mi restituirebbe la chiave cercata ma, se la chiave cercata era "aa1", potrebbe trovare "Aa1" o "AA1", voce più alta dandomi uno degli altri – d0pe

+0

Hai ragione - ha vinto " t lavorare come se fosse necessario che la mappa utilizzi un comparatore con distinzione tra maiuscole e minuscole (non ciò che si desidera) e l'avvio da key.toLowerCase (Locale) non sarebbe affidabile per lingue diverse. La risposta accettata è il modo per ottenere quello che vuoi. –

6

In una TreeMap, aggiungendo due chiavi aeb (in questo ordine) in modo che il confronto (a, b) restituisca 0 risulterà che l'ultima voce aggiunta (b) sovrascriverà la prima (a).

Nel tuo caso, questo significa che non ci sarà mai alcun uso per l'insensitive case (id).

citando http://java.sun.com/javase/6/docs/api/java/util/TreeMap.html

Si noti che l'ordinamento mantenuto da una mappa ordinata (se un comparatore esplicita è fornita) deve essere coerente con eguali se questa mappa ordinato è quello di attuare correttamente l'interfaccia Map. (Vedi Comparable o Comparator per una definizione precisa di coerente con equals.) Questo perché l'interfaccia Map è definita in termini dell'operazione equals, ma una mappa esegue tutti i confronti chiave usando il suo metodo compareTo (o compare), quindi due chiavi che sono considerati uguali con questo metodo sono, dal punto di vista della mappa ordinata, uguali. Il comportamento di una mappa ordinata è ben definito anche se il suo ordinamento è incoerente con gli uguali; semplicemente non riesce a rispettare il contratto generale dell'interfaccia Mappa.

Questo probabilmente non è quello che desideri.

Se la mappa è relativamente piccola e non è necessario recuperare le voci ordinate molte volte, una soluzione è utilizzare una HashMap (o una TreeMap senza impostare esplicitamente il comparatore) e ordinare le voci senza distinzione tra maiuscole e minuscole quando hai bisogno di loro ordinati

1

avete bisogno di un multimap: ogni voce di questa multimap mantiene i insensibili chiavi casi e aanother mappa con le chiavi originali come valore.

Ci sono molte implementazioni liberamente utilizzabili su multimaps quali Common Collections, Google Collections, ecc

0

In aggiunta a tutte le altre risposte e concordare, che è impossibile avere una struttura unica TreeMap con diversi comparatori:

Dalla tua domanda ho capito che ci sono due requisiti: il modello dei dati deve essere case sensitive (se si desidera utilizzare i valori maiuscole e minuscole quando si utilizza get()), il relatore non fa distinzione tra maiuscole e minuscole (si desidera un ordinamento sensibile al maiuscolo/minuscolo, la presentazione è solo un'ipotesi).

Supponiamo di popolare la mappa con i mapping (aa, obj1), (aA, obj2), (Aa, obj3), (AA, obj4). L'iteratore fornirà i valori nell'ordine: (obj4, obj3, obj2, obj1) (*). Ora quale ordine ti aspetti se la mappa è stata ordinata senza distinzione tra maiuscole e minuscole? Tutte e quattro le chiavi sarebbero uguali e l'ordine indefinito. O stai cercando una soluzione che risolva la raccolta {obj1, obj2, obj3, obj4} per la chiave 'AA'? Ma questo è un approccio diverso.

incoraggia così la comunità ad essere onesti: quindi il mio consiglio a questo punto è quello di guardare la vostra esigenza di nuovo :)

(*) non testato, per scontato che 'A' < 'a' = true.

Problemi correlati