CollectionBuilder.st
author Claus Gittinger <cg@exept.de>
Sat, 02 May 2020 21:40:13 +0200
changeset 5476 7355a4b11cb6
parent 5148 80aed7148971
permissions -rw-r--r--
#FEATURE by cg class: Socket class added: #newTCPclientToHost:port:domain:domainOrder:withTimeout: changed: #newTCPclientToHost:port:domain:withTimeout:

"{ Encoding: utf8 }"

"
 COPYRIGHT (c) 1996 by Claus Gittinger
              All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"
"{ Package: 'stx:libbasic2' }"

"{ NameSpace: Smalltalk }"

ArrayedCollection subclass:#CollectionBuilder
	instanceVariableNames:'collections'
	classVariableNames:''
	poolDictionaries:''
	category:'Collections-Sequenceable'
!

!CollectionBuilder class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 1996 by Claus Gittinger
              All Rights Reserved

 This software is furnished under a license and may be used
 only in accordance with the terms of that license and with the
 inclusion of the above copyright notice.   This software may not
 be provided or otherwise made available to, or used by, any
 other person.  No title to or ownership of the software is
 hereby transferred.
"
!

documentation
"
    When building large collections by concatenation, this helper can speedup this operation.
    It non-destructively creates a list of the slices added during the concatenation process, 
    thus (usually) reducing the amount of storage and time required to construct the collection.
    Especially, if the slices are constants (strings) and even reused (same string occurring multiple times),
    the saving in memory mey be significant.

    However, there is a tradeof: the time to access, to enumerate and to query the size of
    the resulting collection is slower. 
    Therefore, this is (usually) only useful if a throw-away collection is
    constructed to be used only a small number of times for enumeration (or writing to a file).

    It is very similar to Java's StringBuffer, but can handle any kind of collection.
    (however, please see also Stream / #streamContents:, for yet another (better?) way of building collections ...)

    [see also:]
        WriteStream

    [author:]
        Claus Gittinger

    [example:]
        |coll|

        coll := CollectionBuilder new.
        1 to:100000 do:[:i |
            coll addAll:#(1 2 3 4 5 6 7 8 9 0)
        ].
        coll
"
!

examples
"
  when building large collections by concatenation,
  the following standard creation is time consuming:
                                                                        [exBegin]
    Time millisecondsToRun:[
        |coll|

        coll := OrderedCollection new.
        1 to:100000 do:[:i |
            coll addAll:i printString
        ]
    ]    
                                                                        [exEnd]

  the following is faster, and does not actually create a new collection:
                                                                        [exBegin]
    Time millisecondsToRun:[
        |coll|

        coll := CollectionBuilder new.
        1 to:100000 do:[:i |
            coll addAll:i printString
        ]
    ]     
                                                                        [exEnd]
   Time to enumerate:
                                                                        [exBegin]
    |coll|

    coll := OrderedCollection new.
    1 to:100000 do:[:i |
        coll addAll:i printString
    ].
    Time millisecondsToRun:[
        coll do:[:each | each ].
    ]     
                                                                        [exEnd]
                                                                        [exBegin]
    |coll|

    coll := CollectionBuilder new.
    1 to:100000 do:[:i |
        coll addAll:i printString
    ].
    Time millisecondsToRun:[
        coll do:[:each | each ].
    ]     
                                                                        [exEnd]

"
! !

!CollectionBuilder class methodsFor:'instance creation'!

withAll:collections and:aCollection
    ^ self new withAll:collections and:aCollection


! !

!CollectionBuilder methodsFor:'accessing'!

at:index
    |collFirst collLast|

    index < 1 ifTrue:[^ self subscriptBoundsError:index].

    collFirst := 0.
    collections do:[:eachSlice |
        collLast := collFirst + eachSlice size.
        index <= collLast ifTrue:[
            ^ eachSlice at:(index - collFirst)
        ].
        collFirst := collLast.
    ].
    ^ self indexNotIntegerOrOutOfBounds:index

    "
     |c|

     c := CollectionBuilder new.
     c := c , #(1 2 3 4).
     c := c , #(5 6 7 8).
     c := c , #(9 10 11 12).
     c inspect.
     c at:13  
    "

    "Modified: 1.2.1996 / 17:01:16 / cg"
! !

!CollectionBuilder methodsFor:'adding & removing'!

add:anObject
    collections := collections copyWith:(Array with:anObject).
    ^ anObject

    "Created: 1.2.1996 / 17:09:15 / cg"
!

addAll:aCollection
    "add all elements of the argument, aCollection to the receiver.
     Returns the argument, aCollection."

    collections isNil ifTrue:[
        collections := OrderedCollection with:aCollection
    ] ifFalse:[
        collections add:aCollection
    ].
    ^ aCollection

    "Created: 1.2.1996 / 17:09:29 / cg"
    "Modified: 1.2.1996 / 17:14:54 / cg"
! !

!CollectionBuilder methodsFor:'copying'!

, aCollection
    ^ CollectionBuilder withAll:collections and:aCollection

    "Created: 1.2.1996 / 16:43:18 / cg"
! !

!CollectionBuilder methodsFor:'enumerating'!

do:aBlock
    collections do:[:coll |
	coll do:aBlock
    ]

    "Created: 1.2.1996 / 17:05:36 / cg"
!

keysAndValuesDo:aBlock
    |idx|

    idx := 1.
    collections do:[:coll |
	coll do:[:element |
	    aBlock value:idx value:element.
	    idx := idx + 1
	]
    ]

    "Created: 1.2.1996 / 17:06:13 / cg"
! !

!CollectionBuilder methodsFor:'inspecting'!

inspectorClass
    "redefined to launch an OrderedCollectionInspector
     (instead of the default InspectorView)."

    ^ OrderedCollectionInspectorView

    "Created: 1.2.1996 / 17:07:53 / cg"
! !

!CollectionBuilder methodsFor:'private'!

withAll:collections1 and:collections2
    collections1 isEmptyOrNil ifTrue:[
        collections := OrderedCollection with:collections2
    ] ifFalse:[
        collections := OrderedCollection withAll:collections1.
        collections2 notEmptyOrNil ifTrue:[
            collections add:collections2
        ].
    ].

    "Created: 1.2.1996 / 16:44:15 / cg"
    "Modified: 1.2.1996 / 17:00:17 / cg"
! !

!CollectionBuilder methodsFor:'queries'!

size
    ^ collections inject:0 into:[:sumSoFar :subColl | sumSoFar + subColl size]

    "Created: 1.2.1996 / 16:42:31 / cg"
! !

!CollectionBuilder class methodsFor:'documentation'!

version_CVS
    ^ '$Header$'
! !