|
1 " |
|
2 COPYRIGHT (c) 1989-93 by Claus Gittinger |
|
3 All Rights Reserved |
|
4 |
|
5 This software is furnished under a license and may be used |
|
6 only in accordance with the terms of that license and with the |
|
7 inclusion of the above copyright notice. This software may not |
|
8 be provided or otherwise made available to, or used by, any |
|
9 other person. No title to or ownership of the software is |
|
10 hereby transferred. |
|
11 " |
|
12 |
|
13 Object subclass:#Collection |
|
14 instanceVariableNames:'' |
|
15 classVariableNames:'' |
|
16 poolDictionaries:'' |
|
17 category:'Collections-Abstract' |
|
18 ! |
|
19 |
|
20 Collection comment:' |
|
21 |
|
22 COPYRIGHT (c) 1989-93 by Claus Gittinger |
|
23 All Rights Reserved |
|
24 |
|
25 Abstract superclass for all collections |
|
26 |
|
27 %W% %E% |
|
28 '! |
|
29 |
|
30 !Collection class methodsFor:'instance creation'! |
|
31 |
|
32 with:anObject |
|
33 "return a new Collection with one element:anObject" |
|
34 |
|
35 |newCollection| |
|
36 |
|
37 newCollection := self new. |
|
38 newCollection add:anObject. |
|
39 ^ newCollection |
|
40 ! |
|
41 |
|
42 with:firstObject with:secondObject |
|
43 "return a new Collection with two elements:firstObject and secondObject" |
|
44 |
|
45 |newCollection| |
|
46 |
|
47 newCollection := self new. |
|
48 newCollection add:firstObject. |
|
49 newCollection add:secondObject. |
|
50 ^ newCollection |
|
51 ! |
|
52 |
|
53 with:firstObject with:secondObject with:thirdObject |
|
54 "return a new Collection with three elements" |
|
55 |
|
56 |newCollection| |
|
57 |
|
58 newCollection := self new. |
|
59 newCollection add:firstObject. |
|
60 newCollection add:secondObject. |
|
61 newCollection add:thirdObject. |
|
62 ^ newCollection |
|
63 ! |
|
64 |
|
65 with:firstObject with:secondObject with:thirdObject with:fourthObject |
|
66 "return a new Collection with four elements" |
|
67 |
|
68 |newCollection| |
|
69 |
|
70 newCollection := self new. |
|
71 newCollection add:firstObject. |
|
72 newCollection add:secondObject. |
|
73 newCollection add:thirdObject. |
|
74 newCollection add:fourthObject. |
|
75 ^ newCollection |
|
76 ! |
|
77 |
|
78 new:size withAll:element |
|
79 "return a new COllection of size, where all elements are |
|
80 initialized to element" |
|
81 |
|
82 |newCollection| |
|
83 |
|
84 newCollection := self new:size. |
|
85 size timesRepeat:[newCollection add:element] |
|
86 ! |
|
87 |
|
88 withAll:aCollection |
|
89 "return a new Collection with all elements taken from the argument, |
|
90 aCollection" |
|
91 |
|
92 |newCollection| |
|
93 |
|
94 newCollection := self new. |
|
95 newCollection addAll:aCollection. |
|
96 ^newCollection |
|
97 ! ! |
|
98 |
|
99 !Collection methodsFor:'error handling'! |
|
100 |
|
101 errorNotFound |
|
102 "report an error that Object was not in the collection" |
|
103 |
|
104 self error:'Object is not in the Collection' |
|
105 ! |
|
106 |
|
107 errorNotKeyed |
|
108 "report an error that keyed access methods are not allowed" |
|
109 |
|
110 self error:(self class name, 's do not respond to keyed accessing messages') |
|
111 ! ! |
|
112 |
|
113 !Collection methodsFor:'accessing'! |
|
114 |
|
115 anElement |
|
116 "return any element from the collection" |
|
117 |
|
118 self do: [:each | ^ each]. |
|
119 ^ nil |
|
120 ! ! |
|
121 |
|
122 !Collection methodsFor:'adding & removing'! |
|
123 |
|
124 add:anObject |
|
125 "add the argument, anObject to the receiver" |
|
126 |
|
127 ^ self subclassResponsibility |
|
128 ! |
|
129 |
|
130 addLast:anObject |
|
131 "add the argument, anObject to the receiver" |
|
132 |
|
133 ^ self add:anObject |
|
134 ! |
|
135 |
|
136 addAll:aCollection |
|
137 "add all elements of the argument, aCollection to the receiver" |
|
138 |
|
139 aCollection do:[:element | |
|
140 self add:element |
|
141 ]. |
|
142 ^ aCollection |
|
143 ! |
|
144 |
|
145 remove:anObject ifAbsent:exceptionBlock |
|
146 "remove the argument, anObject from the receiver - if it was not |
|
147 in the collection returns the the value of the exceptionBlock" |
|
148 |
|
149 ^ self subclassResponsibility |
|
150 ! |
|
151 |
|
152 remove:anObject |
|
153 "remove the argument, anObject from the receiver" |
|
154 |
|
155 self remove:anObject ifAbsent:[self errorNotFound] |
|
156 ! |
|
157 |
|
158 removeAll:aCollection |
|
159 "remove all elements of the argument, aCollection from the receiver" |
|
160 |
|
161 aCollection do:[:element | self remove:element]. |
|
162 ^ aCollection |
|
163 ! ! |
|
164 |
|
165 !Collection methodsFor:'growing'! |
|
166 |
|
167 growSize |
|
168 "return a suitable size increment for growing" |
|
169 |
|
170 ^ self size max:2 |
|
171 ! |
|
172 |
|
173 grow |
|
174 "make the receiver larger" |
|
175 |
|
176 self grow:(self size + self growSize) |
|
177 ! |
|
178 |
|
179 grow:howBig |
|
180 "change the receivers size" |
|
181 |
|
182 ^ self subclassResponsibility |
|
183 ! ! |
|
184 |
|
185 !Collection methodsFor:'testing'! |
|
186 |
|
187 isEmpty |
|
188 "return true, if the receiver is empty" |
|
189 |
|
190 ^ self size == 0 |
|
191 ! |
|
192 |
|
193 includes:anElement |
|
194 "return true, if the argument, anObject is in the list" |
|
195 |
|
196 self do:[:element | |
|
197 (anElement = element) ifTrue:[^ true]. |
|
198 ]. |
|
199 ^ false |
|
200 ! |
|
201 |
|
202 includesAll:aCollection |
|
203 "return true, if the the receiver includes all elements of |
|
204 the argument, aCollection; false if any is missing" |
|
205 |
|
206 aCollection do:[:element | |
|
207 (self includes:element) ifFalse:[^ false]. |
|
208 ]. |
|
209 ^ true |
|
210 ! |
|
211 |
|
212 occurrencesOf:anElement |
|
213 "return the number of occurrences of the argument, anElement in |
|
214 the receiver" |
|
215 |
|
216 |count "<SmallInteger>" | |
|
217 |
|
218 count := 0. |
|
219 self do:[:element | |
|
220 (anElement = element) ifTrue:[ |
|
221 count := count + 1 |
|
222 ]. |
|
223 ]. |
|
224 ^ count |
|
225 ! |
|
226 |
|
227 size |
|
228 "return the number of elements in the receiver" |
|
229 |
|
230 |count "<SmallInteger>" | |
|
231 |
|
232 count := 0. |
|
233 self do:[:element | |
|
234 count := count + 1 |
|
235 ]. |
|
236 ^ count |
|
237 ! ! |
|
238 |
|
239 !Collection methodsFor:'enumerating'! |
|
240 |
|
241 do:aBlock |
|
242 "evaluate the argument, aBlock for each element" |
|
243 |
|
244 ^ self subclassResponsibility |
|
245 ! |
|
246 |
|
247 collect:aBlock |
|
248 "for each element in the receiver, evaluate the argument, aBlock |
|
249 and return a new collection with the results" |
|
250 |
|
251 |newCollection| |
|
252 |
|
253 newCollection := self species new. |
|
254 self do:[:each | newCollection add:(aBlock value:each)]. |
|
255 ^ newCollection |
|
256 ! |
|
257 |
|
258 detect:aBlock |
|
259 "evaluate the argument, aBlock for each element in the receiver until |
|
260 the block returns true; in this case return the element which caused |
|
261 the true evaluation. |
|
262 If none of the evaluations return true, report an error" |
|
263 |
|
264 ^ self detect:aBlock ifNone:[self errorNotFound] |
|
265 ! |
|
266 |
|
267 detect:aBlock ifNone:exceptionBlock |
|
268 "evaluate the argument, aBlock for each element in the receiver until |
|
269 the block returns true; in this case return the element which caused |
|
270 the true evaluation. |
|
271 If none of the evaluations returns true, return the result of the |
|
272 evaluation of the exceptionBlock" |
|
273 |
|
274 self do:[:each | |
|
275 (aBlock value:each) ifTrue:[^ each]. |
|
276 ]. |
|
277 ^ exceptionBlock value |
|
278 ! |
|
279 |
|
280 inject:thisValue into:binaryBlock |
|
281 |nextValue| |
|
282 |
|
283 nextValue := thisValue. |
|
284 self do: [:each | nextValue := binaryBlock value:nextValue value:each]. |
|
285 ^ nextValue |
|
286 ! |
|
287 |
|
288 reject:aBlock |
|
289 "return a new collection with all elements from the receiver, for which |
|
290 the argument aBlock evaluates to false" |
|
291 |
|
292 ^ self select:[:element | (aBlock value:element) == false] |
|
293 ! |
|
294 |
|
295 select:aBlock |
|
296 "return a new collection with all elements from the receiver, for which |
|
297 the argument aBlock evaluates to true" |
|
298 |
|
299 |newCollection| |
|
300 |
|
301 newCollection := self species new. |
|
302 self do:[:each | |
|
303 (aBlock value:each) ifTrue:[newCollection add:each]. |
|
304 ]. |
|
305 ^ newCollection |
|
306 ! ! |
|
307 |
|
308 !Collection methodsFor:'converting'! |
|
309 |
|
310 asArray |
|
311 "return a new Array with the collections elements" |
|
312 |
|
313 |anArray |
|
314 index "<SmallInteger>" | |
|
315 |
|
316 anArray := Array new:(self size). |
|
317 index := 1. |
|
318 self do:[:each | |
|
319 anArray at:index put:each. |
|
320 index := index + 1 |
|
321 ]. |
|
322 ^ anArray |
|
323 ! |
|
324 |
|
325 asByteArray |
|
326 "return a new ByteArray with the collections elements" |
|
327 |
|
328 |aByteArray |
|
329 index "<SmallInteger>" | |
|
330 |
|
331 aByteArray := ByteArray new:(self size). |
|
332 index := 1. |
|
333 self do:[:each | |
|
334 aByteArray at:index put:each asInteger. |
|
335 index := index + 1 |
|
336 ]. |
|
337 ^ aByteArray |
|
338 ! |
|
339 |
|
340 asString |
|
341 "return a String with the collections elements |
|
342 (which must convertable to characters)" |
|
343 |
|
344 |aString |
|
345 index "<SmallInteger>" | |
|
346 |
|
347 aString := String new:(self size). |
|
348 index := 1. |
|
349 self do:[:each | |
|
350 aString at:index put:each asCharacter. |
|
351 index := index + 1 |
|
352 ]. |
|
353 ^ aString |
|
354 ! |
|
355 |
|
356 asText |
|
357 "return a new Text-object with the elements printstings" |
|
358 |
|
359 |aText |
|
360 index "<SmallInteger>" | |
|
361 |
|
362 aText := Text new:(self size). |
|
363 index := 1. |
|
364 self do:[:each | |
|
365 aText at:index put:(each printString). |
|
366 index := index + 1 |
|
367 ]. |
|
368 ^ aText |
|
369 ! |
|
370 |
|
371 asBag |
|
372 "return a new Bag with the receiver collections elements" |
|
373 |
|
374 |aBag| |
|
375 |
|
376 aBag := Bag new. |
|
377 self do:[:each | aBag add:each]. |
|
378 ^ aBag |
|
379 ! |
|
380 |
|
381 asOrderedCollection |
|
382 "return a new OrderedCollection with the receiver collections elements" |
|
383 |
|
384 |anOrderedCollection| |
|
385 |
|
386 anOrderedCollection := OrderedCollection new:self size. |
|
387 self do:[:each | anOrderedCollection addLast:each]. |
|
388 ^ anOrderedCollection |
|
389 ! |
|
390 |
|
391 asSet |
|
392 "return a new Set with the receiver collections elements" |
|
393 |
|
394 |aSet| |
|
395 |
|
396 aSet := Set new: self size. |
|
397 self do:[:each | aSet add:each]. |
|
398 ^ aSet |
|
399 ! |
|
400 |
|
401 asSortedCollection |
|
402 "return a new SortedCollection with the receiver collections elements" |
|
403 |
|
404 |aSortedCollection| |
|
405 |
|
406 aSortedCollection := SortedCollection new:self size. |
|
407 aSortedCollection addAll:self. |
|
408 ^ aSortedCollection |
|
409 ! |
|
410 |
|
411 asSortedCollection:sortBlock |
|
412 "return a new SortedCollection with the receiver collections elements, |
|
413 using sortBlock for comparing" |
|
414 |
|
415 |aSortedCollection| |
|
416 |
|
417 aSortedCollection := SortedCollection sortBlock:sortBlock. |
|
418 aSortedCollection addAll:self. |
|
419 ^ aSortedCollection |
|
420 ! ! |
|
421 |
|
422 !Collection methodsFor:'printing & storing'! |
|
423 |
|
424 maxPrint |
|
425 ^ 5000 |
|
426 ! |
|
427 |
|
428 printString |
|
429 "return the printString of a big collection can take a long time |
|
430 due to long temporary strings - I use a buffer here collecting some |
|
431 elements to reduce the GC overhead ... |
|
432 " |
|
433 |
|
434 |thisString buffer count string noneYet total| |
|
435 |
|
436 string := (self class name) , '('. |
|
437 noneYet := true. |
|
438 buffer := ''. |
|
439 count := 0. |
|
440 total := 0. |
|
441 self do: [:element | |
|
442 thisString := element printString. |
|
443 noneYet ifTrue:[ |
|
444 noneYet := false. |
|
445 buffer := buffer , thisString |
|
446 ] ifFalse:[ |
|
447 buffer := buffer , (' ' , thisString) |
|
448 ]. |
|
449 count := count + 1. |
|
450 (count == 20) ifTrue:[ |
|
451 string := string , buffer. |
|
452 buffer := ''. |
|
453 count := 0 |
|
454 ]. |
|
455 total := total + 1. |
|
456 (total > 5000) ifTrue:[ |
|
457 string := string , buffer , '... )'. |
|
458 ^string |
|
459 ] |
|
460 ]. |
|
461 string := string , buffer , ')'. |
|
462 ^string |
|
463 ! |
|
464 |
|
465 displayString |
|
466 "return the printString of a big collection can take a long time |
|
467 due to long temporary strings - I use a buffer here collecting some |
|
468 elements to reduce the GC overhead ... |
|
469 " |
|
470 |
|
471 |thisString buffer count string noneYet total| |
|
472 |
|
473 string := (self class name) , '('. |
|
474 noneYet := true. |
|
475 buffer := ''. |
|
476 count := 0. |
|
477 total := 0. |
|
478 self do: [:element | |
|
479 thisString := element displayString. |
|
480 noneYet ifTrue:[ |
|
481 noneYet := false. |
|
482 buffer := buffer , thisString |
|
483 ] ifFalse:[ |
|
484 buffer := buffer , (' ' , thisString) |
|
485 ]. |
|
486 count := count + 1. |
|
487 (count == 20) ifTrue:[ |
|
488 string := string , buffer. |
|
489 buffer := ''. |
|
490 count := 0 |
|
491 ]. |
|
492 total := total + 1. |
|
493 (total > 5000) ifTrue:[ |
|
494 string := string , buffer , '... )'. |
|
495 ^string |
|
496 ] |
|
497 ]. |
|
498 string := string , buffer , ')'. |
|
499 ^string |
|
500 ! |
|
501 |
|
502 printOn:aStream |
|
503 |tooMany firstOne noMore| |
|
504 |
|
505 tooMany := aStream position + self maxPrint. |
|
506 aStream nextPutAll:self class name. |
|
507 aStream nextPut:$(. |
|
508 firstOne := true. |
|
509 noMore := false. |
|
510 self do:[:element | |
|
511 noMore ifFalse:[ |
|
512 firstOne ifFalse:[ |
|
513 aStream nextPut:(Character space) |
|
514 ] ifTrue:[ |
|
515 firstOne := false |
|
516 ]. |
|
517 (aStream position > tooMany) ifTrue:[ |
|
518 aStream nextPutAll:'...etc...)'. |
|
519 noMore := true |
|
520 ] ifFalse:[ |
|
521 element printOn:aStream |
|
522 ] |
|
523 ]. |
|
524 ]. |
|
525 aStream nextPut:$) |
|
526 ! |
|
527 |
|
528 storeOn:aStream |
|
529 "output a printed representation (which can be re-read) |
|
530 onto the argument aStream" |
|
531 |
|
532 |isEmpty| |
|
533 |
|
534 aStream nextPutAll:'(('. |
|
535 aStream nextPutAll:(self class name). |
|
536 aStream nextPutAll:' new)'. |
|
537 isEmpty := true. |
|
538 self do:[:element | |
|
539 aStream nextPutAll:' add: '. |
|
540 element storeOn:aStream. |
|
541 aStream nextPut:$;. |
|
542 isEmpty := false |
|
543 ]. |
|
544 isEmpty ifFalse:[aStream nextPutAll:' yourself']. |
|
545 aStream nextPut:$) |
|
546 ! ! |