github.com/searKing/golang/go@v1.2.74/container/stream/op/reduce/sink.go (about)

     1  // Copyright 2020 The searKing Author. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package reduce
     6  
     7  import (
     8  	"github.com/searKing/golang/go/container/stream/op/terminal"
     9  	"github.com/searKing/golang/go/util/function/binary"
    10  	"github.com/searKing/golang/go/util/object"
    11  	"github.com/searKing/golang/go/util/optional"
    12  )
    13  
    14  /**
    15   * A type of {@code TerminalSink} that implements an associative reducing
    16   * operation on elements of type {@code T} and producing a result of type
    17   * {@code R}.
    18   *
    19   * @param <T> the type of input element to the combining operation
    20   * @param <R> the result type
    21   * @param <K> the type of the {@code AccumulatingSink}.
    22   */
    23  type AccumulatingSink interface {
    24  	Combine(other AccumulatingSink)
    25  }
    26  
    27  type ReducingSink struct {
    28  	terminal.TODOSink
    29  	seed  optional.Optional
    30  	state optional.Optional
    31  
    32  	reducer  binary.BiFunction
    33  	combiner binary.BiFunction
    34  }
    35  
    36  func NewReducingSink(seed optional.Optional, reducer binary.BiFunction, combiner binary.BiFunction) *ReducingSink {
    37  	object.RequireNonNull(reducer)
    38  	sink := &ReducingSink{
    39  		seed:     seed,
    40  		reducer:  reducer,
    41  		combiner: combiner,
    42  	}
    43  	sink.SetDerived(sink)
    44  	return sink
    45  }
    46  
    47  func (sink *ReducingSink) Begin(size int) {
    48  	sink.state = sink.seed
    49  }
    50  
    51  func (sink *ReducingSink) Accept(t interface{}) {
    52  	if !sink.state.IsPresent() {
    53  		sink.state = optional.Of(t)
    54  		return
    55  	}
    56  	sink.state = optional.Of(sink.reducer.Apply(sink.state.Get(), t))
    57  	return
    58  }
    59  
    60  func (sink *ReducingSink) Combine(other terminal.Sink) {
    61  	otherOptional := other.Get()
    62  	if !otherOptional.IsPresent() {
    63  		return
    64  	}
    65  
    66  	if !sink.state.IsPresent() {
    67  		sink.Accept(otherOptional.Get())
    68  		return
    69  	}
    70  	if sink.combiner != nil {
    71  		sink.state = optional.Of(sink.combiner.Apply(sink.state.Get(), otherOptional.Get()))
    72  		return
    73  	}
    74  	sink.Accept(otherOptional.Get())
    75  	return
    76  }
    77  
    78  func (sink *ReducingSink) Get() optional.Optional {
    79  	return sink.state
    80  }