OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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.core; | 5 part of dart.core; |
6 | 6 |
7 /** | 7 /** |
8 * A [List] is an indexable collection with a length. It can be of | 8 * A [List] is an indexable collection with a length. It can be of |
9 * fixed size or extendable. | 9 * fixed size or extendable. |
10 */ | 10 */ |
11 abstract class List<E> implements Collection<E>, Sequence<E> { | 11 abstract class List<E> implements Collection<E> { |
12 /** | 12 /** |
13 * Creates a list of the given [length]. | 13 * Creates a list of the given [length]. |
14 * | 14 * |
15 * If no [length] argument is supplied an extendable list of | 15 * The length of the returned list is not fixed. |
16 * length 0 is created. | |
17 * | |
18 * If a [length] argument is supplied, a fixed size list of that | |
19 * length is created. | |
20 */ | 16 */ |
21 external factory List([int length]); | 17 external factory List([int length = 0]); |
22 | 18 |
23 /** | 19 /** |
24 * Creates a list with the elements of [other]. The order in | 20 * Creates a fixed-sized list of the given [length] where each entry is |
| 21 * filled with [fill]. |
| 22 */ |
| 23 external factory List.fixedLength(int length, {E fill: null}); |
| 24 |
| 25 /** |
| 26 * Creates an list of the given [length] where each entry is |
| 27 * filled with [fill]. |
| 28 * |
| 29 * The length of the returned list is not fixed. |
| 30 */ |
| 31 external factory List.filled(int length, E fill); |
| 32 |
| 33 /** |
| 34 * Creates an list with the elements of [other]. The order in |
25 * the list will be the order provided by the iterator of [other]. | 35 * the list will be the order provided by the iterator of [other]. |
| 36 * |
| 37 * The length of the returned list is not fixed. |
26 */ | 38 */ |
27 factory List.from(Iterable<E> other) { | 39 factory List.from(Iterable<E> other) { |
28 var list = new List<E>(); | 40 var list = new List<E>(); |
29 for (var e in other) { | 41 for (var e in other) { |
30 list.add(e); | 42 list.add(e); |
31 } | 43 } |
32 return list; | 44 return list; |
33 } | 45 } |
34 | 46 |
35 /** | 47 /** |
(...skipping 23 matching lines...) Expand all Loading... |
59 void add(E value); | 71 void add(E value); |
60 | 72 |
61 /** | 73 /** |
62 * Adds [value] at the end of the list, extending the length by | 74 * Adds [value] at the end of the list, extending the length by |
63 * one. Throws an [UnsupportedError] if the list is not | 75 * one. Throws an [UnsupportedError] if the list is not |
64 * extendable. | 76 * extendable. |
65 */ | 77 */ |
66 void addLast(E value); | 78 void addLast(E value); |
67 | 79 |
68 /** | 80 /** |
69 * Appends all elements of the [collection] to the end of this list. | 81 * Appends all elements of the [iterable] to the end of this list. |
70 * Extends the length of the list by the number of elements in [collection]. | 82 * Extends the length of the list by the number of elements in [iterable]. |
71 * Throws an [UnsupportedError] if this list is not | 83 * Throws an [UnsupportedError] if this list is not extensible. |
72 * extendable. | |
73 */ | 84 */ |
74 void addAll(Collection<E> collection); | 85 void addAll(Iterable<E> iterable); |
75 | 86 |
76 /** | 87 /** |
77 * Sorts the list according to the order specified by the [compare] function. | 88 * Sorts the list according to the order specified by the [compare] function. |
78 * | 89 * |
79 * The [compare] function must act as a [Comparator]. | 90 * The [compare] function must act as a [Comparator]. |
80 * The default [List] implementations use [Comparable.compare] if | 91 * The default [List] implementations use [Comparable.compare] if |
81 * [compare] is omitted. | 92 * [compare] is omitted. |
82 */ | 93 */ |
83 void sort([int compare(E a, E b)]); | 94 void sort([int compare(E a, E b)]); |
84 | 95 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 E removeAt(int index); | 138 E removeAt(int index); |
128 | 139 |
129 /** | 140 /** |
130 * Pops and returns the last element of the list. | 141 * Pops and returns the last element of the list. |
131 * Throws a [UnsupportedError] if the length of the | 142 * Throws a [UnsupportedError] if the length of the |
132 * list cannot be changed. | 143 * list cannot be changed. |
133 */ | 144 */ |
134 E removeLast(); | 145 E removeLast(); |
135 | 146 |
136 /** | 147 /** |
137 * Returns the first element of the list, or throws an out of bounds | |
138 * exception if the list is empty. | |
139 */ | |
140 E get first; | |
141 | |
142 /** | |
143 * Returns the last element of the list, or throws an out of bounds | |
144 * exception if the list is empty. | |
145 */ | |
146 E get last; | |
147 | |
148 /** | |
149 * Returns a new list containing [length] elements from the list, | 148 * Returns a new list containing [length] elements from the list, |
150 * starting at [start]. | 149 * starting at [start]. |
151 * Returns an empty list if [length] is 0. | 150 * Returns an empty list if [length] is 0. |
152 * Throws an [ArgumentError] if [length] is negative. | 151 * Throws an [ArgumentError] if [length] is negative. |
153 * Throws an [RangeError] if [start] or | 152 * Throws an [RangeError] if [start] or |
154 * [:start + length - 1:] are out of range. | 153 * [:start + length - 1:] are out of range. |
155 */ | 154 */ |
156 List<E> getRange(int start, int length); | 155 List<E> getRange(int start, int length); |
157 | 156 |
158 /** | 157 /** |
(...skipping 13 matching lines...) Expand all Loading... |
172 * not extendable. | 171 * not extendable. |
173 * If [length] is 0, this method does not do anything. | 172 * If [length] is 0, this method does not do anything. |
174 * Throws an [ArgumentError] if [length] is negative. | 173 * Throws an [ArgumentError] if [length] is negative. |
175 * Throws an [RangeError] if [start] or | 174 * Throws an [RangeError] if [start] or |
176 * [:start + length: - 1] are out of range. | 175 * [:start + length: - 1] are out of range. |
177 */ | 176 */ |
178 void removeRange(int start, int length); | 177 void removeRange(int start, int length); |
179 | 178 |
180 /** | 179 /** |
181 * Inserts a new range into the list, starting from [start] to | 180 * Inserts a new range into the list, starting from [start] to |
182 * [:start + length - 1:]. The entries are filled with [initialValue]. | 181 * [:start + length - 1:]. The entries are filled with [fill]. |
183 * Throws an [UnsupportedError] if the list is | 182 * Throws an [UnsupportedError] if the list is |
184 * not extendable. | 183 * not extendable. |
185 * If [length] is 0, this method does not do anything. | 184 * If [length] is 0, this method does not do anything. |
186 * If [start] is the length of the list, this method inserts the | 185 * If [start] is the length of the list, this method inserts the |
187 * range at the end of the list. | 186 * range at the end of the list. |
188 * Throws an [ArgumentError] if [length] is negative. | 187 * Throws an [ArgumentError] if [length] is negative. |
189 * Throws an [RangeError] if [start] is negative or if | 188 * Throws an [RangeError] if [start] is negative or if |
190 * [start] is greater than the length of the list. | 189 * [start] is greater than the length of the list. |
191 */ | 190 */ |
192 void insertRange(int start, int length, [E initialValue]); | 191 void insertRange(int start, int length, [E fill]); |
193 } | 192 } |
| 193 |
| 194 /** |
| 195 * An unmodifiable [List]. |
| 196 */ |
| 197 abstract class NonExtensibleListMixin<E> |
| 198 extends Iterable<E> implements List<E> { |
| 199 |
| 200 Iterator<E> get iterator => new ListIterator(this); |
| 201 |
| 202 void forEach(f(E element)) { |
| 203 for (int i = 0; i < this.length; i++) f(this[i]); |
| 204 } |
| 205 |
| 206 bool contains(E value) { |
| 207 for (int i = 0; i < length; i++) { |
| 208 if (this[i] == value) return true; |
| 209 } |
| 210 return false; |
| 211 } |
| 212 |
| 213 reduce(initialValue, combine(previousValue, E element)) { |
| 214 var value = initialValue; |
| 215 for (int i = 0; i < this.length; i++) { |
| 216 value = combine(value, this[i]); |
| 217 } |
| 218 return value; |
| 219 } |
| 220 |
| 221 bool every(bool f(E element)) { |
| 222 for (int i = 0; i < this.length; i++) { |
| 223 if (!f(this[i])) return false; |
| 224 } |
| 225 return true; |
| 226 } |
| 227 |
| 228 bool any(bool f(E element)) { |
| 229 for (int i = 0; i < this.length; i++) { |
| 230 if (f(this[i])) return true; |
| 231 } |
| 232 return false; |
| 233 } |
| 234 |
| 235 bool get isEmpty { |
| 236 return this.length == 0; |
| 237 } |
| 238 |
| 239 E elementAt(int index) { |
| 240 return this[index]; |
| 241 } |
| 242 |
| 243 int indexOf(E value, [int start = 0]) { |
| 244 for (int i = start; i < length; i++) { |
| 245 if (this[i] == value) return i; |
| 246 } |
| 247 return -1; |
| 248 } |
| 249 |
| 250 int lastIndexOf(E value, [int start]) { |
| 251 if (start == null) start = length - 1; |
| 252 for (int i = start; i >= 0; i--) { |
| 253 if (this[i] == value) return i; |
| 254 } |
| 255 return -1; |
| 256 } |
| 257 |
| 258 E get first { |
| 259 if (length > 0) return this[0]; |
| 260 throw new StateError("No elements"); |
| 261 } |
| 262 |
| 263 E get last { |
| 264 if (length > 0) return this[length - 1]; |
| 265 throw new StateError("No elements"); |
| 266 } |
| 267 |
| 268 E get single { |
| 269 if (length == 1) return this[0]; |
| 270 if (length == 0) throw new StateError("No elements"); |
| 271 throw new StateError("More than one element"); |
| 272 } |
| 273 |
| 274 List<E> getRange(int start, int length) { |
| 275 List<E> result = <E>[]; |
| 276 for (int i = 0; i < length; i++) { |
| 277 result.add(this[start + i]); |
| 278 } |
| 279 return result; |
| 280 } |
| 281 |
| 282 void operator []=(int index, E value) { |
| 283 throw new UnsupportedError( |
| 284 "Cannot modify an unmodifiable list"); |
| 285 } |
| 286 |
| 287 void set length(int newLength) { |
| 288 throw new UnsupportedError( |
| 289 "Cannot change the length of an unmodifiable list"); |
| 290 } |
| 291 |
| 292 void add(E value) { |
| 293 throw new UnsupportedError( |
| 294 "Cannot add to an unmodifiable list"); |
| 295 } |
| 296 |
| 297 void addLast(E value) { |
| 298 throw new UnsupportedError( |
| 299 "Cannot add to an unmodifiable list"); |
| 300 } |
| 301 |
| 302 void addAll(Iterable<E> iterable) { |
| 303 throw new UnsupportedError( |
| 304 "Cannot add to an unmodifiable list"); |
| 305 } |
| 306 |
| 307 void sort([Comparator<E> compare]) { |
| 308 throw new UnsupportedError( |
| 309 "Cannot modify an unmodifiable list"); |
| 310 } |
| 311 |
| 312 void clear() { |
| 313 throw new UnsupportedError( |
| 314 "Cannot clear an unmodifiable list"); |
| 315 } |
| 316 |
| 317 E removeAt(int index) { |
| 318 throw new UnsupportedError( |
| 319 "Cannot remove in an unmodifiable list"); |
| 320 } |
| 321 |
| 322 E removeLast() { |
| 323 throw new UnsupportedError( |
| 324 "Cannot remove in an unmodifiable list"); |
| 325 } |
| 326 |
| 327 void setRange(int start, int length, List<E> from, [int startFrom]) { |
| 328 throw new UnsupportedError( |
| 329 "Cannot modify an unmodifiable list"); |
| 330 } |
| 331 |
| 332 void removeRange(int start, int length) { |
| 333 throw new UnsupportedError( |
| 334 "Cannot remove in an unmodifiable list"); |
| 335 } |
| 336 |
| 337 void insertRange(int start, int length, [E initialValue]) { |
| 338 throw new UnsupportedError( |
| 339 "Cannot insert range in an unmodifiable list"); |
| 340 } |
| 341 } |
| 342 |
| 343 /** |
| 344 * Iterates over a [Sequence] in growing index order. |
| 345 */ |
| 346 class ListIterator<E> implements Iterator<E> { |
| 347 final List<E> _list; |
| 348 int _position; |
| 349 E _current; |
| 350 |
| 351 ListIterator(this._list) : _position = -1; |
| 352 |
| 353 bool moveNext() { |
| 354 int nextPosition = _position + 1; |
| 355 if (nextPosition < _list.length) { |
| 356 _current = _list[nextPosition]; |
| 357 _position = nextPosition; |
| 358 return true; |
| 359 } |
| 360 _position = _list.length; |
| 361 _current = null; |
| 362 return false; |
| 363 } |
| 364 |
| 365 E get current => _current; |
| 366 } |
| 367 |
| 368 class MappedList<S, T> extends NonExtensibleListMixin<T> { |
| 369 final List<S> _list; |
| 370 final _Transformation<S, T> _f; |
| 371 |
| 372 MappedList(this._list, T this._f(S element)); |
| 373 |
| 374 T operator[](int index) => _f(_list[index]); |
| 375 int get length => _list.length; |
| 376 } |
| 377 |
| 378 /** |
| 379 * An immutable view of a [List]. |
| 380 */ |
| 381 class ListView<E> extends NonExtensibleListMixin<E> { |
| 382 final List<E> _list; |
| 383 final int _offset; |
| 384 final int _length; |
| 385 |
| 386 /** |
| 387 * If the given length is `null` then the ListView's length is bound by |
| 388 * the backed [list]. |
| 389 */ |
| 390 ListView(List<E> list, this._offset, this._length) : _list = list { |
| 391 if (_offset is! int || _offset < 0) { |
| 392 throw new ArgumentError(_offset); |
| 393 } |
| 394 if (_length != null && |
| 395 (_length is! int || _length < 0)) { |
| 396 throw new ArgumentError(_length); |
| 397 } |
| 398 } |
| 399 |
| 400 int get length { |
| 401 int originalLength = _list.length; |
| 402 int skipLength = originalLength - _offset; |
| 403 if (skipLength < 0) return 0; |
| 404 if (_length == null || _length > skipLength) return skipLength; |
| 405 return _length; |
| 406 } |
| 407 |
| 408 E operator[](int index) { |
| 409 int skipIndex = index + _offset; |
| 410 if (index < 0 || |
| 411 (_length != null && index >= _length) || |
| 412 index + _offset >= _list.length) { |
| 413 throw new RangeError.value(index); |
| 414 } |
| 415 return _list[index + _offset]; |
| 416 } |
| 417 |
| 418 ListView<E> skip(int skipCount) { |
| 419 if (skipCount is! int || skipCount < 0) { |
| 420 throw new ArgumentError(skipCount); |
| 421 } |
| 422 return new ListView(_list, _offset + skipCount, _length); |
| 423 } |
| 424 |
| 425 ListView<E> take(int takeCount) { |
| 426 if (takeCount is! int || takeCount < 0) { |
| 427 throw new ArgumentError(takeCount); |
| 428 } |
| 429 int newLength = takeCount; |
| 430 if (_length != null && takeCount > _length) newLength = _length; |
| 431 return new ListView(_list, _offset, newLength); |
| 432 } |
| 433 } |
OLD | NEW |