| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of dart.collection; | 5 part of dart.collection; |
| 6 | 6 |
| 7 | |
| 8 /** | 7 /** |
| 9 * A specialized double-linked list of elements that extends [LinkedListEntry]. | 8 * A specialized double-linked list of elements that extends [LinkedListEntry]. |
| 10 * | 9 * |
| 11 * This is not a generic data structure. It only accepts elements that extend | 10 * This is not a generic data structure. It only accepts elements that extend |
| 12 * the [LinkedListEntry] class. See the [Queue] implementations for | 11 * the [LinkedListEntry] class. See the [Queue] implementations for |
| 13 * generic collections that allow constant time adding and removing at the ends. | 12 * generic collections that allow constant time adding and removing at the ends. |
| 14 * | 13 * |
| 15 * This is not a [List] implementation. Despite its name, this class does not | 14 * This is not a [List] implementation. Despite its name, this class does not |
| 16 * implement the [List] interface. It does not allow constant time lookup by | 15 * implement the [List] interface. It does not allow constant time lookup by |
| 17 * index. | 16 * index. |
| 18 * | 17 * |
| 19 * Because the elements themselves contain the links of this linked list, | 18 * Because the elements themselves contain the links of this linked list, |
| 20 * each element can be in only one list at a time. To add an element to another | 19 * each element can be in only one list at a time. To add an element to another |
| 21 * list, it must first be removed from its current list (if any). | 20 * list, it must first be removed from its current list (if any). |
| 22 * | 21 * |
| 23 * In return, each element knows its own place in the linked list, as well as | 22 * In return, each element knows its own place in the linked list, as well as |
| 24 * which list it is in. This allows constant time [LinkedListEntry.addAfter], | 23 * which list it is in. This allows constant time [LinkedListEntry.addAfter], |
| 25 * [LinkedListEntry.addBefore] and [LinkedListEntry.unlink] operations | 24 * [LinkedListEntry.addBefore] and [LinkedListEntry.unlink] operations |
| 26 * when all you have is the element. | 25 * when all you have is the element. |
| 27 * | 26 * |
| 28 * A `LinkedList` also allows constant time adding and removing at either end, | 27 * A `LinkedList` also allows constant time adding and removing at either end, |
| 29 * and a constant time length getter. | 28 * and a constant time length getter. |
| 30 */ | 29 */ |
| 31 class LinkedList<E extends LinkedListEntry<E>> | 30 class LinkedList<E extends LinkedListEntry<E>> extends Iterable<E> { |
| 32 extends Iterable<E> { | |
| 33 | |
| 34 int _modificationCount = 0; | 31 int _modificationCount = 0; |
| 35 int _length = 0; | 32 int _length = 0; |
| 36 E _first; | 33 E _first; |
| 37 | 34 |
| 38 /** | 35 /** |
| 39 * Construct a new empty linked list. | 36 * Construct a new empty linked list. |
| 40 */ | 37 */ |
| 41 LinkedList(); | 38 LinkedList(); |
| 42 | 39 |
| 43 /** | 40 /** |
| (...skipping 21 matching lines...) Expand all Loading... |
| 65 /** | 62 /** |
| 66 * Remove [entry] from the linked list. | 63 * Remove [entry] from the linked list. |
| 67 * | 64 * |
| 68 * Returns false and does nothing if [entry] is not in this linked list. | 65 * Returns false and does nothing if [entry] is not in this linked list. |
| 69 * | 66 * |
| 70 * This is equivalent to calling `entry.unlink()` if the entry is in this | 67 * This is equivalent to calling `entry.unlink()` if the entry is in this |
| 71 * list. | 68 * list. |
| 72 */ | 69 */ |
| 73 bool remove(E entry) { | 70 bool remove(E entry) { |
| 74 if (entry._list != this) return false; | 71 if (entry._list != this) return false; |
| 75 _unlink(entry); // Unlink will decrement length. | 72 _unlink(entry); // Unlink will decrement length. |
| 76 return true; | 73 return true; |
| 77 } | 74 } |
| 78 | 75 |
| 79 Iterator<E> get iterator => new _LinkedListIterator<E>(this); | 76 Iterator<E> get iterator => new _LinkedListIterator<E>(this); |
| 80 | 77 |
| 81 int get length => _length; | 78 int get length => _length; |
| 82 | 79 |
| 83 /** | 80 /** |
| 84 * Remove all elements from this linked list. | 81 * Remove all elements from this linked list. |
| 85 */ | 82 */ |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 } | 139 } |
| 143 | 140 |
| 144 bool get isEmpty => _length == 0; | 141 bool get isEmpty => _length == 0; |
| 145 | 142 |
| 146 /// Inserts [newEntry] as last entry of the list. | 143 /// Inserts [newEntry] as last entry of the list. |
| 147 /// | 144 /// |
| 148 /// If [updateFirst] is true and [entry] is the first entry in the list, | 145 /// If [updateFirst] is true and [entry] is the first entry in the list, |
| 149 /// updates the [_first] field to point to the [newEntry] as first entry. | 146 /// updates the [_first] field to point to the [newEntry] as first entry. |
| 150 void _insertBefore(E entry, E newEntry, {bool updateFirst}) { | 147 void _insertBefore(E entry, E newEntry, {bool updateFirst}) { |
| 151 if (newEntry.list != null) { | 148 if (newEntry.list != null) { |
| 152 throw new StateError( | 149 throw new StateError('LinkedListEntry is already in a LinkedList'); |
| 153 'LinkedListEntry is already in a LinkedList'); | |
| 154 } | 150 } |
| 155 _modificationCount++; | 151 _modificationCount++; |
| 156 | 152 |
| 157 newEntry._list = this; | 153 newEntry._list = this; |
| 158 if (isEmpty) { | 154 if (isEmpty) { |
| 159 assert(entry == null); | 155 assert(entry == null); |
| 160 newEntry._previous = newEntry._next = newEntry; | 156 newEntry._previous = newEntry._next = newEntry; |
| 161 _first = newEntry; | 157 _first = newEntry; |
| 162 _length++; | 158 _length++; |
| 163 return; | 159 return; |
| (...skipping 17 matching lines...) Expand all Loading... |
| 181 _length--; | 177 _length--; |
| 182 entry._list = entry._next = entry._previous = null; | 178 entry._list = entry._next = entry._previous = null; |
| 183 if (isEmpty) { | 179 if (isEmpty) { |
| 184 _first = null; | 180 _first = null; |
| 185 } else if (identical(entry, _first)) { | 181 } else if (identical(entry, _first)) { |
| 186 _first = next; | 182 _first = next; |
| 187 } | 183 } |
| 188 } | 184 } |
| 189 } | 185 } |
| 190 | 186 |
| 191 | 187 class _LinkedListIterator<E extends LinkedListEntry<E>> implements Iterator<E> { |
| 192 class _LinkedListIterator<E extends LinkedListEntry<E>> | |
| 193 implements Iterator<E> { | |
| 194 final LinkedList<E> _list; | 188 final LinkedList<E> _list; |
| 195 final int _modificationCount; | 189 final int _modificationCount; |
| 196 E _current; | 190 E _current; |
| 197 LinkedListEntry<E> _next; | 191 LinkedListEntry<E> _next; |
| 198 bool _visitedFirst; | 192 bool _visitedFirst; |
| 199 | 193 |
| 200 _LinkedListIterator(LinkedList<E> list) | 194 _LinkedListIterator(LinkedList<E> list) |
| 201 : _list = list, | 195 : _list = list, |
| 202 _modificationCount = list._modificationCount, | 196 _modificationCount = list._modificationCount, |
| 203 _next = list._first, | 197 _next = list._first, |
| 204 _visitedFirst = false; | 198 _visitedFirst = false; |
| 205 | 199 |
| 206 E get current => _current; | 200 E get current => _current; |
| 207 | 201 |
| 208 bool moveNext() { | 202 bool moveNext() { |
| 209 if (_modificationCount != _list._modificationCount) { | 203 if (_modificationCount != _list._modificationCount) { |
| 210 throw new ConcurrentModificationError(this); | 204 throw new ConcurrentModificationError(this); |
| 211 } | 205 } |
| 212 if (_list.isEmpty || | 206 if (_list.isEmpty || (_visitedFirst && identical(_next, _list.first))) { |
| 213 (_visitedFirst && identical(_next, _list.first))) { | |
| 214 _current = null; | 207 _current = null; |
| 215 return false; | 208 return false; |
| 216 } | 209 } |
| 217 _visitedFirst = true; | 210 _visitedFirst = true; |
| 218 _current = _next; | 211 _current = _next; |
| 219 _next = _next._next; | 212 _next = _next._next; |
| 220 return true; | 213 return true; |
| 221 } | 214 } |
| 222 } | 215 } |
| 223 | 216 |
| 224 | |
| 225 /** | 217 /** |
| 226 * An object that can be an element in a [LinkedList]. | 218 * An object that can be an element in a [LinkedList]. |
| 227 * | 219 * |
| 228 * All elements of a `LinkedList` must extend this class. | 220 * All elements of a `LinkedList` must extend this class. |
| 229 * The class provides the internal links that link elements together | 221 * The class provides the internal links that link elements together |
| 230 * in the `LinkedList`, and a reference to the linked list itself | 222 * in the `LinkedList`, and a reference to the linked list itself |
| 231 * that an element is currently part of. | 223 * that an element is currently part of. |
| 232 * | 224 * |
| 233 * An entry can be in at most one linked list at a time. | 225 * An entry can be in at most one linked list at a time. |
| 234 * While an entry is in a linked list, the [list] property points to that | 226 * While an entry is in a linked list, the [list] property points to that |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 /** | 284 /** |
| 293 * Insert an element before this element in this element's linked list. | 285 * Insert an element before this element in this element's linked list. |
| 294 * | 286 * |
| 295 * This entry must be in a linked list when this method is called. | 287 * This entry must be in a linked list when this method is called. |
| 296 * The [entry] must not be in a linked list. | 288 * The [entry] must not be in a linked list. |
| 297 */ | 289 */ |
| 298 void insertBefore(E entry) { | 290 void insertBefore(E entry) { |
| 299 _list._insertBefore(this as dynamic/*=E*/, entry, updateFirst: true); | 291 _list._insertBefore(this as dynamic/*=E*/, entry, updateFirst: true); |
| 300 } | 292 } |
| 301 } | 293 } |
| OLD | NEW |