observer_list.dart 1.46 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:collection';

/// A list optimized for containment queries.
///
/// Consider using an [ObserverList] instead of a [List] when the number of
/// [contains] calls dominates the number of [add] and [remove] calls.
11 12
// TODO(ianh): Use DelegatingIterable, possibly moving it from the collection
// package to foundation, or to dart:collection.
13
class ObserverList<T> extends Iterable<T> {
14
  final List<T> _list = <T>[];
15 16 17 18 19 20 21 22 23 24 25
  bool _isDirty = false;
  HashSet<T> _set;

  /// Adds an item to the end of this list.
  void add(T item) {
    _isDirty = true;
    _list.add(item);
  }

  /// Removes an item from the list.
  ///
26 27
  /// This is O(N) in the number of items in the list.
  ///
28 29 30 31 32 33 34
  /// Returns whether the item was present in the list.
  bool remove(T item) {
    _isDirty = true;
    return _list.remove(item);
  }

  @override
35
  bool contains(Object element) {
36
    if (_list.length < 3)
37
      return _list.contains(element);
38 39 40

    if (_isDirty) {
      if (_set == null) {
41
        _set = HashSet<T>.from(_list);
42 43 44 45 46 47 48
      } else {
        _set.clear();
        _set.addAll(_list);
      }
      _isDirty = false;
    }

49
    return _set.contains(element);
50 51 52 53
  }

  @override
  Iterator<T> get iterator => _list.iterator;
54 55 56 57 58 59

  @override
  bool get isEmpty => _list.isEmpty;

  @override
  bool get isNotEmpty => _list.isNotEmpty;
60
}