Структури даних .NET:
Більше до розмови про те, чому ArrayList та List насправді різні
Масиви
Як стверджує один користувач, масиви - це колекція "старої школи" (так, масиви вважаються колекцією, хоча не є частиною System.Collections
). Але що таке "old school" щодо масивів порівняно з іншими колекціями, тобто тими, які ви вказали у своєму заголовку (тут, ArrayList та List (Of T))? Почнемо з основ, переглянувши масиви.
Для початку Arrays в Microsoft .NET - це "механізми, які дозволяють розглядати кілька [логічно пов'язаних] елементів як єдину колекцію" (див. Пов'язану статтю). Що це означає? Масиви зберігають окремі елементи (елементи) послідовно, один за одним, в пам'яті зі стартовою адресою. Використовуючи масив, ми можемо легко отримати доступ до послідовно збережених елементів, що починаються з цієї адреси.
Крім цього і всупереч програмуванню 101 загальної концепції, масиви дійсно можуть бути досить складними:
Масиви можуть бути одномірними, багатовимірними або нежирними (про нечіткі масиви варто прочитати). Самі масиви не є динамічними: після ініціалізації масив n розмірів залишає достатньо місця, щоб вмістити n кількість об'єктів. Кількість елементів у масиві не може зростати або зменшуватися. Dim _array As Int32() = New Int32(100)
залишає достатньо місця на блоці пам'яті для масиву, який містить 100 об'єктів примітивного типу Int32 (у цьому випадку масив ініціалізується, щоб містити 0s). Адреса цього блоку повертається до _array
.
Згідно зі статтею, загальна мовна специфікація (CLS) вимагає, щоб усі масиви були нульовими. Масиви в .NET підтримують масиви на основі нуля; однак це рідше. У результаті "спільної" нульових масивів Microsoft витрачає багато часу на оптимізацію їх продуктивності ; отже, одномірні, нульові масиви (SZ) - це "особливі" - і справді найкраща реалізація масиву (на відміну від багатовимірного тощо) - тому що СЗ мають специфічні мовні інструкції щодо маніпулювання ними.
Масиви завжди передаються за посиланням (як адреса пам'яті) - важливий фрагмент головоломки масиву, який потрібно знати. Хоча вони перевіряють межі (викличе помилку), перевірка меж також може бути відключена на масивах.
Знову ж таки, найбільша перешкода для масивів - це те, що вони не підлягають повторному зміненню. Вони мають "фіксовану" ємність. Представляємо ArrayList та List (Of T) до нашої історії:
ArrayList - негенеричний список
ArrayList (поряд з List(Of T)
- хоча є деякі критичні відмінності, тут, пояснено пізніше) - це , можливо , краще за все розглядати як чергове доповнення до колекції (в широкому сенсі). ArrayList успадковує інтерфейс IList (нащадок інтерфейсу 'ICollection'). Самі ArrayLists є об'ємнішими - вимагають більше накладних витрат, ніж списки.
IList
дає можливість реалізації трактувати ArrayLists як списки фіксованого розміру (наприклад, масиви); однак, крім додаткової функціональності, доданої ArrayLists, немає реальних переваг у використанні ArrayLists, які мають фіксований розмір як ArrayLists (над масивами) в цьому випадку помітно повільніше.
З мого читання, ArrayLists не можна закреслити: "Використання багатовимірних масивів як елементів ... не підтримується". Знову ще один цвях у труні ArrayLists. ArrayLists також не "надрукував» - це означає , що під ним все, ArrayList просто динамічний масив об'єктів: Object[]
. Для цього потрібно багато боксу (неявного) та розпакування (явного) при впровадженні ArrayLists, знову додаючи до їхніх витрат.
Не обгрунтована думка: я думаю, що я пам’ятаю чи читав, чи чув від одного з моїх професорів, що ArrayLists є своєрідною концептуальною дитиною ублюдків спроби переходу з масивів до колекцій списків, тобто, коли колись було велике вдосконалення для масивів, вони більше не є найкращим варіантом, оскільки подальший розвиток було зроблено щодо колекцій
Список (з T): яким став ArrayList (і сподівався бути)
Різниця у використанні пам'яті достатньо значна, коли список (Of Int32) спожив на 56% менше пам'яті, ніж ArrayList, що містить той же примітивний тип (8 Мб проти 19 МБ у вищезгаданій демонстрації джентльмена: знову ж, тут пов'язано ) - хоча це результат, складений 64-бітною машиною. Ця різниця насправді демонструє дві речі: по-перше, (1), об'єкт типу "об'єкт" типу Int32 (ArrayList) є набагато більшим, ніж чистий примітивний тип Int32 (Список); по-друге (2), різниця експоненціальна в результаті внутрішньої роботи 64-бітної машини.
Отже, у чому різниця і що таке Список (Т) ? MSDN визначає List(Of T)
як "... сильно набраний список об'єктів, до яких можна отримати доступ за індексом." Тут важливе значення має "сильно набраний" біт: список (з T) "розпізнає" типи і зберігає об'єкти як їх тип. Отже, а Int32
зберігається як тип, Int32
а не Object
тип. Це усуває проблеми, спричинені боксу та розпакування.
MSDN вказує, що ця різниця вступає в дію лише під час зберігання примітивних типів, а не референтних типів. Занадто, різниця дійсно виникає у великих масштабах: понад 500 елементів. Що ще цікавіше, це те, що документація MSDN говорить: "Для вашої переваги використовувати тип-реалізацію класу List (Of T) замість класу ArrayList ...."
По суті, List (Of T) - це ArrayList, але краще. Це "загальний еквівалент" ArrayList. Як і ArrayList, його не гарантовано сортувати до сортування (перейти до фігури). Список (Of T) також має деяку додаткову функціональність.