Built Collections for Dart #
Built Collections are immutable collections using the builder pattern.
Each of the core SDK collections is split in two: a mutable builder class and an immutable "built" class. Builders are for computation, "built" classes are for safely sharing with no need to copy defensively.
Immutable collections work particularly well with immutable values. See built_value.
You can read more about built_collection on medium.
- are immutable, if the elements/keys/values used are immutable;
- are comparable;
- are hashable;
- reject nulls;
- require generic type parameters;
- reject wrong-type elements;
- use copy-on-write to avoid copying unnecessarily.
See below for details on each of these points.
A note about strong mode #
Please note that from version
1.1.0 built_collection must be used in
to get all the type guarantees. That is, your project must have no warnings or
errors when analyzed with the strong mode analyzer. This allows some runtime
checks to be skipped because the equivalent check can be done statically.
Recommended Style #
A project can benefit greatly from using Built Collections throughout. Methods that will not mutate a collection can accept the "built" version, making it clear that no mutation will happen and completely avoiding the need for defensive copying.
For code that is public to other projects or teams not using
Built Collections, prefer to accept
Iterable where possible. That way
your code is compatible with SDK collections, Built Collections and any
other collection implementation that builds on
It's okay to accept
Map if needed. Built Collections
provide efficient conversion to their SDK counterparts via
Built Collections are Immutable #
Built Collections do not offer any methods that modify the collection. In
order to make changes, first call
toBuilder to get a mutable builder.
In particular, Built Collections do not implement or extend their mutable
Iterable, but not
Iterable, but not
BuiltSetMultimap share no interface with the SDK collections.
Built Collections can contain mutable elements. However, this use is not recommended, as mutations to the elements will break comparison and hashing.
Built Collections are Comparable #
Core SDK collections do not offer equality checks by default.
Built Collections do a deep comparison against other Built Collections of the same type, only. Hashing is used to make repeated comparisons fast.
Built Collections are Hashable #
Core SDK collections do not compute a deep hashCode.
Built Collections do compute, and cache, a deep hashCode. That means they can be stored inside collections that need hashing, such as hash sets and hash maps. They also use the cached hash code to speed up repeated comparisons.
Built Collections Reject Nulls #
null in a collection is usually a bug, so Built Collections and their
builders throw if given a
null element, key or value.
Built Collections Require Generic Type Parameters #
List<dynamic> is error-prone because it can be assigned to a
any type without warning. So, all Built Collections must be created with
explicit element, key or value types.
Built Collections Reject Wrong-type Elements, Keys and Values #
Collections that happen to contain elements, keys or values that are not of the right type can lead to difficult-to-find bugs. So, all Built Collections and their builders are aggressive about validating types, even with checked mode disabled.
Built Collections Avoid Copying Unnecessarily #
Built Collections and their builder and helper types collaborate to avoid copying unless it's necessary.
BuiltSetMultimap.toMap do not make
a copy, but return a copy-on-write wrapper. So, Built Collections can be
efficiently and easily used with code that needs core SDK collections but
does not mutate them.
When you want to provide a collection that explicitly throws when a
mutation is attempted, use
Features and bugs #
Please file feature requests and bugs at the issue tracker.
- Add extensions methods:
Iterable.toBuiltSet. Requires SDK 2.6.0.
- Cleanup: remove unnecessary
- Bug fix:
ListMultimapBuilder.no longer ignores modifications under some circumstances.
- Bug fix:
lastsetters can no longer modify the underlying collection.
- Add benchmark for VM and dart2js.
- Stop doing explicit type checks on elements; in Dart 2 these are implied.
- Modify methods on
Iterableelements so they only iterate over the iterable once. Improves performance when the iterable are slow/lazy.
- Add return val to
and add return values to
- Many changes following Dart 2 improvements to collections:
- Remove obsolete
ListBuildersetters and getters:
- Implement Dart 2 methods in internal collections used by
fromconstructors, like the current constructors, take collections of any type and check each element. The
ofconstructors, like the SDK
ofconstructors, take a collection of the correct type. This means they can be used for type inference, allowing you to omit the explicit type.
removeLastmethods on builders return values like their SDK collection equivalents.
- Add length, isEmpty and isNotEmpty to ListBuilder, MapBuilder and SetBuilder
- Allow SDK 2.0.0.
- Allow quiver 2.0.0, use test version 1.
- Allow quiver 0.29.
- Type fixes for DDC. Stop using a
- Tweaks to tests.
- Allow quiver 0.28.
- Stop using
Mapfactories. It causes problems for the analyzer when using a pre-Dart-2 SDK.
- Improve package description.
- Prepare for Dart 2; add methods that will appear in
- Allow quiver 0.27.
- Revert changes for Dart 2; they will be re-released as v3.0.0 as they are break libraries that provide their own implementations of built collections.
- Fix changes for Dart 2.
- Prepare for Dart 2; add methods that will appear in
BuiltMapnow allow you to specify the underlying collection type. For example, you can construct a
SplayTreeSet. This results in a set that is always in sorted order instead of preserving insertion order. Another useful possibility is to use a
HashSet, which leads to a random order but improves performance over the default. See
- Split collection classes into abstract interfaces and concrete, private,
implementations. This allows new implementations of the interfaces. Note that
this change is invisible unless you rely on the exact
runtimeTypeof the collections.
- Fix a bug whereby
MapBuilderallowed nulls to be introduced via
- Allow quiver 0.26.
- The addIterable method is now generic. This allows the types of the functions passed in to be inferred.
- Add BuiltIterable interface for when you want to accept a BuiltList or BuiltSet.
- Use real generic syntax, drop comment-based syntax.
- Add operator to ListBuilder and MapBuilder for easier inline updates.
- Allow quiver 0.25.
- Widen parameter of BuiltSet.difference and BuiltSet.intersection to
BuiltSet<Object>to match Set.
- Update for Set.difference change in SDK 1.21.0.
asSetto the built collection classes.
- Remove runtime checks that are unnecessary if the project using
built_collection is "strong mode clean", that is, if it has no errors with
strong mode. See note in
README.mdabout strong mode.
- Allow quiver 0.23.
- Strong mode clean.
- Add reference identity check to equals operators.
- Fix factories when iterable generic type is subtype of requested type.
- Add generic type information to map, fold and expand methods.
- Make map operator take Object instead of K, as SDK collections do.
- Fix toString for result of toList, toSet, toMap.
- Fix missing generics on some return types.
- Fix BuiltList and BuiltSet "contains" method, should take Object, not E.
- Add removeAll and retainAll methods to SetBuilder.
- Add BuiltList.toBuiltSet() and BuiltSet.toBuiltList().
- Add addIterable methods to Map and Multimap builders.
- Add BuiltSetMultimap.
- Fix "part of" statement.
- Bug fix: fix Iterable "update in place" methods of BuiltList and BuiltSet so they discard original list or set.
- Make keys and values stable for BuiltMap and BuiltMultimap.
- Make repeated builds return identical instances for BuiltList, BuiltMap, BuiltSet.
- Add 'replace' methods.
- Add BuiltListMultimap.
- Fix comments.
- Add build and rebuild methods to BuiltList, BuiltMap, BuiltSet.
- Add update methods to ListBuilder, MapBuilder, SetBuilder.
- Initial version.
Use this package as a library
1. Depend on it
Add this to your package's pubspec.yaml file:
dependencies: built_collection: ^4.3.0
2. Install it
You can install packages from the command line:
$ pub get
$ flutter pub get
Alternatively, your editor might support
pub get or
flutter pub get.
Check the docs for your editor to learn more.
3. Import it
Now in your Dart code, you can use:
Describes how popular the package is relative to other packages. [more]
Code health derived from static analysis. [more]
Reflects how tidy and up-to-date the package is. [more]
Weighted score of the above. [more]
We analyzed this package on Nov 21, 2019, and provided a score, details, and suggestions below. Analysis was completed with status completed using:
- Dart: 2.6.1
- pana: 0.12.21
Detected platforms: Flutter, web, other
No platform restriction found in primary library
Maintain an example. (-10 points)
Create a short demo in the
example/ directory to show how to use this package.
Common filename patterns include
built_collection.dart. Packages with multiple examples should provide
For more information see the pub package layout conventions.