001/* 002 * Copyright 2023 the original author or authors. 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package de.cuioss.tools.collect; 017 018import static de.cuioss.tools.base.Preconditions.checkArgument; 019 020import java.util.Collection; 021import java.util.Iterator; 022import java.util.Map; 023import java.util.stream.Stream; 024 025import lombok.experimental.UtilityClass; 026 027/** 028 * <h2>Overview</h2> Utility Methods for Collections and some types to be used 029 * in the context of Collections. 030 * 031 * <h3>isEmpty()</h3> The overloaded method 032 * {@link MoreCollections#isEmpty(Collection)} checks all kinds of Collections / 033 * varargs parameter for not being null and emptiness. In case of 034 * {@link Stream}s it solely checks for being not null in order not to consume 035 * it. 036 * 037 * <h3>requireNotEmpty()</h3> The overloaded method 038 * {@link MoreCollections#requireNotEmpty(Collection)} checks all kinds of 039 * Collections / varargs parameter for not being null nor empty. In case of 040 * being null / empty they will throw an {@link IllegalArgumentException} 041 * 042 * <h3>Map Difference</h3> The method 043 * {@link MoreCollections#difference(Map, Map)} creates an {@link MapDifference} 044 * view on the two given maps in order to check, well whether they are equal or 045 * not and if not which elements are differing. 046 * 047 * <h3>Map contains key</h3> Check whether the given Map contains at least one 048 * of the given keys (varags) 049 * 050 * @author Oliver Wolff 051 * 052 */ 053@UtilityClass 054public final class MoreCollections { 055 056 /** 057 * Simple check method for a {@code null} safe check of the emptiness of the 058 * given varags-parameter. 059 * 060 * @param elements to be checked, may be null 061 * @return {@code true} is the given elements are {@code null} or {@code empty} 062 */ 063 public static boolean isEmpty(Object... elements) { 064 return null == elements || 0 == elements.length; 065 } 066 067 /** 068 * Simple check method for a {@code null} safe check of the emptiness of the 069 * given parameter. 070 * 071 * @param elements to be checked, may be null 072 * @return {@code true} is the given elements are {@code null} or {@code empty} 073 */ 074 public static boolean isEmpty(Iterable<?> elements) { 075 return null == elements || isEmpty(elements.iterator()); 076 } 077 078 /** 079 * Simple check method for a {@code null} safe check of the emptiness of the 080 * given parameter. 081 * 082 * @param elements to be checked, may be null 083 * @return {@code true} is the given elements are {@code null} or {@code empty} 084 */ 085 public static boolean isEmpty(Collection<?> elements) { 086 return null == elements || elements.isEmpty(); 087 } 088 089 /** 090 * Simple check method for a {@code null} safe check of the emptiness of the 091 * given parameter. 092 * 093 * @param map to be checked, may be null 094 * @return {@code true} is the given elements are {@code null} or {@code empty} 095 */ 096 public static boolean isEmpty(Map<?, ?> map) { 097 return null == map || map.isEmpty(); 098 } 099 100 /** 101 * Simple check method for a {@code null} safe check of the emptiness of the 102 * given parameter. 103 * 104 * @param elements to be checked, may be null 105 * @return {@code true} is the given elements are {@code null} or {@code empty} 106 */ 107 public static boolean isEmpty(Iterator<?> elements) { 108 return null == elements || !elements.hasNext(); 109 } 110 111 /** 112 * Shorthand for checking whether the given elements are empty or not. 113 * 114 * @param <T> identifying the type to be checked 115 * @param elements to be checked 116 * @return the given parameter 117 * @throws IllegalArgumentException in case the given elements are {@code null} 118 * or empty 119 */ 120 @SafeVarargs 121 public static <T> T[] requireNotEmpty(T... elements) { 122 checkArgument(!isEmpty(elements)); 123 return elements; 124 } 125 126 /** 127 * Shorthand for checking whether the given elements are empty or not. 128 * 129 * @param <T> identifying the type to be checked 130 * @param elements to be checked 131 * @return the given parameter 132 * @throws IllegalArgumentException in case the given elements are {@code null} 133 * or empty 134 */ 135 public static <T> Collection<T> requireNotEmpty(Collection<T> elements) { 136 checkArgument(!isEmpty(elements)); 137 return elements; 138 } 139 140 /** 141 * Shorthand for checking whether the given elements are empty or not. 142 * 143 * @param <T> identifying the type to be checked 144 * @param elements to be checked 145 * @param message to be set in error-case 146 * @return the given parameter 147 * @throws IllegalArgumentException in case the given elements are {@code null} 148 * or empty 149 */ 150 public static <T> Collection<T> requireNotEmpty(Collection<T> elements, String message) { 151 checkArgument(!isEmpty(elements), message); 152 return elements; 153 } 154 155 /** 156 * Shorthand for checking whether the given elements are empty or not. 157 * 158 * @param <K> the type for the key 159 * @param <V> the type for the value 160 * @param elements to be checked 161 * @return the given parameter 162 * @throws IllegalArgumentException in case the given elements are {@code null} 163 * or empty 164 */ 165 public static <K, V> Map<K, V> requireNotEmpty(Map<K, V> elements) { 166 checkArgument(!isEmpty(elements)); 167 return elements; 168 } 169 170 /** 171 * Shorthand for checking whether the given elements are empty or not. 172 * 173 * @param <K> the type for the key 174 * @param <V> the type for the value 175 * @param elements to be checked 176 * @param message to be set in error-case 177 * @return the given parameter 178 * @throws IllegalArgumentException in case the given elements are {@code null} 179 * or empty 180 */ 181 public static <K, V> Map<K, V> requireNotEmpty(Map<K, V> elements, String message) { 182 checkArgument(!isEmpty(elements), message); 183 return elements; 184 } 185 186 /** 187 * Shorthand for checking whether the given elements are empty or not. 188 * 189 * @param <T> identifying the type to be checked 190 * @param elements to be checked 191 * @return the given parameter 192 * @throws IllegalArgumentException in case the given elements are {@code null} 193 * or empty 194 */ 195 public static <T> Iterable<T> requireNotEmpty(Iterable<T> elements) { 196 checkArgument(!isEmpty(elements)); 197 return elements; 198 } 199 200 /** 201 * Shorthand for checking whether the given elements are empty or not. 202 * 203 * @param <T> identifying the type to be checked 204 * @param elements to be checked 205 * @param message to be set in error-case 206 * @return the given parameter 207 * @throws IllegalArgumentException in case the given elements are {@code null} 208 * or empty 209 */ 210 public static <T> Iterable<T> requireNotEmpty(Iterable<T> elements, String message) { 211 checkArgument(!isEmpty(elements), message); 212 return elements; 213 } 214 215 /** 216 * Shorthand for checking whether the given elements are empty or not. 217 * 218 * @param elements to be checked 219 * @return the given parameter 220 * @throws IllegalArgumentException in case the given elements are {@code null} 221 * or empty 222 */ 223 public static <T> Iterator<T> requireNotEmpty(Iterator<T> elements) { 224 checkArgument(!isEmpty(elements)); 225 return elements; 226 } 227 228 /** 229 * Shorthand for checking whether the given elements are empty or not. 230 * 231 * @param <T> identifying the type to be checked 232 * @param elements to be checked 233 * @param message to be set in error-case 234 * @return the given parameter 235 * @throws IllegalArgumentException in case the given elements are {@code null} 236 * or empty 237 */ 238 public static <T> Iterator<T> requireNotEmpty(Iterator<T> elements, String message) { 239 checkArgument(!isEmpty(elements), message); 240 return elements; 241 } 242 243 /** 244 * Shorthand for checking whether the given elements are empty or not. 245 * <em>Caution: </em> In order not to consume the stream only a null check will 246 * be performed. 247 * 248 * @param <T> identifying the type to be checked 249 * @param elements to be checked 250 * @return the given parameter 251 * @throws IllegalArgumentException in case the given elements are {@code null} 252 */ 253 public static <T> Stream<T> requireNotEmpty(Stream<T> elements) { 254 checkArgument(!isEmpty(elements)); 255 return elements; 256 } 257 258 /** 259 * Shorthand for checking whether the given elements are empty or not. 260 * <em>Caution: </em> In order not to consume the stream only a null check will 261 * be performed. 262 * 263 * @param <T> identifying the type to be checked 264 * @param elements to be checked 265 * @param message to be set in error-case 266 * @return the given parameter 267 * @throws IllegalArgumentException in case the given elements are {@code null} 268 */ 269 public static <T> Stream<T> requireNotEmpty(Stream<T> elements, String message) { 270 checkArgument(!isEmpty(elements), message); 271 return elements; 272 } 273 274 /** 275 * Simple check method for a {@code null} safe check of the emptiness of the 276 * given parameter. <em>Caution: </em> In order not to consume the stream only a 277 * null check will be performed. 278 * 279 * @param elements to be checked, may be null 280 * @return {@code true} is the given elements are {@code null}. The Stream 281 * content will be untouched 282 * @throws IllegalArgumentException in case the given elements are {@code null} 283 */ 284 public static boolean isEmpty(Stream<?> elements) { 285 return null == elements; 286 } 287 288 /** 289 * Checks whether the given map contains at least one of the given keys to be 290 * checked. 291 * 292 * @param map to be checked. If it is {@code null} or empty the method will 293 * always return {@code false} 294 * @param keys to be checked. If it is {@code null} or empty the method will 295 * always return {@code false} 296 * @return {@code true} if the map contains at lest one of the given keys, 297 * {@code false} otherwise 298 */ 299 public static boolean containsKey(Map<?, ?> map, Object... keys) { 300 if (isEmpty(map) || isEmpty(keys)) { 301 return false; 302 } 303 for (Object key : keys) { 304 if (map.containsKey(key)) { 305 return true; 306 } 307 } 308 return false; 309 } 310 311 /** 312 * Computes the difference between two maps. This difference is an immutable 313 * snapshot of the state of the maps at the time this method is called. It will 314 * never change, even if the maps change at a later time. 315 * 316 * <p> 317 * Since this method uses {@code HashMap} instances internally, the keys of the 318 * supplied maps must be well-behaved with respect to {@link Object#equals} and 319 * {@link Object#hashCode}. 320 * 321 * <p> 322 * <b>Note:</b>If you only need to know whether two maps have the same mappings, 323 * call {@code 324 * left.equals(right)} instead of this method. 325 * 326 * @param <K> the type for the key 327 * @param <V> the type for the value 328 * @param left the map to treat as the "left" map for purposes of comparison, 329 * must not be null 330 * @param right the map to treat as the "right" map for purposes of comparison , 331 * must not be null 332 * @return the difference between the two maps 333 * 334 * @author com.google.common.collect.MapDifference<K, V> 335 */ 336 public static <K, V> MapDifference<K, V> difference(Map<? extends K, ? extends V> left, 337 Map<? extends K, ? extends V> right) { 338 return MapDiffenceImpl.from(left, right); 339 } 340 341}