[squeak-dev] The Trunk: Collections-ul.282.mcz
commits at source.squeak.org
commits at source.squeak.org
Mon Jan 25 22:15:13 UTC 2010
Levente Uzonyi uploaded a new version of Collections to project The Trunk:
http://source.squeak.org/trunk/Collections-ul.282.mcz
==================== Summary ====================
Name: Collections-ul.282
Author: ul
Time: 25 January 2010, 10:56:13.924 pm
UUID: 44962376-0c2e-ea4c-9fce-9fb056cd768b
Ancestors: Collections-nice.281
In the HashedCollection hierarchy:
- cosmetic changes: use #ifNotNil: if possible
- use unary symbols instead of blocks with a single unary send
- removed unnecessary line from #atRandom
- restored correct compatibility method for #fullCheck
In Dictionary:
- make sure that #associationsSelect: works with PluggableDictionary by using #copyEmpty instead of #species + #new
- deprecated #keyForIdentity:, because it's similar to #keyAtIdentityValue:ifAbsent:
In WeakKeyDictionary:
- #rehash throws away nil keys, so we don't have to iterate twice over array
- don't let the key go away in #noCheckNoGrowFillFrom:
In WeakKeyToCollectionDictionary:
- don't let the key go away in #noCheckNoGrowFillFrom:
- removed #finalizeValues because it became same as super
In WeakSet:
- #do:after: doesn't skip the first element if anElement is nil
- speed up #slowSize
- don't rehash twice in #grow, just count the occupied slots first with #slowSize
Other:
- simplified a few KeyedSet's methods
- added #collect: to PluggableDictionary (super doesn't copy the blocks)
=============== Diff against Collections-nice.281 ===============
Item was changed:
+ ----- Method: IdentityDictionary>>keyAtValue:ifAbsent: (in category 'accessing') -----
- ----- Method: IdentityDictionary>>keyAtValue:ifAbsent: (in category 'private') -----
keyAtValue: value ifAbsent: exceptionBlock
"Answer the key that is the external name for the argument, value. If
there is none, answer the result of evaluating exceptionBlock."
+ ^super keyAtIdentityValue: value ifAbsent: exceptionBlock!
- self associationsDo:
- [:association | value == association value ifTrue: [^ association key]].
- ^ exceptionBlock value!
Item was changed:
----- Method: Set>>noCheckNoGrowFillFrom: (in category 'private') -----
noCheckNoGrowFillFrom: anArray
"Add the elements of anArray except nils to me assuming that I don't contain any of them, they are unique and I have more free space than they require."
1 to: anArray size do: [ :index |
+ (anArray at: index) ifNotNil: [ :object |
- | object |
- (object := anArray at: index) ifNotNil: [
array
at: (self scanForEmptySlotFor: object)
put: object ] ]!
Item was changed:
----- Method: WeakSet>>noCheckNoGrowFillFrom: (in category 'private') -----
noCheckNoGrowFillFrom: anArray
"Add the elements of anArray except nils and flag to me assuming that I don't contain any of them, they are unique and I have more free space than they require."
tally := 0.
1 to: anArray size do: [ :index |
+ (anArray at: index) ifNotNil: [ :object |
+ object == flag ifFalse: [
- | object |
- ((object := anArray at: index) == flag or: [
- object == nil ]) ifFalse: [
array
at: (self scanForEmptySlotFor: object)
put: object.
+ tally := tally + 1 ] ] ]!
- tally := tally + 1 ] ]!
Item was changed:
----- Method: WeakKeyDictionary>>finalizeValues: (in category 'finalization') -----
finalizeValues: finiObjects
"Remove all associations with key == nil and value is in finiObjects.
This method is folded with #rehash for efficiency."
| oldArray |
oldArray := array.
array := Array new: oldArray size.
tally := 0.
+ 1 to: array size do: [ :index |
+ (oldArray at: index) ifNotNil: [ :association |
+ association key ifNotNil: [ :key | "Don't let the key go away"
+ (finiObjects includes: association value) ifFalse: [
+ array
+ at: (self scanForEmptySlotFor: key)
+ put: association.
+ tally := tally + 1 ] ] ] ]!
- 1 to: array size do:[ :i |
- | association |
- (association := oldArray at: i) ifNotNil: [
- | key |
- ((key := association key) == nil and: [ "Don't let the key go away"
- finiObjects includes: association value ])
- ifFalse: [
- array
- at: (self scanForEmptySlotFor: key)
- put: association.
- tally := tally + 1 ] ] ]!
Item was changed:
----- Method: WeakSet>>grow (in category 'private') -----
grow
"Grow the elements array if needed.
Since WeakSets just nil their slots, a lot of the occupied (in the eyes of the set) slots are usually empty. Doubling size if unneeded can lead to BAD performance, therefore we see if reassigning the <live> elements to a Set of similiar size leads to a sufficiently (50% used here) empty set first"
+ tally // 2 < self slowSize
+ ifTrue: [ super grow ]
+ ifFalse: [ self rehash ]
+ !
- | oldTally |
- oldTally := tally.
- self rehash.
- oldTally // 2 < tally ifTrue: [ super grow ]!
Item was changed:
----- Method: WeakSet>>growTo: (in category 'private') -----
growTo: anInteger
"Grow the elements array and reinsert the old elements"
| oldElements |
oldElements := array.
+ array := WeakArray new: anInteger withAll: flag.
- array := WeakArray new: anInteger.
- array atAllPut: flag.
self noCheckNoGrowFillFrom: oldElements!
Item was changed:
----- Method: HashedCollection>>atRandom: (in category 'accessing') -----
atRandom: aGenerator
"Answer a random element of the receiver. Uses aGenerator which
+ should be kept by the user in a variable and used every time. Use
+ this instead of #atRandom for better uniformity of random numbers because
- should be kept by the user in a variable and used every time. Use
- this instead of #atRandom for better uniformity of random numbers because
only you use the generator. Causes an error if self has no elements."
+
| rand |
-
self emptyCheck.
rand := aGenerator nextInt: self size.
+ self doWithIndex: [ :each :index |
+ index = rand ifTrue: [ ^each ] ]!
- self doWithIndex:[:each :ind |
- ind = rand ifTrue:[^each]].
- ^ self errorEmptyCollection
- !
Item was changed:
----- Method: KeyedSet>>member: (in category 'adding') -----
member: newObject
"Include newObject as one of the receiver's elements, if already exists just return it"
| index |
newObject ifNil: [self error: 'Sets cannot meaningfully contain nil as an element'].
index := self scanFor: (keyBlock value: newObject).
+ (array at: index) ifNotNil: [ :element | ^element ].
- (array at: index) ifNotNil: [^ array at: index].
self atNewIndex: index put: newObject.
^ newObject!
Item was changed:
+ ----- Method: WeakSet>>add: (in category 'adding') -----
- ----- Method: WeakSet>>add: (in category 'public') -----
add: newObject
"Include newObject as one of the receiver's elements, but only if
not already present. Answer newObject"
| index element |
newObject ifNil: [self error: 'Sets cannot meaningfully contain nil as an element'].
index := self scanFor: newObject.
((element := array at: index) == flag or: [ element == nil ])
ifTrue: [self atNewIndex: index put: newObject].
^newObject!
Item was changed:
----- Method: KeyedSet>>at:ifAbsent: (in category 'accessing') -----
at: key ifAbsent: aBlock
"Answer the value associated with the key or, if key isn't found,
answer the result of evaluating aBlock."
+ ^(array at: (self scanFor: key)) ifNil: [ aBlock value ]!
- | obj |
- obj := array at: (self scanFor: key).
- obj ifNil: [^ aBlock value].
- ^ obj!
Item was changed:
+ ----- Method: WeakSet>>includes: (in category 'testing') -----
- ----- Method: WeakSet>>includes: (in category 'public') -----
includes: anObject
+ ^(array at: (self scanFor: anObject))
+ ifNil: [ false ]
+ ifNotNil: [ :object | object ~~ flag ]!
- | element |
- ^((element := array at: (self scanFor: anObject)) == flag or: [ element == nil ]) not!
Item was changed:
----- Method: Dictionary>>noCheckNoGrowFillFrom: (in category 'private') -----
noCheckNoGrowFillFrom: anArray
"Add the elements of anArray except nils to me assuming that I don't contain any of them, they are unique and I have more free space than they require."
1 to: anArray size do: [ :index |
+ (anArray at: index) ifNotNil: [ :association |
- | object |
- (object := anArray at: index) ifNotNil: [
array
+ at: (self scanForEmptySlotFor: association key)
+ put: association ] ]!
- at: (self scanForEmptySlotFor: object key)
- put: object ] ]!
Item was changed:
----- Method: KeyedSet>>initialize: (in category 'private') -----
initialize: n
+
super initialize: n.
+ keyBlock := #key
- keyBlock := [:element | element key].
!
Item was changed:
----- Method: WeakKeyDictionary>>keysDo: (in category 'accessing') -----
keysDo: aBlock
"Evaluate aBlock for each of the receiver's keys."
self associationsDo: [ :association |
+ (association key) ifNotNil: [ :key | "Don't let the key go away"
- | key |
- (key := association key) ifNotNil: [ "Don't let the key go away"
aBlock value: key ] ].!
Item was changed:
----- Method: Dictionary>>add: (in category 'adding') -----
add: anAssociation
+ | index |
- | index element |
index := self scanFor: anAssociation key.
+ (array at: index)
- (element := array at: index)
ifNil: [ self atNewIndex: index put: anAssociation ]
+ ifNotNil: [ :element | element value: anAssociation value ].
- ifNotNil: [ element value: anAssociation value ].
^anAssociation!
Item was changed:
----- Method: WeakSet>>do:after: (in category 'public') -----
do: aBlock after: anElement
- | each startIndex |
+ | startIndex |
+ tally = 0 ifTrue: [ ^self ].
+ startIndex := anElement
+ ifNil: [ 0 ]
+ ifNotNil: [ self scanFor: anElement ].
+ startIndex + 1 to: array size do: [ :index |
+ (array at: index) ifNotNil: [ :object |
+ object == flag ifFalse: [
+ aBlock value: object ] ] ]!
- tally = 0 ifTrue: [^self].
- startIndex := anElement ifNil: [1] ifNotNil:
- [self scanFor: anElement].
- startIndex + 1 to: array size do:
- [:index |
- ((each := array at: index) == nil or: [each == flag])
- ifFalse: [aBlock value: each]
- ]!
Item was changed:
+ ----- Method: WeakSet>>remove:ifAbsent: (in category 'removing') -----
- ----- Method: WeakSet>>remove:ifAbsent: (in category 'public') -----
remove: oldObject ifAbsent: aBlock
| index |
index := self scanFor: oldObject.
(array at: index) == flag ifTrue: [ ^ aBlock value ].
array at: index put: flag.
tally := tally - 1.
self fixCollisionsFrom: index.
^oldObject!
Item was changed:
----- Method: WeakKeyDictionary>>finalizeValues (in category 'finalization') -----
finalizeValues
"remove all nil keys and rehash the receiver afterwards"
- | assoc |
- 1 to: array size do: [ :index |
- (assoc := array at: index) ifNotNil: [
- assoc key ifNil: [ array at: index put: nil ] ] ].
self rehash!
Item was changed:
----- Method: HashedCollection class>>goodPrimeAtLeast: (in category 'sizing') -----
goodPrimeAtLeast: lowerLimit
"Answer the next good prime >= lowerlimit.
If lowerLimit is larger than the largest known good prime,
just make it odd."
| primes low mid high prime |
primes := self goodPrimes.
low := 1.
high := primes size.
lowerLimit > (primes at: high) ifTrue: [
+ ^lowerLimit bitOr: 1 ].
- ^lowerLimit even
- ifTrue: [ lowerLimit + 1 ]
- ifFalse: [ lowerLimit ] ].
[ high - low <= 1 ] whileFalse: [
mid := high + low // 2.
prime := primes at: mid.
prime = lowerLimit ifTrue: [ ^prime ].
prime < lowerLimit
ifTrue: [ low := mid ]
ifFalse: [ high := mid ] ].
(primes at: low) >= lowerLimit ifTrue: [ ^primes at: low ].
^primes at: high!
Item was changed:
----- Method: Dictionary>>at:put: (in category 'accessing') -----
at: key put: anObject
"Set the value at key to be anObject. If key is not found, create a
new entry for key and set is value to anObject. Answer anObject."
+ | index |
- | index assoc |
index := self scanFor: key.
+ (array at: index)
+ ifNil: [ self atNewIndex: index put: (Association key: key value: anObject) ]
+ ifNotNil: [ :association | association value: anObject ].
+ ^anObject!
- assoc := array at: index.
- assoc
- ifNil: [self atNewIndex: index put: (Association key: key value: anObject)]
- ifNotNil: [assoc value: anObject].
- ^ anObject!
Item was changed:
----- Method: KeyedSet>>keysSorted (in category 'accessing') -----
keysSorted
+ ^self keys sort!
- | keys |
- keys := SortedCollection new.
- self do: [:item | keys add: (keyBlock value: item)].
- ^ keys!
Item was changed:
----- Method: WeakSet>>slowSize (in category 'public') -----
slowSize
"Careful!! Answer the maximum amount
of elements in the receiver, not the
exact amount"
+ | count |
+ count := 0.
+ 1 to: array size do: [ :index |
+ (array at: index) ifNotNil: [ :object |
+ object == flag ifFalse: [
+ count := count + 1 ] ] ].
+ ^tally := count!
- tally := array inject: 0 into:
- [:total :each | (each == nil or: [each == flag])
- ifTrue: [total] ifFalse: [total + 1]].
- ^tally!
Item was changed:
----- Method: WeakKeyDictionary>>noCheckNoGrowFillFrom: (in category 'private') -----
noCheckNoGrowFillFrom: anArray
"Add the elements of anArray except nils and flag to me assuming that I don't contain any of them, they are unique and I have more free space than they require."
tally := 0.
+ 1 to: anArray size do:[ :index |
+ (anArray at: index) ifNotNil: [ :association |
+ association key ifNotNil: [ :key | "Don't let the key go away"
+ array
+ at: (self scanForEmptySlotFor: key)
+ put: association.
+ tally := tally + 1 ] ] ]!
- 1 to: anArray size do:[ :i |
- | association |
- (association := anArray at: i) ifNotNil: [
- array
- at: (self scanForEmptySlotFor: association key)
- put: association.
- tally := tally + 1 ] ]!
Item was changed:
----- Method: WeakKeyToCollectionDictionary>>noCheckNoGrowFillFrom: (in category 'as yet unclassified') -----
noCheckNoGrowFillFrom: anArray
"Add the elements of anArray except nils and associations with empty collections (or with only nils) to me assuming that I don't contain any of them, they are unique and I have more free space than they require."
tally := 0.
+ 1 to: anArray size do: [ :index |
+ (anArray at: index) ifNotNil: [ :association |
+ association key ifNotNil: [ :key | "Don't let the key go away"
+ | cleanedValue |
+ (cleanedValue := association value copyWithout: nil) isEmpty
+ ifFalse: [
+ association value: cleanedValue.
+ array
+ at: (self scanForEmptySlotFor: key)
+ put: association.
+ tally := tally + 1 ] ] ] ]!
- 1 to: anArray size do:[ :i |
- | association cleanedValue |
- ((association := anArray at: i) == nil or: [
- (cleanedValue := association value copyWithout: nil) isEmpty ])
- ifFalse: [
- association value: cleanedValue.
- array
- at: (self scanForEmptySlotFor: association key)
- put: association.
- tally := tally + 1 ] ]!
Item was changed:
----- Method: HashedCollection class>>rehashAll (in category 'initialization') -----
rehashAll
"HashedCollection rehashAll"
+ self allSubclassesDo: #rehashAllInstances!
- self allSubclassesDo: [ :each | each rehashAllInstances ]!
Item was changed:
----- Method: HashedCollection>>fullCheck (in category 'compatibility') -----
fullCheck
"This is a private method, formerly implemented in Set, that is no longer required.
It is here for compatibility with external packages only."
+ "Keep array at least 1/4 free for decent hash behavior"
+
+ array size * 3 < (tally * 4) ifTrue: [ self grow ]!
- ^ self
- !
Item was changed:
----- Method: KeyedSet>>noCheckNoGrowFillFrom: (in category 'private') -----
noCheckNoGrowFillFrom: anArray
"Add the elements of anArray except nils to me assuming that I don't contain any of them, they are unique and I have more free space than they require."
1 to: anArray size do: [ :index |
+ (anArray at: index) ifNotNil: [ :object |
- | object |
- (object := anArray at: index) ifNotNil: [
array
at: (self scanForEmptySlotFor: (keyBlock value: object))
put: object ] ]!
Item was changed:
----- Method: Dictionary>>associationsSelect: (in category 'enumerating') -----
associationsSelect: aBlock
"Evaluate aBlock with each of my associations as the argument. Collect
into a new dictionary, only those associations for which aBlock evaluates
to true."
| newCollection |
+ newCollection := self copyEmpty.
+ self associationsDo: [ :each |
+ (aBlock value: each) ifTrue: [ newCollection add: each ] ].
- newCollection := self species new.
- self associationsDo:
- [:each |
- (aBlock value: each) ifTrue: [newCollection add: each]].
^newCollection!
Item was changed:
----- Method: Dictionary>>associationsDo: (in category 'enumerating') -----
associationsDo: aBlock
"Evaluate aBlock for each of the receiver's elements (key/value
associations)."
tally = 0 ifTrue: [ ^self].
1 to: array size do: [ :index |
+ (array at: index) ifNotNil: [ :element |
+ aBlock value: element ] ]!
- | each |
- (each := array at: index)
- ifNotNil: [ aBlock value: each ] ]!
Item was changed:
----- Method: Set>>do: (in category 'enumerating') -----
do: aBlock
tally = 0 ifTrue: [ ^self ].
1 to: array size do: [ :index |
+ (array at: index) ifNotNil: [ :element |
+ aBlock value: element ] ]!
- | each |
- (each := array at: index)
- ifNotNil: [ aBlock value: each ] ]!
Item was changed:
+ ----- Method: Dictionary>>keyForIdentity: (in category 'accessing') -----
- ----- Method: Dictionary>>keyForIdentity: (in category 'testing') -----
keyForIdentity: anObject
"If anObject is one of the values of the receive, return its key, else return nil. Contrast #keyAtValue: in which there is only an equality check, here there is an identity check"
+ self deprecated: 'Use #keyAtIdentityValue:ifAbsent:'.
+ ^self keyAtIdentityValue: anObject ifAbsent: nil!
- self associationsDo: [:assoc | assoc value == anObject ifTrue: [^ assoc key]].
- ^ nil!
Item was changed:
+ ----- Method: WeakSet>>do: (in category 'enumerating') -----
- ----- Method: WeakSet>>do: (in category 'public') -----
do: aBlock
tally = 0 ifTrue: [ ^self ].
1 to: array size do: [ :index |
+ (array at: index) ifNotNil: [ :object |
+ object == flag ifFalse: [
+ aBlock value: object ] ] ]!
- | each |
- ((each := array at: index) == nil or: [ each == flag ])
- ifFalse: [ aBlock value: each ] ]!
Item was changed:
+ ----- Method: WeakSet>>like: (in category 'accessing') -----
- ----- Method: WeakSet>>like: (in category 'public') -----
like: anObject
"Answer an object in the receiver that is equal to anObject,
nil if no such object is found. Relies heavily on hash properties"
| element |
^(element := array at: (self scanFor: anObject)) == flag
ifFalse: [ element ]!
Item was changed:
----- Method: WeakKeyDictionary>>at:put: (in category 'accessing') -----
at: key put: anObject
"Set the value at key to be anObject. If key is not found, create a new
entry for key and set is value to anObject. Answer anObject."
+ | index |
- | index element |
key ifNil: [ ^anObject ].
index := self scanFor: key.
+ (array at: index)
- (element := array at: index)
ifNil: [ self atNewIndex: index put: (WeakKeyAssociation key: key value: anObject) ]
+ ifNotNil: [ :association | association value: anObject ].
- ifNotNil: [ element value: anObject ].
^anObject!
Item was changed:
+ ----- Method: WeakSet>>collect: (in category 'enumerating') -----
- ----- Method: WeakSet>>collect: (in category 'public') -----
collect: aBlock
+
+ | newSet |
- | each newSet |
newSet := self species new: self size.
+ tally = 0 ifTrue: [ ^newSet ].
+ 1 to: array size do: [ :index |
+ (array at: index) ifNotNil: [ :object |
+ object == flag ifFalse: [
+ newSet add: (aBlock value: object) ] ] ].
- tally = 0 ifTrue: [^newSet ].
- 1 to: array size do:
- [:index |
- ((each := array at: index) == nil or: [each == flag])
- ifFalse: [newSet add: (aBlock value: each)]
- ].
^newSet!
Item was changed:
----- Method: HashedCollection class>>rehashAllInstances (in category 'initialization') -----
rehashAllInstances
"Do not use #allInstancesDo: because rehash may create new instances."
+ self allInstances do: #rehash!
- self allInstances do: [ :each | each rehash ] !
Item was changed:
+ ----- Method: WeakSet>>size (in category 'accessing') -----
- ----- Method: WeakSet>>size (in category 'public') -----
size
"Careful!! Answer the maximum amount
of elements in the receiver, not the
exact amount"
^tally!
Item was added:
+ ----- Method: PluggableDictionary>>collect: (in category 'enumerating') -----
+ collect: aBlock
+ "Evaluate aBlock with each of my values as the argument. Collect the resulting values into a collection that is like me. Answer with the new collection."
+
+ | newCollection |
+ newCollection := (self species new: self size)
+ hashBlock: hashBlock;
+ equalBlock: equalBlock;
+ yourself.
+ self associationsDo: [ :each |
+ newCollection at: each key put: (aBlock value: each value) ].
+ ^newCollection
+
+ !
Item was removed:
- ----- Method: WeakKeyToCollectionDictionary>>finalizeValues (in category 'as yet unclassified') -----
- finalizeValues
- self rehash!
More information about the Squeak-dev
mailing list
|