2012-02-01 8 views
12

Czy jest jakiś szczególny powód, dla którego ich brakuje?Dlaczego Java `BitSet` nie ma funkcji` shiftLeft` i `shiftRight`?

Występują one w wersji BigInteger, ale ze względu na niezmienny wzór projektu BigInteger są one zwykle bardzo wolne. BitSet jest o wiele ładniejszy, ponieważ jest zmienny, ale brakuje mi funkcji shift (s). Dla BitSet przydatne będzie również przesunięcie w miejscu, jak również rotacja cykliczna.

Widziałem odpowiedź na Shifting a Java BitSet (używanie get(off, len) do zmiany biegów, jednak wymaga to kopiowania).

Nie zrozum mnie źle. Wiem, gdzie zgłaszać błędy. Zastanawiam się tylko, czy istnieje szczególny powód powodujący ich pominięcie, np. jakiś wzorzec projektowy lub taka koncepcja. W szczególności jako zawarty w BigInteger.

+0

Ponieważ jest to "zestaw", a nie "ciąg". – bmargulies

+1

@bmargulies: '' long' też nie jest ciągiem. Ma jednak operatorów zmianowych. A 'String' faktycznie nie ma. A semantyka "get (i, j)" zasadniczo zgadza się z 'substring' i nie jest dostępna dla' long' albo ... –

+0

Termin 'set' oznacza kolekcję * an unacheered *. BitSet ma zadanie wiedzieć, które moce 2 są włączone, a nie tasować je. – bmargulies

Odpowiedz

9

Pojęciowo, BitSet jest zwykle/często używany do śledzenia wielu ustawień, tak, że każdy bit w zestawie ma określone znaczenie. Tak więc operacja zmiany nie ma większego sensu w tym kontekście.

Wyraźnie znalazłeś inny przydatny cel dla BitSet, ale wykracza to poza zakres, dla którego prawdopodobnie przewidywano, że jest to BitSet.

+1

Aby zacytować z [the docs] (http://docs.oracle.com/javase/6/docs/api/java/util/BitSet.html): BitSet był przewidziany jako _ "wektor bitów, który rośnie w miarę potrzeb . " Jest to o wiele bardziej ogólne niż typowe użycie, które sugerujesz. Inne klasy wektorowe (Vector, ArrayList itp.) Nie mają operacji "shift", ale mają operacje "wstawiania" i "usuwania", które skutecznie robią to samo. Byłoby sensowne, by BitSet miał podobną funkcjonalność, ale tak nie jest. –

+0

"Nieuporządkowany" punkt "set" jest dobry, z tym wyjątkiem, że jest stosowany w sposób nieoczekiwany. Dziękuję Ci. –

+0

Podważam widok, że BitSet jest dla ustawień. Jeśli robię ustawienia, albo używam bitów w int/long, tak jak "prawdziwi programiści" :-) zrobiłem to 20 lat temu, albo, bardziej poprawnie, użyję Enums i EnumSet. Zwykle używam BitSetów bardziej jako rzadkiego/kompaktowego 'Set '. – user949300

1

Domyślam się, że niektóre z ich kodu byłyby bardziej skomplikowane. Na przykład, jeśli "zostawiłeś przesunięcie o 3" wszystko, możesz mieć jedno dodatkowe pole, przesunięcie, które wynosi -3 (lub może 3, mam tylko 50% szansy, aby to naprawić :-). I dla metod get() i set(), jeśli po prostu dostosujesz bitIndex przez shift, kod powinien zadziałać. na przykład

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); 
    } 

Jednak dla niektórych innych operacji, jak przecina() i lub(), kod będzie zacząć naprawdę bałagan. Teraz rdzeń metody lub() jest bardzo prosta i szybka:

// 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); 

Jeśli oba BitSets miał ewentualne zmiany będzie to bałagan szybko. Prawdopodobnie doszli do wniosku, że jeśli naprawdę chcesz się przesuwać, powinieneś użyć get i copy.

Jedna rzecz, która mnie zaskoczyła - w get(), nie robią 1L << bitIndex&31. Podobno < < pętle wokół, które, teraz, gdy pamiętam mój odległy język maszynowy, ma sens.

+1

Tak, rozważałem zrobienie tego. Ale naprawdę potrzebowałem pracy "albo" i "xor". Java faktycznie ma kod do wykonywania zmian w 'int []' w 'BigInteger', i mogliby prawie skopiować to do' BitSet' dla 'long []'. To naprawdę niewiele różni się. –