2013-06-02 11 views
14

Esiste un caso d'uso per il metodo size() nella classe java.util.BitSet?Qual è il motivo del metodo size() di BitSet?

Voglio dire - il JavaDoc dice chiaramente che dipende dall'implementazione, restituisce la dimensione della memoria interna long[] in bit. Da quello che dice, si potrebbe concludere che non sarà in grado di impostare un po 'con un indice superiore a size(), ma che non è vero, il BitSet può crescere automaticamente:

BitSet myBitSet = new BitSet(); 
System.out.println(myBitSet.size()); // prints "64" 
myBitSet.set(768); 
System.out.println(myBitSet.size()); // prints "832" 

in ogni singolo incontro con BitSet ho avuto nella mia vita, ho sempre voluto usare length() dal momento che si restituisce la dimensione logica del BitSet:

BitSet myBitSet = new BitSet(); 
System.out.println(myBitSet.length()); // prints "0" 
myBitSet.set(768); 
System.out.println(myBitSet.length()); // prints "769" 

Anche se mi è stato di programmazione Java per gli ultimi 6 anni, i due metodi sono sempre molto confondendo per me. Li mescolo spesso e uso quello sbagliato, per inciso, perché nella mia testa, penso a BitSet come un intelligente Set<boolean> dove userei size().

È come se ArrayList avesse length() restituire il numero di elementi e size() restituire la dimensione dell'array sottostante.

Ora, c'è qualche caso d'uso per il metodo size() che mi manca? È utile in qualche modo? Qualcuno l'ha mai usato per qualcosa? Potrebbe essere importante per alcuni bit di puntamento manuale o qualcosa di simile?


EDIT (dopo qualche ricerca più)

mi sono reso conto BitSet è stato introdotto in Java 1.0, mentre il quadro Collezioni con la maggior parte delle classi che usiamo è stato introdotto in Java 1.2. Quindi, in pratica, mi sembra che lo size() sia mantenuto per ragioni legacy e non ci sia un vero uso per questo. Le nuove classi Collection non hanno questi metodi, mentre alcuni dei vecchi (Vector, ad esempio) lo fanno.

risposta

4

Ho realizzato che BitSet è stato introdotto in Java 1.0 mentre il framework Collections con la maggior parte delle classi che usiamo è stato introdotto in Java 1.2.

Corretto.

Quindi, in pratica, mi sembra che size() sia mantenuta a causa di motivi legacy e che non ci sia un reale utilizzo.

Sì, praticamente.

L'altro metodo "dimensione" è length() che fornisce l'indice più grande in cui è impostato un bit. Da un punto di vista logico, length() è più utile di size() ... ma length() è stato introdotto solo in Java 1.2.

L'unica (ipotetica) usa-caso posso pensare a dove size() potrebbe essere migliore di length() è quando:

  • si sta cercando di stabilire un "paletto" per un'iterazione dei bit nella impostato, e
  • è molto probabile che si smetterà di iterare molto prima della fine, e
  • non importa se si va un po 'oltre l'ultimo bit impostato.

In tal caso, size() è probabilmente meglio di length() perché è una chiamata più economica. (Guarda il codice sorgente ...) Ma è piuttosto marginale.

(immagino, un altro caso d'uso in maniera analoga è quando si sta creando un nuovo BitSet e preallocare è basata sulla size() di un BitSet esistente. Anche in questo caso, la differenza è marginale.)

Ma si sono giusto per la compatibilità. È chiaro che non è stato possibile né eliminare size() né modificare la semantica senza creare problemi di compatibilità. Quindi presumibilmente decisero di lasciar perdere. (In effetti, non hanno nemmeno visto la necessità di deprecarlo. Il "danno" nell'avere un metodo non particolarmente utile nell'API è minimo.)

+0

Sembra come se fossi sulla buona strada, dopo tutto. Aspetterò un po 'di più se qualcuno viene con un uso rivoluzionario per il metodo, ma immagino che il segno di spunta sarà tuo. È un peccato che non lo abbiano deprecato. Mi farebbe risparmiare tempo prezioso nell'usare quello sbagliato. –

0

È il numero di 0 e 1 che deve essere un multiplo di 64. È possibile utilizzare la cardinalità() per il numero di 1s.

+2

So cosa fa. Ma mi chiedo perché mai qualcuno vorrebbe invocare un simile metodo. O includilo nell'API, in primo luogo. Ho ragione, supponendo che 'BitSet' sia una vecchia generazione di classi util? (vedere la mia modifica) –

+0

Non è il "numero di 0 e 1". È ["il numero di bit di spazio effettivamente utilizzati da questo BitSet per rappresentare i valori bit"] (http://docs.oracle.com/javase/7/docs/api/java/util/BitSet.html#size()). – EJP

+1

@EJP Anche se potrebbe essere più chiaro, non vedere la differenza. C'è spazio che non è pieno di 0 e 1? –

1

Se il metodo size non è stato progettato dai creatori di Java come pubblico, sarebbe ancora indubbiamente esistere come metodo/campo privato. Quindi stiamo discutendo sulla sua accessibilità e forse sulla denominazione.

Java 1.0 ha avuto un sacco di ispirazione, non solo la sintassi procedurale, da C/C++. Nella libreria standard C++ esistono anche gli equivalenti a BitSet, length e size. Loro sono chiamati là size e capacity, rispettivamente. Raramente c'è un motivo difficile per usare capacity in C++, e ancor meno in un linguaggio spazzato come Java, ma avere il metodo accessibile è ancora discutibilmente utile. Spiegherò in termini Java.

Dimmi, qual è il numero massimo di istruzioni macchina necessarie per l'esecuzione di un'operazione BitSet come set? Si vorrebbe rispondere "solo una manciata", ma questo è vero solo se quella particolare operazione non porta alla riallocazione dell'intero array sottostante. Teoricamente, le riallocazioni trasformano un algoritmo a tempo costante in un tempo lineare.

Questa differenza teorica ha un impatto molto pratico? Raramente. L'array di solito non cresce troppo spesso. Tuttavia, ogni volta che si dispone di un algoritmo che funziona su un valore crescente di BitSet con una dimensione finale approssimativamente nota, si salverà su riallocazioni se si passa già la dimensione finale al costruttore di BitSet. In alcune circostanze molto speciali questo può anche avere un effetto notevole, nella maggior parte dei casi non fa male.

  • set quindi ha una complessità temporale costante: chiamarla non può mai bloccare l'applicazione troppo a lungo.
  • se solo un'istanza estremamente grande BitSet utilizza tutta la memoria disponibile (in base alla progettazione), lo swap potrebbe iniziare in modo evidente in seguito, a seconda di come JVM implementa l'operazione di crescita (con o senza una copia aggiuntiva).

Ora immagina di operare su molti BitSet, ognuno dei quali è stato allocato con una dimensione di destinazione. Stai costruendo un'istanza di BitSet da un'altra e vuoi che la nuova condivida la dimensione di destinazione della vecchia come sai che le userete fianco a fianco. Avere il metodo size rende più semplice l'implementazione pulita.

0

Una delle ragioni principali che ritengo possa essere utile è quando è necessario estendere la classe BitSet e sovrascrivere il metodo della lunghezza. In tal caso, la dimensione è utile. sotto è come la lunghezza restituisce il valore con dipendenza dal metodo di dimensione.

protected Set bitset; 
public int length() { 
    int returnValue = 0; 
    // Make sure set not empty 
    // Get maximum value +1 
    if (bitset.size() > 0) { 
    Integer max = (Integer)Collections.max(bitset); 
    returnValue = max.intValue()+1; 
    } 
    return returnValue; 
} 
Problemi correlati