С любезного разрешения Майка Чемберза (Mike Chambers), публикую перевод на русский язык его статьи «Using Vectors in ActionScript 3 and Flash Player 10». Дальнейшее повествование идет от имени Майка.
Одной из новых возможностей, появившихся в Flash Player 10 Public Beta, является включение в эту версию плеера нового класса Vector. По существу, класс Vector является массивом, но в дополнение к функционалу массива он отслеживает тип хранимых элементов данных, и поэтому может обеспечить (иногда довольно существенный) прирост производительности по сравнению с обычным массивом.
Пользоваться классом Vector так же просто, как и пользоваться классом Array. Фактически, класс Vector содержит все те же методы, что и класс Array, и главным отличием между ними является то, как вы создаете экземпляры этих классов.
Для примера, вот так вы инстанцируете экземпляр массива:
-
var a:Array = new Array();
ну или вот так:
-
var b:Array = [];
А это пример создания экземпляра вектора, который будет хранить объекты с типом int:
-
// var ИМЯ_ПЕРЕМЕННОЙ:Vector.<ТИП_ХРАНИМЫХ_ЭЛЕМЕНТОВ> = new Vector<ТИП_ХРАНИМЫХ_ЭЛЕМЕНТОВ>();
-
var vector:Vector.<int> = new Vector.<int>();
Точно так же, как и в случае использования массива, вы можете инстанцировать экземпляры вектора конкретного размера, передавая длину в качестве первого необязательного параметра конструктора:
-
var size:int = 7;
-
var vector:Vector.<int> = new Vector.<int>(size);
Кроме того, конструктор вектора имеет второй необязательный аргумент в виде булева флага, определяющего должен ли текущий экземпляр Vector быть фиксированного размера (true), либо же его длина в дальнейшем может изменяться (false). По умолчанию этот параметр имеет значение false. В дальнейшем его можно изменить обратившись к свойству fixed экземпляра класса Vector:
-
var size:int = 7;
-
var fixed:Boolean = true
-
var vector:Vector.<int> = new Vector.<int>(size, fixed);
-
vector.fixed = !fixed;
Имейте в виду, что если свойство fixed установлено в true, то далее вы уже не можете вызывать методы изменяющие длину массива, например, методы pop(), push(), shift() и т.д.
Кроме того, Vector следит и за соблюдением единообразия типа хранимых в нем переменных, в то время как в массиве можно хранить элементы разных типов:
-
var s:String = "I am a string";
-
var d:Date = new Date();
-
var n:Number = 1138;
-
var a:Array = new Array();
-
a[0] = s;
-
a[1] = d;
-
a[2] = n;
-
-
trace(a[1] is Date); // true
Однако в этом случае у вас возникнут ошибки на этапе компиляции:
-
var s:String = "I am a string";
-
var d:Date = new Date();
-
var n:Number = 1138;
-
var v:Vector.<String> = new Vector.<String>();
-
v[0] = s;
-
v[1] = d;
-
v[2] = n;
-
-
trace(v[1] is Date); // false
-
-
// Ошибки этапа компиляции:
-
// Implicit coercion of a value of type Date to an unrelated type String.
-
// Implicit coercion of a value of type Number to an unrelated type String.
Если не принимать во внимание эти различия, то работа с классом Vector очень похожа на работу с массивом. API обоих классов абсолютно идентичные. Кроме того, так же как и в случае использования массива, вы можете получить доступ к элементам Vector-а, обратившись к ним непосредственно по их индексу:
-
var vector:Vector.<int> = new Vector.<int>();
-
-
var rand:Number;
-
for(var i:int = 0; i <1000000; i++)
-
{
-
rand = (Math.floor(Math.random() * 1000000) as int);
-
vector.push(rand);
-
}
-
trace(vector[7]);
И последнее, что нужно иметь в виду при работе с векторами, заключается в том, что Vector представляет собой вариант «уплотненного» массива. Фактически, это означает, что все элементы, содержащиеся в экземпляре класса Vector должны иметь какое-либо значение или быть равными null. Например, при использовании массива вы можете свободно сделать следующее:
-
var a:Array = new Array();
-
a[0] = "foo";
-
a[6] = "bar";
Однако, если вы попробуете проделать то же самое с экземпляром Vector, то вы получите ошибку RangeError на этапе исполнения:
-
var v:Vector.<String> = new Vector.<String>();
-
v[0] = "foo";
-
v[6] = "bar";
Чтобы исправить это, зададим вектору длину при его создании:
-
var v:Vector.<String> = new Vector.<String>(7);
-
v[0] = "foo";
-
v[6] = "bar";
Ниже приведен пример, который показывает разницу в производительности при работе с вектором и массивом, каждый из которых содержит по миллиону чисел. Имейте в виду, что представленный ниже код — это только один специфичный тест, и повышение производительности в случае использования класса Vector в каждом конкретном приложении может быть как больше, так и меньше.
-
package
-
{
-
import flash.display.Sprite;
-
-
public class VectorTest extends Sprite
-
{
-
private static const NUM_LOOPS:int = 5;
-
public function VectorTest()
-
{
-
-
var vector:Vector.<int> = new Vector.<int>();
-
var array:Array = new Array();
-
-
// Наполняем данными.
-
var rand:Number;
-
for(var i:int = 0; i <1000000; i++)
-
{
-
rand = (Math.floor(Math.random() * 1000000) as int);
-
vector.push(rand);
-
array.push(rand);
-
}
-
-
var sTime:Number = getMilliseconds();
-
loopArray(array);
-
trace("Loop Array Avg (5) : " + ((getMilliseconds() - sTime)/NUM_LOOPS));
-
-
sTime = getMilliseconds();
-
loopVector(vector);
-
trace("Loop Vector Avg (5) : " + ((getMilliseconds() - sTime)/NUM_LOOPS));
-
-
}
-
-
private function getMilliseconds():Number
-
{
-
return (new Date()).getTime();
-
}
-
-
private function loopArray(a:Array):void
-
{
-
var len:Number = a.length;
-
-
var n:int;
-
for(var i:int = 0; i <NUM_LOOPS; i++)
-
{
-
for(var k:int = 0; k <len; k++)
-
{
-
n = a[k];
-
}
-
}
-
}
-
-
private function loopVector(v:Vector.<int>):void
-
{
-
var len:Number = v.length;
-
-
var n:int;
-
for(var i:int = 0; i <NUM_LOOPS; i++)
-
{
-
for(var k:int = 0; k <len; k++)
-
{
-
n = v[k];
-
}
-
}
-
}
-
}
-
-
}
На моей машине вывелись следующие значения:
-
Loop Array Avg (5) : 115.8
-
Loop Vector Avg (5) : 108.8
Что является довольно значительной разницей, с учетом простоты теста (выборка значения элемента по индексу).
Вы можете найти больше информации о классе Vector, обратившись к документации по Flash Player 10 Beta, а так же к информации о Flash Player 10 на Adobe Labs.
См. также:




Спасибо за перевод!
Но, пожалуй, не соглашусь с оценкой.
На мой взгляд прирост в 7% ничтожен, и в этом простом тесте это как раз завышенное значение.
Если добавить в цикл какие-то расчёты, ускорение от обращения к Vector станет ещё меньше.
Типизация, а соответственно, и упрощение внутренней организации, и отсутствие лишних преобразований/проверок, мгновенное получение элемента по индексу, должны были дать ускорение в разы!
Вобщем, то же самое что и с "поддержкой 3D".