Я хочу получить массив байтов (Массив [Байт]) от где-нибудь (чтение из файла, из сокета, и т.д.) и затем обеспечить эффективный способ вытащить биты из него (например, обеспечить функцию для извлечения 32-разрядного целого числа из смещения N в массиве). Я затем хотел бы перенести массив байтов (скрывающий его) обеспечение функций для получения по запросу битов из массива (вероятно, использующий ленивый val для каждого бита, чтобы выйти).
Я предположил бы иметь переносящийся класс, который берет неизменный тип массива байтов в конструкторе, чтобы доказать, что содержание массива никогда не изменяется. IndexedSeq [Байт] казался релевантным, но я не мог разработать, как пойти от Массива [Байт] в IndexedSeq [Байт].
Часть 2 вопроса - то, если я использовал IndexedSeq [Байт], результант кодирует быть немного медленнее? Мне нужен код для выполнения максимально быстро, так придерживался бы Массива [Байт], если компилятор мог бы сделать лучшее задание с ним.
Я мог записать класс обертки вокруг массива, но это замедлит вещи - один дополнительный уровень абстракции для каждого доступа к байтам в массиве. Производительность очень важна из-за количества доступов к массиву, которые будут требоваться. Я должен быстро кодировать, но хотел бы сделать код приятно одновременно.Спасибо!
PS: Я - новичок Scala.
Обработка массива [T]
как IndexedSeq [T]
вряд ли может быть проще:
Array(1: Byte): IndexedSeq[Byte] // trigger an Implicit View
wrapByteArray(Array(1: Byte)) // explicitly calling
Распаковка убьет вас задолго до того, как появится дополнительный слой косвенного обращения.
C:\>scala -Xprint:erasure -e "{val a = Array(1: Byte); val b1: Byte = a(0); val
b2 = (a: IndexedSeq[Byte])(0)}"
[[syntax trees at end of erasure]]// Scala source: scalacmd5680604016099242427.s
cala
val a: Array[Byte] = scala.Array.apply((1: Byte), scala.this.Predef.
wrapByteArray(Array[Byte]{}));
val b1: Byte = a.apply(0);
val b2: Byte = scala.Byte.unbox((scala.this.Predef.wrapByteArray(a): IndexedSeq).apply(0));
Чтобы избежать этого, библиотека коллекций Scala должна быть специализирована на типе элемента в том же стиле, что и Tuple1
и Tuple2
. Мне сказали, что это запланировано, но это немного сложнее, чем просто шлепать @specialized
повсюду, поэтому я не знаю, сколько времени это займет.
ОБНОВЛЕНИЕ
Да, WrappedArray
является изменяемым, хотя collection.IndexedSeq [Byte]
не имеет методов для изменения, поэтому вы можете просто доверять клиентам, которые не будут приводить к изменяемый интерфейс. Следующий выпуск Scalaz будет включать ImmutableArray , который предотвращает это.
Упаковка осуществляется путем извлечения элемента из коллекции с помощью этого универсального метода:
trait SeqLike[+A, +Repr] extends IterableLike[A, Repr] { self =>
def apply(idx: Int): A
}
На уровне JVM эта подпись стирается по типу до:
def apply(idx: Int): Object
Если ваша коллекция содержит примитивы, то есть подтипы AnyVal
, они должны быть помещены в соответствующую оболочку для возврата из этого метода. Для некоторых приложений это серьезная проблема с производительностью.Чтобы избежать этого, на Java были написаны целые библиотеки, особенно fastutils .
Специализация, направленная на аннотации , была добавлена в Scala 2.8, чтобы инструктировать компилятор генерировать различные версии класса или метода, адаптированные к перестановкам примитивных типов. Это уже было применено к нескольким местам в стандартной библиотеке, например. TupleN
, ProductN
, Функция {0, 1, 2}
. Если бы это также было применено к иерархии коллекций, эти затраты на производительность можно было бы снизить.
Если вы хотите работать с последовательностями в Scala, я рекомендую вам выбрать один из следующих:
Неизменяемые последовательности:
(связанные последовательности) Список, поток, очередь
(индексированные последовательности) Вектор
Mutable seqs:
(связанный seq) ListBuffer
(indexed seq) ArrayBuffer
Новые коллекции Scala (2.8) мне было трудно понять, в первую очередь из-за нехватки (правильной) документации, а также из-за исходный код (сложные иерархии). Чтобы очистить сознание, я сделал этот рисунок, чтобы визуализировать базовую структуру:
(источник: programmera.net )
Также обратите внимание, что Массив
не является частью дерева структура, это особый случай, поскольку она обертывает массив Java (что является особым случаем в Java).