Как в мой тип (type) записывать изменяющиеся по размеру массивы / спис

  • Автор темы fedotxxl
  • Дата начала
F

fedotxxl

Как в мой тип (type) записывать изменяющиеся по размеру массивы / списки?
Вообще возможно ли это? Если невозможно, то как добиться подобного эффекта другими методами?
 
Y

Yakov

Используйте класс.
Смотрите исходники java.util.ArrayList, например.
 
F

fedotxxl

Да, я догадывался, что можно сделать через классы... Но через классы, думаю, сильно медлено будет
 
K

K-Fire

так речь о яве идет или о лотус-скрипте? Если LS то массив/список как вариант объявить и можно будет запихивать любой тип.
 
Y

Yakov

Речь, конечно же, идет о LotusScript. Я предлагал посмотреть, как реализован класс java.util.ArrayList, и написать подобный класс. Вот мой класс, которым я пользуюсь постоянно.
Код:
Private Const CAPACITY_INCREMENT = 512
Private Const ARRAY_BASE = -32768

'############################################################################
####
Public Class VariantList

Private values() As Variant
Private count As Long
Private capacity As Long

Private Sub init()
capacity = CAPACITY_INCREMENT
count = 0
Redim values(0 + ARRAY_BASE To capacity - 1 + ARRAY_BASE)
End Sub

Private Sub EnsureCapacity(minCapacity As Long)
Dim newCapacity As Long
newCapacity = capacity
While (newCapacity < minCapacity)
newCapacity = newCapacity + CAPACITY_INCREMENT
Wend
If (capacity < newCapacity) Then
capacity = newCapacity
Redim Preserve values(0 + ARRAY_BASE To capacity - 1 + ARRAY_BASE)
End If
End Sub

'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~

Public Sub New
Call init()
End Sub

Public Sub Delete
Erase values
End Sub

Public Sub add(value As Variant)
ensureCapacity(count + 1)
If Isobject(value) Then
Set values(count + ARRAY_BASE) = value
Else
values(count + ARRAY_BASE) = value
End If
count = count + 1
End Sub

Public Sub clear()
Erase values
Call init()
End Sub

Public Function getElement(index As Long) As Variant
If (index >= count) Then Exit Function
If Isobject(values(index + ARRAY_BASE)) Then
Set getElement = values(index + ARRAY_BASE)
Else
getElement = values(index + ARRAY_BASE)
End If
End Function

Public Function size() As Long
size = count
End Function

End Class
'############################################################################
####
Ограничения данного класса: количество элементов в коллекции не может превышать 64K. Как это обойти, напишу ниже. Еще одно ограничение - элементы можно только добавлять. У меня еще не было ситуаций, когда из коллекции нужно было удалять элементы. Но реализовать метод remove() не составит труда, я надеюсь. :)
Далее. Можно написать подкласс данного класса, поддерживающий сортировку элементов. Можно написать класс "суперколлекции" (или "метаколлекции"), который обойдет ограничение вместимости в 64K элементов. Вот пример:
Код:
Private Const BLOCK_SIZE = 65536

Class VariantHugeList

Private values As VariantList
Private currentList As VariantList
Private count As Long
Private listCount As Long

Private Sub init()
count = 0
listCount = 1
Set values = New VariantList()
Set currentList = New VariantList()
Call values.add(currentList)
End Sub

Sub growth()
listCount = listCount + 1
Set currentList = New VariantList()
Call values.add(currentList)
End Sub

'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~

Public Sub New
Call init()
End Sub

Public Sub Delete
Delete currentList
Delete values
End Sub

Public Sub add(value As Variant)
If (currentList.size() >= BLOCK_SIZE) Then
Call growth()
End If
count = count + 1
currentList.add(value)
End Sub

Public Sub clear()
Delete currentList
Delete values
Call init()
End Sub

Public Function getElement(index As Long) As Variant
If (index >= count) Then Exit Function
Dim listIndex As Long
Dim inListIndex As Long
Dim varList As Variant
listIndex = index \ BLOCK_SIZE
inListIndex = index Mod BLOCK_SIZE
Set varList = values.getElement(listIndex)
If Isobject(varList.getElement(inListIndex)) Then
Set getElement = varList.getElement(inListIndex)
Else
getElement = varList.getElement(inListIndex)
End If
End Function

Public Function size() As Integer
size = count
End Function

End Class
Есть еще "хитрый" динамический массив - список (List):
Код:
Dim myList List As Variant
myList("0") = 0
myList("1") = 1
...
myList("100000") = 100000

Про скорость и память напишу ниже, когда "бенчмарк" свой найду.
 
Y

Yakov

Итак, тесты.
Участники: обычный массив, VariantList, VariantHugeList, List.
Тесты: время заполнения коллекции целыми числами, время произвольного доступа (random access) к элементам коллекции, потребление памяти.
Размеры коллекций - 32K, 64K, 128K элементов.
Результаты:
Код:
32K
C	RA	M
Array			0.110	0.015	516
VariantList	 0.328	0.031	516
VariantHugeList 0.453	0.047	516
List			 0.437	0.047	1688

64K
C	RA	M
Array			0.219	0.031	1028
VariantList	 0.593	0.032	1032
VariantHugeList 0.719	0.109	1052
List			 1.109	0.141	5340

128K

VariantHugeList 1.265	0.203	2064
List			 2.687	0.375	12416
C - время создания, сек.
RA - время, портаченное на произвольный доступ к 10% элементов, сек.
M - потр*цензура*емая коллекцией память, Kb.

Выводы.
Выводы делайте сами. :)
 
F

fedotxxl

Для: Yakov
Можно спросить - каким образом вы проводили тест? Можете выложить свою БД для тестирования?
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!