Что такое хороший, изменяемый размер, произвольный доступ, эффективный байтовый векторный класс в Java? - PullRequest
5 голосов
/ 01 октября 2011

Я пытаюсь найти класс для хранения вектора байтов в Java, который поддерживает: произвольный доступ (чтобы я мог получить или установить байт в любом месте), изменение размера (чтобы я мог либо добавить что-либо в конец, либо вручную изменить размер), разумная эффективность (я мог бы хранить мегабайты данных в этих вещах), все в памяти (у меня нет файловой системы). Есть предложения?

Пока что кандидатами являются:

  • byte[]. Не изменяемого размера.
  • java.util.Vector<Byte>. Злой. Также мучительно неэффективно.
  • java.io.ByteArrayOutputStream. Не произвольный доступ.
  • java.nio.ByteBuffer. Размер не изменяется.
  • org.apache.commons.collections.primitives.ArrayByteList. Не изменяемого размера. Что странно, потому что он автоматически изменит размер, если вы добавите к нему материал, вы просто не сможете явно изменить размер!
  • Чистая реализация ОЗУ java.nio.channels.FileChannel. Не могу найти. (Помните, у меня нет файловой системы.)
  • Apache Commons VFS и файловая система RAM. Если я должен буду, но мне действительно нравится что-то более легкое ...

Это кажется таким странным упущением, что я уверен, что должен что-то пропустить. Я просто выяснил что. Чего мне не хватает?

Ответы [ 3 ]

3 голосов
/ 01 октября 2011

Я бы рассмотрел класс, который заключает в себе множество кусков из byte[] массивов как элементы ArrayList или Vector.

. Делайте каждый кусок кратным, например, 1024байты, поэтому функции доступа могут получить index >> 10 для доступа к нужному элементу ArrayList, а затем index & 0x3ff для доступа к конкретному элементу байта этого массива.

Это позволит избежать потерь при обработкекаждый byte как Byte объект, с дорогой потерей того, что осталось в конце последнего куска.

1 голос
/ 02 октября 2011

В этих случаях я просто инициализирую ссылку на массив разумной длины, а когда он становится слишком маленьким, создаю и копирую его в больший, вызывая Arrays.copyOf (). e.g.:

byte[] a = new byte[16];
if (condition) {
    a = Arrays.copyOf(a, a.length*2);
}

И мы можем обернуть это в классе, если это необходимо ...

0 голосов
/ 01 октября 2011

ArrayList более эффективен, чем Vector, потому что он не синхронизирован.

Для повышения эффективности вы можете начать с приличной начальной емкости.См. Конструктор:

ArrayList(int initialCapacity) 

Я думаю, что по умолчанию установлено значение только 16, хотя вам, возможно, понадобится гораздо больший размер.

Несмотря на то, что кажется, ArrayList очень эффективен даже примиллионная запись! Я написал небольшую тестовую программу, которая добавляет миллионную запись в ArrayList, не объявляя начальную емкость, и на моем 5-летнем ноутбуке с Linux (процессор Core 2 T5200) требуется всего около 100 миллисекунд.заполнить весь список.Если я объявляю начальный интервал в 1 миллион байт, это занимает около 60-80 мс, но если я объявляю 10000 элементов, это может занимать около 130-160 мс, поэтому, возможно, лучше не объявлять что-либо, если вы не можете сделать правильное предположение о месте

Что касается использования памяти, она занимает около 8 Мб памяти, что я считаю абсолютно разумным, если только вы не пишете программное обеспечение для телефона.

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import org.obliquid.util.StopWatch;

public class ArrayListTest {

        public static void main(String args[]) {
                System.out.println("tot=" + Runtime.getRuntime().totalMemory() 
                     + " free=" + Runtime.getRuntime().freeMemory());
                StopWatch watch = new StopWatch();
                List<Byte> bytes = new ArrayList<Byte>();
                for (int i = 0; i < 1000000; i++) {
                        bytes.add((byte) (i % 256 - 128));
                }
                System.out.println("Elapsed: " 
                     + watch.computeElapsedMillisSeconds());
                System.out.println("tot=" + Runtime.getRuntime().totalMemory() 
                     + " free=" + Runtime.getRuntime().freeMemory());
        }
}

Как и ожидалось, Vectorработает немного хуже в диапазоне 160-200 мс.

Пример вывода без указания начального размера и с реализацией ArrayList.

tot=31522816 free=31023176
Elapsed: 74
tot=31522816 free=22537648
...