2012-02-01 20 views
12

Có lý do cụ thể nào khiến chúng thiếu sót không?Tại sao Java `BitSet` không có các hàm` shiftLeft` và `shiftRight`?

Chúng tồn tại trong BigInteger, nhưng do mẫu thiết kế không thay đổi của BigInteger chúng thường rất chậm. BitSet đẹp hơn nhiều vì có thể thay đổi, nhưng tôi thực sự bỏ lỡ các chức năng shift (<<>>> cho long s). Đối với BitSet, chuyển dịch tại chỗ cũng sẽ hữu ích, cũng như xoay vòng theo chu kỳ.

Tôi đã thấy câu trả lời cho Shifting a Java BitSet (sử dụng get(off, len) để dịch chuyển; tuy nhiên điều này yêu cầu sao chép).

Đừng làm cho tôi sai. Tôi biết nơi để báo cáo lỗi. Tôi chỉ tự hỏi nếu có một lý do cụ thể là để bỏ qua chúng, ví dụ: một số mẫu thiết kế hoặc một khái niệm như vậy. Cụ thể là chúng được bao gồm trong BigInteger.

+0

Vì đó là 'bộ', không phải là 'chuỗi'. – bmargulies

+1

@bmargulies: Một 'long' cũng không phải là một chuỗi. Tuy nhiên, nó có các nhà khai thác dịch chuyển. Và một 'String' thực sự thì không. Và ngữ nghĩa 'get (i, j)' về cơ bản đồng ý với 'chuỗi con', và không có sẵn cho' long' hoặc là ... –

+0

Thuật ngữ 'set' có nghĩa là 'an * bộ sưu tập không theo thứ tự *'. BitSet có công việc biết được quyền hạn nào của 2 được bật, không phải là xáo trộn chúng. – bmargulies

Trả lời

9

Về mặt khái niệm, BitSet thường được sử dụng để theo dõi nhiều cài đặt, sao cho mỗi bit trong tập hợp có ý nghĩa cụ thể. Vì vậy, một hoạt động thay đổi làm cho ít ý nghĩa trong bối cảnh đó.

Bạn đã tìm thấy một mục đích hữu ích khác cho một số BitSet, nhưng nằm ngoài phạm vi mà BitSet có thể đã được hình dung.

+1

Trích dẫn từ [tài liệu] (http://docs.oracle.com/javase/6/docs/api/java/util/BitSet.html): BitSet được hình dung là _ "một vectơ các bit phát triển khi cần . " Điều này là tổng quát hơn nhiều so với cách sử dụng thông thường mà bạn đề xuất. Các lớp vector khác (Vector, ArrayList, v.v.) không có hoạt động "shift", nhưng chúng có các hoạt động "chèn" và "xóa" có hiệu quả tương tự. Nó sẽ có ý nghĩa đối với BitSet để có chức năng tương tự, nhưng nó không có. –

+0

Điểm thiết lập 'không có thứ tự 'là tốt, ngoại trừ việc nó không được sử dụng một cách không hợp lý. Cảm ơn bạn. –

+0

Tôi đặt câu hỏi rằng BitSet là dành cho cài đặt. Nếu tôi đang cài đặt, tôi hoặc sử dụng bit trong một int/dài, giống như "lập trình viên thực sự" :-) đã làm 20 năm trước, hoặc, đúng hơn, tôi sẽ sử dụng Enums và EnumSet. Tôi có xu hướng sử dụng BitSets nhiều hơn như là một tập hợp sp thưa thớt/nhỏ gọn. – user949300

1

Tôi đoán là nó sẽ làm cho một số cách mã của họ phức tạp hơn. Ví dụ, nếu bạn "trái thay đổi bởi 3" tất cả mọi thứ, bạn có thể có một trường bổ sung, thay đổi, đó là -3 (hoặc có thể 3, tôi đã chỉ có 50% cơ hội để làm cho nó đúng :-). Và đối với các phương thức get() và set(), nếu bạn chỉ cần điều chỉnh bitIndex bằng shift, mã sẽ hoạt động. ví dụ.

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

Tuy nhiên, đối với một số hoạt động khác, như giao nhau() và hoặc(), mã sẽ bắt đầu trở nên thực sự lộn xộn. Hiện tại, cốt lõi của phương thức hoặc() rất đơn giản và nhanh chóng:

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

Nếu cả hai BitSets có thể thay đổi điều này sẽ nhanh chóng lộn xộn. Họ có thể nghĩ rằng nếu bạn thực sự muốn thay đổi, bạn nên sử dụng get và copy.

Một điều khiến tôi ngạc nhiên - trong get(), họ không làm 1L << bitIndex&31. Rõ ràng là < < vòng quanh, mà bây giờ tôi nhớ ngôn ngữ máy từ xa của tôi, có ý nghĩa.

+1

Vâng, tôi đã cân nhắc thực hiện điều đó. Nhưng tôi thực sự cần 'hoặc' và' xor' để làm việc. Java thực sự có mã để thực hiện các thay đổi trên 'int []' trong 'BigInteger', và chúng có thể sao chép khá nhiều sang' BitSet' cho 'long []'. Nó không thực sự khác nhiều. –