2012-02-01 14 views
12

C'è qualche motivo particolare per cui questi sono mancanti?Perché Java `BitSet` non ha le funzioni` shiftLeft` e `shiftRight`?

Esiste in BigInteger, ma a causa del modello di progettazione immutabile di BigInteger questi sono in genere terribilmente lenti. BitSet è molto più bello perché è mutabile, ma mi mancano davvero le funzioni shift (<< e per long s). Per BitSet, sarebbe utile anche uno spostamento sul posto, oltre alla rotazione ciclica.

Ho visto la risposta a Shifting a Java BitSet (utilizzando get(off, len) per lo spostamento, tuttavia ciò richiede la copia).

Non fraintendetemi. So dove segnalare i bug. Mi stavo chiedendo se c'era un particolare motivo per ometterli, ad esempio , ad es. qualche motivo di design o un tale concetto. In particolare poiché sono inclusi in BigInteger.

+0

Perché è un "set", non una "stringa". – bmargulies

+1

@bmargulies: A 'long' non è una stringa. Eppure, ha gli operatori di turno. E un 'String' in realtà no. E la semantica 'get (i, j)' concorda essenzialmente con 'substring', e non è disponibile per' long' o ... –

+0

Il termine 'set' significa 'una * collezione non ordinata *. Il BitSet ha il compito di sapere quali poteri di 2 sono attivati, non di mescolarli. – bmargulies

risposta

9

Concettualmente, uno BitSet viene in genere/spesso utilizzato per tenere traccia di molte impostazioni, in modo tale che ogni bit nell'insieme abbia un significato specifico. Quindi un'operazione di cambio non ha molto senso in quel contesto.

Hai chiaramente trovato un altro utile per uno BitSet, ma è al di fuori dell'ambito per il quale era probabilmente previsto BitSet.

+1

Per citare da [i documenti] (http://docs.oracle.com/javase/6/docs/api/java/util/BitSet.html): BitSet è stato immaginato come _ "un vettore di bit che cresce come necessario ". Questo è molto più generale dell'uso tipico che suggerisci. Altre classi di vettori (Vector, ArrayList, ecc.) Non hanno un'operazione "shift", ma hanno operazioni "insert" e "delete" che fanno effettivamente la stessa cosa. Sarebbe logico che BitSet abbia funzionalità simili, ma non è così. –

+0

Il punto 'set' (non ordinato) è buono, tranne per il fatto che viene utilizzato in modo un po 'inconsueto. Grazie. –

+0

Mi interrogo sulla vista che BitSet è per le impostazioni. Se faccio impostazioni, uso bit in int/long, proprio come "real programmers" :-) ha fatto 20 anni fa, o, più correttamente, userò Enums e un EnumSet. Tendo ad usare BitSet di più come un set di caratteri sparsi/compatti '. – user949300

1

La mia ipotesi è che renderebbe alcuni dei loro codici molto più complicati. Ad esempio, se "lasci il turbo per 3" tutto, potresti avere un campo aggiuntivo, shift, che è -3 (o forse 3, ho solo il 50% di possibilità di farlo bene :-). E, per i metodi get() e set(), se si regola semplicemente bitIndex per shift, il codice dovrebbe funzionare. per esempio.

public boolean get(int bitIndex) { 
    bitIndex += shift; // new code!!! 
    if (bitIndex < 0) 
     throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex); 

    checkInvariants(); 

    int wordIndex = wordIndex(bitIndex); 
    return (wordIndex < wordsInUse) 
     && ((words[wordIndex] & (1L << bitIndex)) != 0); 
    } 

Tuttavia, per alcune delle altre operazioni, come interseca() eo(), il codice sarebbe iniziare a ricevere davvero disordinato. In questo momento il cuore del metodo o() è molto semplice e veloce:

// Perform logical OR on words in common 
    for (int i = 0; i < wordsInCommon; i++) 
     words[i] |= set.words[i]; 

    // Copy any remaining words 
    if (wordsInCommon < set.wordsInUse) 
    System.arraycopy(set.words, wordsInCommon, 
        words, wordsInCommon, 
       wordsInUse - wordsInCommon); 

Se entrambi bitsets avevano possibili turni questo sarebbe un casino veloce. Probabilmente pensavano che se davvero volevi cambiare, dovresti usare get and copy.

Una cosa che mi ha sorpreso - in get(), non lo fanno 1L << bitIndex&31. Apparentemente lo < < si avvicina, il che, ora che ricordo il mio linguaggio macchina molto distante, ha senso.

+1

Sì, ho pensato di farlo. Ma avevo davvero bisogno di 'or' e' xor' per funzionare. Java ha in realtà un codice per fare i turni su 'int []' in 'BigInteger', e potrebbero praticamente copiarli in' BitSet' per 'long []'. Non è molto diverso. –

Problemi correlati