github.com/searKing/golang/go@v1.2.74/util/optional/optional.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 optional 6 7 import ( 8 "errors" 9 10 "github.com/searKing/golang/go/util/function/consumer" 11 "github.com/searKing/golang/go/util/function/predicate" 12 "github.com/searKing/golang/go/util/object" 13 ) 14 15 var ( 16 ErrorNoValuePresent = errors.New("no value present") 17 ) 18 19 // Optional is a container object which may or may not contain a non-{@code null} value. 20 // If a value is present, {@code isPresent()} returns {@code true}. If no 21 // value is present, the object is considered <i>empty</i> and 22 // {@code isPresent()} returns {@code false}. 23 type Optional struct { 24 isPresent bool 25 value interface{} 26 } 27 28 // Empty returns an empty {@code Optional} instance. No value is present for this 29 // {@code Optional}. 30 func Empty() Optional { 31 return Optional{} 32 } 33 34 // Of Returns an {@code Optional} describing the given value. 35 func Of(value interface{}) Optional { 36 return Optional{ 37 isPresent: true, 38 value: value, 39 } 40 } 41 42 // Of Returns an {@code Optional} describing the given value, if 43 // non-{@code null}, otherwise returns an empty {@code Optional}. 44 func OfNillable(value interface{}) Optional { 45 if value == nil { 46 return Empty() 47 } 48 return Of(value) 49 } 50 51 // Get returns the value if a value is present, otherwise throws 52 // {@code ErrorNoValuePresent}. 53 func (o Optional) Get() interface{} { 54 return o.value 55 } 56 57 // IsPresent returns {@code true} if a value is present, otherwise {@code false}. 58 func (o Optional) IsPresent() bool { 59 return o.isPresent 60 } 61 62 type EmptyConsumer interface { 63 Run() 64 } 65 66 /** 67 * If a value is present, performs the given action with the value, 68 * otherwise does nothing. 69 * 70 * @param action the action to be performed, if a value is present 71 * @throws ErrorNilPointer if value is present and the given action is 72 * {@code null} 73 */ 74 func (o Optional) IfPresent(action consumer.Consumer) { 75 if o.IsPresent() { 76 action.Accept(o.value) 77 } 78 } 79 80 /** 81 * If a value is present, performs the given action with the value, 82 * otherwise performs the given empty-based action. 83 * 84 * @param action the action to be performed, if a value is present 85 * @param emptyAction the empty-based action to be performed, if no value is 86 * present 87 * @throws NullPointerException if a value is present and the given action 88 * is {@code null}, or no value is present and the given empty-based 89 * action is {@code null}. 90 * @since 9 91 */ 92 func (o Optional) IfPresentOrElse(action consumer.Consumer, emptyAction EmptyConsumer) { 93 if o.IsPresent() { 94 action.Accept(o.value) 95 return 96 } 97 emptyAction.Run() 98 } 99 100 /** 101 * If a value is present, and the value matches the given predicate, 102 * returns an {@code Optional} describing the value, otherwise returns an 103 * empty {@code Optional}. 104 * 105 * @param predicate the predicate to apply to a value, if present 106 * @return an {@code Optional} describing the value of this 107 * {@code Optional}, if a value is present and the value matches the 108 * given predicate, otherwise an empty {@code Optional} 109 * @throws NullPointerException if the predicate is {@code null} 110 */ 111 func (o Optional) Filter(predicate predicate.Predicater) Optional { 112 object.RequireNonNull(predicate) 113 if !o.IsPresent() { 114 return o 115 } 116 if predicate.Test(o.value) { 117 return o 118 } 119 return Empty() 120 } 121 122 /** 123 * If a value is present, returns an {@code Optional} describing (as if by 124 * {@link #ofNullable}) the result of applying the given mapping function to 125 * the value, otherwise returns an empty {@code Optional}. 126 * 127 * <p>If the mapping function returns a {@code null} result then this method 128 * returns an empty {@code Optional}. 129 * 130 * @apiNote 131 * This method supports post-processing on {@code Optional} values, without 132 * the need to explicitly check for a return status. For example, the 133 * following code traverses a stream of URIs, selects one that has not 134 * yet been processed, and creates a path from that URI, returning 135 * an {@code Optional<Path>}: 136 * 137 * <pre>{@code 138 * Optional<Path> p = 139 * uris.stream().filter(uri -> !isProcessedYet(uri)) 140 * .findFirst() 141 * .map(Paths::get); 142 * }</pre> 143 * 144 * Here, {@code findFirst} returns an {@code Optional<URI>}, and then 145 * {@code map} returns an {@code Optional<Path>} for the desired 146 * URI if one exists. 147 * 148 * @param mapper the mapping function to apply to a value, if present 149 * @param <U> The type of the value returned from the mapping function 150 * @return an {@code Optional} describing the result of applying a mapping 151 * function to the value of this {@code Optional}, if a value is 152 * present, otherwise an empty {@code Optional} 153 * @throws NullPointerException if the mapping function is {@code null} 154 */ 155 func (o Optional) Map(mapper func(interface{}) interface{}) Optional { 156 object.RequireNonNil(mapper) 157 if !o.IsPresent() { 158 return Empty() 159 } 160 161 return OfNillable(mapper(o.value)) 162 } 163 164 /** 165 * If a value is present, returns the result of applying the given 166 * {@code Optional}-bearing mapping function to the value, otherwise returns 167 * an empty {@code Optional}. 168 * 169 * <p>This method is similar to {@link #map(Function)}, but the mapping 170 * function is one whose result is already an {@code Optional}, and if 171 * invoked, {@code flatMap} does not wrap it within an additional 172 * {@code Optional}. 173 * 174 * @param <U> The type of value of the {@code Optional} returned by the 175 * mapping function 176 * @param mapper the mapping function to apply to a value, if present 177 * @return the result of applying an {@code Optional}-bearing mapping 178 * function to the value of this {@code Optional}, if a value is 179 * present, otherwise an empty {@code Optional} 180 * @throws NullPointerException if the mapping function is {@code null} or 181 * returns a {@code null} result 182 */ 183 func (o *Optional) FlatMap(mapper func(interface{}) interface{}) Optional { 184 object.RequireNonNil(mapper) 185 if !o.IsPresent() { 186 return Empty() 187 } 188 189 return OfNillable(mapper(o.value)) 190 }