簡體   English   中英

如何在Java中聲明無限大小/動態的字節數組?

[英]How to Declare a Byte Array of Infinite Size/Dynamic in Java?

我聲明的字節數組在不斷更新時對我來說是未知的,那么如何聲明無限大小/可變大小的字節數組呢?

您不能聲明無限大小的數組,因為這將需要無限的內存。 此外,所有分配調用都處理數字,而不是無限數量。

您可以分配一個按需調整大小的字節緩沖區。 我相信最簡單的選擇是ByteArrayOutputStream

ByteBuffer具有一個使緩沖區的操作更加容易的API,但是您必須自己構建調整大小功能。 最簡單的方法是分配一個更大的新數組,復制舊內容,並將新緩沖區替換為舊緩沖區。

其他答案提到了使用某種List<Byte>的情況。 值得注意的是,如果創建了一堆new Byte()對象,則可以大大增加內存消耗。 Byte.valueOf此問題,但是您必須確保在整個代碼中始終使用它。 如果您打算在許多地方使用此列表,我可能會考慮編寫一個簡單的List裝飾器,該裝飾器可以插入所有元素。 例如:

public class InterningList extends AbstractList<Byte>
{
    ...
    @Override
    public boolean add(Byte b) {
        return super.add(Byte.valueOf(b));
    }
    ...
}

這不是一個完整(甚至沒有經過測試)的示例,只是一些開頭...

Java中的數組不是動態的。 您可以改用列表。

List<Byte> list = new ArrayList<Byte>();

由於具有自動裝箱功能,您可以將Byte對象或原始字節自由添加到此列表中。

要定義不同長度的commons.io.IOUtils只需使用apache commons.io.IOUtils庫,而不是像

byte[] b=new byte[50];

您可以將輸入流傳IOUtils函數,該函數將對該輸入流執行讀取功能,因此字節數組將具有所需的確切字節長度。 例如

byte[] b = IOUtils.toByteArray(inpustream);

混沌..

最好的選擇是使用ArrayList。 當它隨着您的填充而調整大小時。

List<Byte> array = new ArrayList<Byte>();

顯而易見的解決方案是使用ArrayList。

但是,如果您需要性能或內存受限,這將是一個糟糕的解決方案,因為它實際上並不存儲字節,而是存儲字節(即對象)。

對於任何實際應用程序,答案很簡單:您必須管理字節數組,方法是使字節數組根據需要增長。 如果需要,您可以將其嵌入特定的類中:

public class AlmostInfiniteByteArray {

    private byte[] array;
    private int size;

    public AlmostInfiniteByteArray(int cap) {
        array = new byte[cap];
            size = 0;
    }

    public int get(int pos) {
        if (pos>=size) throw new ArrayIndexOutOfBoundsException();
        return array[pos];
    }

    public void set(int pos, byte val) {
        if (pos>=size) {
            if (pos>=array.length) {
                byte[] newarray = new byte[(pos+1)*5/4];
                System.arraycopy(array, 0, newarray, 0, size);
                array = newarray;
            }
            size = pos+1;
        }
        array[pos] = val;
    }
}

ByteArrayOutputStream將允許寫入動態字節數組。 但是,諸如刪除,替換和插入之類的方法不可用。 必須提取字節數組,然后直接對其進行操作。

使用List的任何子類型的ArrayList

List的不同實現可以使您在列表上執行不同的操作(例如,不同的遍歷策略,不同的性能等)

ArrayList的初始容量為10。可以通過ArrayList(5000)進行更改。 ArrayList將在需要時將其大小加倍(它將創建新的數組並將舊的數組復制到新的數組)。

我會稍微調整其他人的答案。

創建LargeByteArray類來管理您的數組。 無論您需要什么,它都會具有get和set方法等。

在后台,該類將使用long來保持當前長度,並使用ArrayList來存儲數組的內容。

我選擇將byte [8192]或byte [16384]數組存儲在ArrayList中。 這將在浪費尺寸方面進行合理的權衡,並減少調整大小的需求。

您甚至可以使數組“稀疏”,即,如果該框中存儲的值非零,則僅分配list.get(index / 8192)條目。

在某些情況下,這種結構可以為您提供更多的存儲空間。

您可以使用的另一種策略是在寫入后壓縮byte []框,並在讀取之前解壓縮(使用LRU高速緩存進行讀取),這可以允許存儲比可用內存多兩倍或更多的內存...盡管這取決於壓縮策略。

之后,您可以查看將一些盒子分頁到磁盤上。

我可以讓你接近無限數組;-)

正如Prashant已經講過的,您可以使用塊中的IOUtils。

這是可以解決任務的一小部分(您將需要IOUtils.toByteArray):

public class IOUtils {

private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;

public static byte[] toByteArray(InputStream input) throws IOException {
    ByteArrayOutputStream output = new ByteArrayOutputStream();
    copy(input, output);
    return output.toByteArray();
}

public static int copy(InputStream input, OutputStream output)
        throws IOException {
    long count = copyLarge(input, output);
    if (count > Integer.MAX_VALUE) {
        return -1;
    }
    return (int) count;
}

public static long copyLarge(InputStream input, OutputStream output)
        throws IOException {
    byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
    long count = 0;
    int n = 0;
    while (-1 != (n = input.read(buffer))) {
        output.write(buffer, 0, n);
        count += n;
    }

    return count;

}
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM