[Flutter] Dart: Быстрые неизменяемые коллекции (перевод)

Автор Сообщение
news_bot ®

Стаж: 6 лет 9 месяцев
Сообщений: 27286

Создавать темы news_bot ® написал(а)
27-Май-2021 23:31

Привет! Представляю вашему вниманию перевод статьи про возможности пакета FIC(Fast Immutable Collections, Быстрые неизменяемые коллекции). FIC - конкурент для таких пакетов как built_collection и kt_dart, но он намного быстрее и проще в использовании.Оригинал: https://medium.com/flutter-community/announcing-fic-fast-immutable-collections-5eb091d1e31fМассивы, к которым вы, возможно, привыкли в других языках, в Dart называются списками (List), и они изменяемые по умолчанию - вы можете добавлять в них новые элементы, удалять и т.д.
var list = [1, 2];
list.add(3); // list: [1, 2, 3].
Существует способ создать неизменяемый список с помощью List.unmodifiable, список, по прежнему, будет иметь метод add, который выдаст ошибку во время исполнения, при попытке данный метод вызвать:
var list = List.unmodifiable([1, 2]);
list.add(3); // Ошибка во время выполнения программы.
Однако можно делать изменения в копии такого списка:
var list = List.unmodifiable([1, 2]); // Этот список нельзя изменять.
var newList = list.toList()..add(3);
print(newList); // [1, 2, 3].
Есть способ лучшеКак вы поняли, обычный List можно использовать как неизменяемый, но при этом приходится писать шаблонный код, его становится трудно читать. Существует другой, более хороший способ: использование IList вместо List. IList неизменяемый - неизменяемый список, с простым API для использования.Чтобы создать IList вы можете просто использовать extension-метод lock над обычным List:
IList<int> iList = [1, 2].lock;
Изменить содержимое IList не получится. Метод add будет возвращать новый IList с добавленным элементом:
var myList = [1, 2].lock; // Его изменить не получится.
var newList = myList.add(3));
print(myList); // [1, 2].
print(newList); // [1, 2, 3].
FICПакет FIC (Fast Immutable Collections, Быстрые неизменяемые коллекции) предоставляет неизменяемые списки. FIC - конкурент для таких пакетов как built_collection и kt_dart, но он намного быстрее и проще в использовании.По ссылке https://pub.dev/packages/fast_immutable_collections Вы можете посмотреть сравнения по скорости с альтернативными пакетами. Иногда FIC даже быстрее, чем родные коллекции в Dart:
Время, требуемое для добавления 1 000 элементов в список из 10 000 элементов. Чем меньше, тем лучшеИспользованиеНеизменяемые коллекции имеют имена IList, ISet и IMap. Чтобы создать неизменяемую коллекцию, Вы просто можете "заблокировать" изменяемую:
IList<int> iList = [1, 2].lock;
ISet<int> iSet = {1, 2}.lock;
IMap<String, int> iMap = {"a": 1, "b": 2}.lock;
Любой Iterable также может быть заблокирован в неизменяемый список(List) или набор(Set) с помощью toIList() и toISet() соответственно, или используя конструкторы:
IList<int> iList = myIterable.toIList();
ISet<int> iSet = myIterable.toISet();
// С помощью конструкторов:
IList<int> iList = IList(myIterable);
ISet<int> iSet = ISet(myIterable);
Также можно "разблокировать" неизменяемые коллекции и получить изменяемые:
List<int> list = iList.unlock;
Set<int> set = iSet.unlock;
Map<String, int> map = iMap.unlock;
// Работает и это:
List<int> list = iList.toList();
Set<int> set = iSet.toSet();
// Работает и это:
List<int> list = List.of(iList);
Set<int> set = Set.of(iSet);
Но помните, что те методы, которые изменяют содержимое неизменяемых коллекций возвращают коллекции с новым содержанием. К примеру:
var iList1 = [1, 2].lock;          
var iList2 = iList1.add(3); // [1, 2, 3].
var iList3 = iList2.remove(2); // [1, 3].         
print(iList1); // Все еще [1, 2].
Благодаря этому методы можно выстраивать в цепочку:
var iList = [1, 2, 3].lock.add(4).remove(2); // [1, 3, 4].
РавенствоПо умолчанию, FIC равны, если их содержимое одинаковое и находится в одном порядке:
var iList1 = [1, 2].lock;
var iList2 = [1, 2].lock;
print(identical(iList1, iList2)); // false.
print(iList1 == iList2); // true.
Это является полной противоположностью для обычных списков(List), которые сравниваются по идентичности:
var list1 = [1, 2];
var list2 = [1, 2];
var list3 = list1;
// Обычные списки(List) сравниваются по идентичности:
print(identical(list1, list2)); // false.
print(identical(list1, list3)); // true.
print(list1 == list2); // false.
// В то время как ILists сравниваются по содержимому:
print(list1.lock == list2.lock); // true.
Однако, IList является настраиваемым. Вы можете создать IList, который будет сравниваться по идентичности:
// Эти ILists сравниваются по содержимому:
var iList1 = [1, 2].lock;
var iList2 = [1, 2].lock;
print(iList1 == iList2); // true.
// Теперь эти же ILists сравниваются по идентичности:
var iList3 = [1, 2].lock.withIdentityEquals;
var iList4 = [1, 2].lock.withIdentityEquals;
print(iList3 == iList4); // false.
СортировкаПорядок объектов в ISet и IMap может быть и тем, который Вы изначально ввели, а может быть и отсортирован в зависимости от конфигурации:
var iSet = {2, 4, 1, 9, 3}.lock;  
print(iSet.join(", ")); // [2, 4, 1, 9, 3].
var iSet = {2, 4, 1, 9, 3}.lock.withConfig(ConfigSet(sort: true));
print(iSet.join(", ")); // [1, 2, 3, 4, 9].
IMapOfSetsПри блокировке Map<K, V>, Вы получаете IMap<K, V>.Однако заблокированная Map<K, Set<V>> становится IMapOfSets<K, V>:
// Map в IMap.
IMap<K, V> map = {'a': 1, 'b': 2}.lock;
// Map в IMapOfSets.
IMapOfSets<K, V> map = {'a': {1, 2}, 'b': {3, 4}}.lock;
"Map of sets" - это вид мультисловаря(multimap). IMapOfSets позволяет добавлять и удалять объекты, не думая о наборах(sets), которые содержатся внутри.К примеру:
IMapOfSets<K, V> map = {'a': {1, 2}, 'b': {3, 4}}.lock;
print(map.add('a', 3)); // {'a': {1, 2, 3}, 'b': {3, 4}}.
По этой ссылке можно найти пример класса, называющийся StudentsPerCourse, который распределяет студентов по курсам. Каждый студент может быть записан в один или несколько курсов. Такую модель можно получить с помощью словаря(map), в котором ключами будут курсы, а значениями - наборы из студентов.ListSetНесмотря на свое название, FIC предлагает и изменяемые типы. К примеру, ListSet сразу же:
  • Изменяемый, упорядоченный набор(Set) фиксированного размера.
  • Изменяемый список(List) фиксированного размера, в котором значения не повторяются:
ListSet<int> listSet = ListSet.of([1, 2, 3]);
expect(listSet[2], 3);
expect(listSet.contains(2), isTrue);
List<int> list = listSet;
Set<int> set = listSet;
expect(list[2], 3);
expect(set.contains(2), isTrue);
Если рассматривать ListSet как Set и сравнивать с LinkedHashSet, то ListSet также является упорядоченным и имеет схожую производительность. Но ListSet занимает меньше места в памяти и может быть отсортирован, так же как и List. Также, у Вас есть доступ к его элемента по индексу за константное время.Минусом, конечно же, является, что ListSet имеет фиксированный размер, а LinkedHashSet - нет. ListSet эффективен и как List, и как Set. Поэтому, к примеру, у него есть эффективный sort метод, в то время как LinkedHashSet требует конвертации в List, сортировки, а затем обратного преобразования в Set.Расширения, хелперы и компараторыFIC также предоставляет:Iterable хелперы и расширения:
  • combineIterables - высокоуровневая функция, которая объединяет два Iterable в один.
  • Iterable.isNullOrEmpty, Iterable.isNotNullOrEmpty и Iterable.isEmptyButNotNull.
  • Iterable.deepEquals сравнивает два объекта по порядку с помощью оператора ==.
  • Iterable.deepEqualsByIdentity сравнивает все объекты по порядку с помощью identical.
  • Iterable.findDuplicates ищет повторяющиеся значения и возвращает Set с дубликатами.
  • Iterable.removeNulls убирает все объекты, равные null, из Iterable.
  • Iterable.removeDuplicates убирает все повторяющиеся объекты. Дополнительно, можно использоваться by функцию для сравнения объектов. Если добавить аргумент removeNulls равное true, то уберутся и null-объекты.
  • Iterable.sortedLike возвращается список, отсортированный в соответствии с Iterable сортировки. Объекты, которых нет в сортировочном Iterable, встанут в конец.
Расширения над List:
  • List.sortOrdered похож на метод sort, но использует сортировку слиянием(merge sort). В противовес sort, orderedSort стабильный, что означает, что различные объекты, которые сравниваются как равные, остаются в начальном порядке.
  • List.sortLike сортирует список в соответствии с ordering Iterable. Объекты, которых нет в ordering, встанут в конец в определенном порядке.
  • List.moveToTheFront перемещает первое вхождение элемента в начало списка.
  • List.moveToTheEnd перемещает первое вхождение элемента в конец списка.
  • List.whereMoveToTheFront перемещает все элементы, которые удовлетворяют предоставленным требованиям, в начало списка.
  • List.whereMoveToTheEnd перемещает все элементы, которые удовлетворяют предоставленным требованиям, в конец списка.
  • List.toggle Если элемента нет в списке, добавляет его и возвращает true. Если уже есть, то удаляет первый необходимый и возвращает false.
  • List.compareAsSets возвращает true если в списке есть требуемые элементы (в любом порядке). Не берутся во внимание повторяющиеся элементы.
  • List.mapIndexed преобразует каждый элемент списка. Функция принимает изначальный элемент и его индекс.
  • List.splitList убирает элементы из списка, которые удовлетворяют условию.
  • List.divideList возвращает несколько списков, разделенных по выбранным элементам.
  • List.addBetween возвращает новый список, добавив разделение между изначальными элементами.
  • List.concat возвращает эффективное слияние до 5 списков.
  • List.splitByLength делит список на один или несколько списков с максимальным количеством элементов length.
  • List.update возвращает список, в котором новые элементы добавляются или обновляются в зависимости от порядкового номера.
  • List.distinct удаляет повторяющиеся объекты, оставляя только уникальные.
  • List.reversedView возвращает список объектов в обратном порядке.
Расширения над Set:
  • Set.toggle Если объекта нет в Set, то он добавляется и возвращается true. Иначе, если объект уже есть в Set, то он удаляется и возвращается false.
Расширения над Iterator:
  • toIterable, toList, toSet, toIList, и toISet преобразуют Iterator в Iterable, List, Set, IList, и ISet, соответственно.
Расширения над Boolean:
  • compareTo делает true > false.
Компараторы
  • compareObject
  • compareObjectTo
  • sortBy
  • sortLike
  • if0
Пакет разработан Philippe Fanaro и Marcelo Glasberg.Другие Flutter пакеты от автора: https://github.com/marcglasberghttps://twitter.com/GlasbergMarceloЧитайте сообщество Flutter в Twitter: https://www.twitter.com/FlutterComm
===========
Источник:
habr.com
===========

===========
Автор оригинала: Philippe Fanaro, Marcelo Glasberg
===========
Похожие новости: Теги для поиска: #_flutter, #_flutter, #_blog_kompanii_rosselhozbank (
Блог компании Россельхозбанк
)
, #_flutter
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 22-Ноя 23:18
Часовой пояс: UTC + 5