001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.commons.lang; 018 019import static org.apache.juneau.commons.utils.AssertionUtils.*; 020import static org.apache.juneau.commons.utils.Utils.*; 021 022/** 023 * A simple mutable integer value. 024 * 025 * <p> 026 * This class extends {@link Value}<{@link Integer}> and adds a convenience method for incrementing 027 * the value, which is useful for counting operations in lambdas and loops. 028 * 029 * <h5 class='section'>Notes:</h5><ul> 030 * <li class='note'> 031 * This class is <b>not thread-safe</b>. For concurrent access, use {@link java.util.concurrent.atomic.AtomicInteger} instead. 032 * </ul> 033 * 034 * <h5 class='section'>Example:</h5> 035 * <p class='bjava'> 036 * <jc>// Create a counter</jc> 037 * IntegerValue <jv>counter</jv> = IntegerValue.<jsm>create</jsm>(); 038 * 039 * <jc>// Use in a lambda to count valid items</jc> 040 * list.forEach(<jv>x</jv> -> { 041 * <jk>if</jk> (<jv>x</jv>.isValid()) { 042 * <jv>counter</jv>.getAndIncrement(); 043 * } 044 * }); 045 * 046 * <jsm>log</jsm>(<js>"Valid items: "</js> + <jv>counter</jv>.get()); 047 * </p> 048 * 049 * <h5 class='section'>See Also:</h5><ul> 050 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauCommonsLang">Lang Package</a> 051 * </ul> 052 */ 053public class IntegerValue extends Value<Integer> { 054 055 /** 056 * Creates a new integer value initialized to <c>0</c>. 057 * 058 * <h5 class='section'>Example:</h5> 059 * <p class='bjava'> 060 * IntegerValue <jv>counter</jv> = IntegerValue.<jsm>create</jsm>(); 061 * <jsm>assertEquals</jsm>(0, <jv>counter</jv>.get()); 062 * </p> 063 * 064 * @return A new integer value. 065 */ 066 public static IntegerValue create() { 067 return of(0); 068 } 069 070 /** 071 * Creates a new integer value with the specified initial value. 072 * 073 * <h5 class='section'>Example:</h5> 074 * <p class='bjava'> 075 * IntegerValue <jv>counter</jv> = IntegerValue.<jsm>of</jsm>(42); 076 * <jsm>assertEquals</jsm>(42, <jv>counter</jv>.get()); 077 * </p> 078 * 079 * @param value The initial value. 080 * @return A new integer value. 081 */ 082 public static IntegerValue of(Integer value) { 083 return new IntegerValue(value); 084 } 085 086 /** 087 * Constructor. 088 */ 089 public IntegerValue() { 090 super(0); 091 } 092 093 /** 094 * Constructor. 095 * 096 * @param value The initial value. 097 */ 098 public IntegerValue(Integer value) { 099 super(value == null ? 0 : value); 100 } 101 102 /** 103 * Adds the specified value to the current value. 104 * 105 * <h5 class='section'>Example:</h5> 106 * <p class='bjava'> 107 * IntegerValue <jv>value</jv> = IntegerValue.<jsm>of</jsm>(10); 108 * <jv>value</jv>.add(5); 109 * <jsm>assertEquals</jsm>(15, <jv>value</jv>.get()); 110 * </p> 111 * 112 * @param x The value to add. 113 * @return This object. 114 */ 115 public IntegerValue add(Integer x) { 116 set(get() + (x == null ? 0 : x)); 117 return this; 118 } 119 120 /** 121 * Adds the specified value to the current value and returns the new value. 122 * 123 * <h5 class='section'>Example:</h5> 124 * <p class='bjava'> 125 * IntegerValue <jv>value</jv> = IntegerValue.<jsm>of</jsm>(10); 126 * <jk>int</jk> <jv>result</jv> = <jv>value</jv>.addAndGet(5); <jc>// Returns 15</jc> 127 * <jsm>assertEquals</jsm>(15, <jv>value</jv>.get()); 128 * </p> 129 * 130 * @param x The value to add. 131 * @return The new value after addition. 132 */ 133 public Integer addAndGet(Integer x) { 134 set(get() + (x == null ? 0 : x)); 135 return get(); 136 } 137 138 /** 139 * Decrements the value by 1. 140 * 141 * <h5 class='section'>Example:</h5> 142 * <p class='bjava'> 143 * IntegerValue <jv>counter</jv> = IntegerValue.<jsm>of</jsm>(5); 144 * <jv>counter</jv>.decrement(); 145 * <jsm>assertEquals</jsm>(4, <jv>counter</jv>.get()); 146 * </p> 147 * 148 * @return This object. 149 */ 150 public IntegerValue decrement() { 151 set(get() - 1); 152 return this; 153 } 154 155 /** 156 * Decrements the value by 1 and returns the new value. 157 * 158 * <h5 class='section'>Example:</h5> 159 * <p class='bjava'> 160 * IntegerValue <jv>counter</jv> = IntegerValue.<jsm>of</jsm>(5); 161 * <jk>int</jk> <jv>result</jv> = <jv>counter</jv>.decrementAndGet(); <jc>// Returns 4</jc> 162 * <jsm>assertEquals</jsm>(4, <jv>counter</jv>.get()); 163 * </p> 164 * 165 * @return The decremented value. 166 */ 167 public Integer decrementAndGet() { 168 set(get() - 1); 169 return get(); 170 } 171 172 /** 173 * Returns the current value and then increments it. 174 * 175 * <p> 176 * This is a convenience method commonly used for counting operations in lambdas and loops. 177 * 178 * <h5 class='section'>Example:</h5> 179 * <p class='bjava'> 180 * IntegerValue <jv>counter</jv> = IntegerValue.<jsm>of</jsm>(5); 181 * <jk>int</jk> <jv>current</jv> = <jv>counter</jv>.getAndIncrement(); <jc>// Returns 5</jc> 182 * <jk>int</jk> <jv>next</jv> = <jv>counter</jv>.get(); <jc>// Returns 6</jc> 183 * </p> 184 * 185 * @return The value before it was incremented. 186 */ 187 public Integer getAndIncrement() { 188 var v = get(); 189 var result = v == null ? 0 : v; 190 set(result + 1); 191 return result; 192 } 193 194 /** 195 * Increments the value by 1. 196 * 197 * <h5 class='section'>Example:</h5> 198 * <p class='bjava'> 199 * IntegerValue <jv>counter</jv> = IntegerValue.<jsm>of</jsm>(5); 200 * <jv>counter</jv>.increment(); 201 * <jsm>assertEquals</jsm>(6, <jv>counter</jv>.get()); 202 * </p> 203 * 204 * @return This object. 205 */ 206 public IntegerValue increment() { 207 set(get() + 1); 208 return this; 209 } 210 211 /** 212 * Increments the value by 1 and returns the new value. 213 * 214 * <h5 class='section'>Example:</h5> 215 * <p class='bjava'> 216 * IntegerValue <jv>counter</jv> = IntegerValue.<jsm>of</jsm>(5); 217 * <jk>int</jk> <jv>result</jv> = <jv>counter</jv>.incrementAndGet(); <jc>// Returns 6</jc> 218 * <jsm>assertEquals</jsm>(6, <jv>counter</jv>.get()); 219 * </p> 220 * 221 * @return The incremented value. 222 */ 223 public Integer incrementAndGet() { 224 set(get() + 1); 225 return get(); 226 } 227 228 /** 229 * Checks if the current value is equal to the specified value. 230 * 231 * <p> 232 * Uses {@link org.apache.juneau.commons.utils.Utils#eq(Object, Object)} for deep equality comparison, which handles nulls safely. 233 * 234 * <h5 class='section'>Example:</h5> 235 * <p class='bjava'> 236 * IntegerValue <jv>value</jv> = IntegerValue.<jsm>of</jsm>(42); 237 * <jsm>assertTrue</jsm>(<jv>value</jv>.is(42)); 238 * <jsm>assertFalse</jsm>(<jv>value</jv>.is(43)); 239 * </p> 240 * 241 * @param value The value to compare to. 242 * @return <jk>true</jk> if the current value is equal to the specified value. 243 */ 244 public boolean is(Integer value) { 245 return eq(get(), value); 246 } 247 248 /** 249 * Checks if the current value matches any of the specified values. 250 * 251 * <p> 252 * Uses {@link org.apache.juneau.commons.utils.Utils#eq(Object, Object)} for deep equality comparison of each value. 253 * 254 * <h5 class='section'>Example:</h5> 255 * <p class='bjava'> 256 * IntegerValue <jv>value</jv> = IntegerValue.<jsm>of</jsm>(5); 257 * <jsm>assertTrue</jsm>(<jv>value</jv>.isAny(3, 5, 7)); 258 * <jsm>assertFalse</jsm>(<jv>value</jv>.isAny(1, 2)); 259 * </p> 260 * 261 * @param values The values to compare to. 262 * @return <jk>true</jk> if the current value matches any of the specified values. 263 */ 264 public boolean isAny(Integer...values) { 265 assertArgNotNull("values", values); 266 var current = get(); 267 for (var value : values) 268 if (eq(current, value)) 269 return true; 270 return false; 271 } 272}