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.commons.lang3; 018 019import java.util.Random; 020 021/** 022 * <p>Utility library that supplements the standard {@link Random} class.</p> 023 * 024 * <p>Caveat: Instances of {@link Random} are not cryptographically secure.</p> 025 * 026 * <p>Please note that the Apache Commons project provides a component 027 * dedicated to pseudo-random number generation, namely 028 * <a href="https://commons.apache.org/rng">Commons RNG</a>, that may be 029 * a better choice for applications with more stringent requirements 030 * (performance and/or correctness).</p> 031 * 032 * @since 3.3 033 */ 034public class RandomUtils { 035 036 /** 037 * Random object used by random method. This has to be not local to the 038 * random method so as to not return the same value in the same millisecond. 039 */ 040 private static final Random RANDOM = new Random(); 041 042 /** 043 * <p> 044 * {@code RandomUtils} instances should NOT be constructed in standard 045 * programming. Instead, the class should be used as 046 * {@code RandomUtils.nextBytes(5);}. 047 * </p> 048 * 049 * <p> 050 * This constructor is public to permit tools that require a JavaBean 051 * instance to operate. 052 * </p> 053 */ 054 public RandomUtils() { 055 } 056 057 /** 058 * <p> 059 * Returns a random boolean value 060 * </p> 061 * 062 * @return the random boolean 063 * @since 3.5 064 */ 065 public static boolean nextBoolean() { 066 return RANDOM.nextBoolean(); 067 } 068 069 /** 070 * <p> 071 * Creates an array of random bytes. 072 * </p> 073 * 074 * @param count 075 * the size of the returned array 076 * @return the random byte array 077 * @throws IllegalArgumentException if {@code count} is negative 078 */ 079 public static byte[] nextBytes(final int count) { 080 Validate.isTrue(count >= 0, "Count cannot be negative."); 081 082 final byte[] result = new byte[count]; 083 RANDOM.nextBytes(result); 084 return result; 085 } 086 087 /** 088 * <p> 089 * Returns a random integer within the specified range. 090 * </p> 091 * 092 * @param startInclusive 093 * the smallest value that can be returned, must be non-negative 094 * @param endExclusive 095 * the upper bound (not included) 096 * @throws IllegalArgumentException 097 * if {@code startInclusive > endExclusive} or if 098 * {@code startInclusive} is negative 099 * @return the random integer 100 */ 101 public static int nextInt(final int startInclusive, final int endExclusive) { 102 Validate.isTrue(endExclusive >= startInclusive, 103 "Start value must be smaller or equal to end value."); 104 Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative."); 105 106 if (startInclusive == endExclusive) { 107 return startInclusive; 108 } 109 110 return startInclusive + RANDOM.nextInt(endExclusive - startInclusive); 111 } 112 113 /** 114 * <p> Returns a random int within 0 - Integer.MAX_VALUE </p> 115 * 116 * @return the random integer 117 * @see #nextInt(int, int) 118 * @since 3.5 119 */ 120 public static int nextInt() { 121 return nextInt(0, Integer.MAX_VALUE); 122 } 123 124 /** 125 * <p> 126 * Returns a random long within the specified range. 127 * </p> 128 * 129 * @param startInclusive 130 * the smallest value that can be returned, must be non-negative 131 * @param endExclusive 132 * the upper bound (not included) 133 * @throws IllegalArgumentException 134 * if {@code startInclusive > endExclusive} or if 135 * {@code startInclusive} is negative 136 * @return the random long 137 */ 138 public static long nextLong(final long startInclusive, final long endExclusive) { 139 Validate.isTrue(endExclusive >= startInclusive, 140 "Start value must be smaller or equal to end value."); 141 Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative."); 142 143 if (startInclusive == endExclusive) { 144 return startInclusive; 145 } 146 147 return startInclusive + nextLong(endExclusive - startInclusive); 148 } 149 150 /** 151 * <p> Returns a random long within 0 - Long.MAX_VALUE </p> 152 * 153 * @return the random long 154 * @see #nextLong(long, long) 155 * @since 3.5 156 */ 157 public static long nextLong() { 158 return nextLong(Long.MAX_VALUE); 159 } 160 161 /** 162 * Generates a {@code long} value between 0 (inclusive) and the specified 163 * value (exclusive). 164 * 165 * @param n Bound on the random number to be returned. Must be positive. 166 * @return a random {@code long} value between 0 (inclusive) and {@code n} 167 * (exclusive). 168 */ 169 private static long nextLong(final long n) { 170 // Extracted from o.a.c.rng.core.BaseProvider.nextLong(long) 171 long bits; 172 long val; 173 do { 174 bits = RANDOM.nextLong() >>> 1; 175 val = bits % n; 176 } while (bits - val + (n - 1) < 0); 177 178 return val; 179 } 180 181 /** 182 * <p> 183 * Returns a random double within the specified range. 184 * </p> 185 * 186 * @param startInclusive 187 * the smallest value that can be returned, must be non-negative 188 * @param endExclusive 189 * the upper bound (not included) 190 * @throws IllegalArgumentException 191 * if {@code startInclusive > endExclusive} or if 192 * {@code startInclusive} is negative 193 * @return the random double 194 */ 195 public static double nextDouble(final double startInclusive, final double endExclusive) { 196 Validate.isTrue(endExclusive >= startInclusive, 197 "Start value must be smaller or equal to end value."); 198 Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative."); 199 200 if (startInclusive == endExclusive) { 201 return startInclusive; 202 } 203 204 return startInclusive + ((endExclusive - startInclusive) * RANDOM.nextDouble()); 205 } 206 207 /** 208 * <p> Returns a random double within 0 - Double.MAX_VALUE </p> 209 * 210 * @return the random double 211 * @see #nextDouble(double, double) 212 * @since 3.5 213 */ 214 public static double nextDouble() { 215 return nextDouble(0, Double.MAX_VALUE); 216 } 217 218 /** 219 * <p> 220 * Returns a random float within the specified range. 221 * </p> 222 * 223 * @param startInclusive 224 * the smallest value that can be returned, must be non-negative 225 * @param endExclusive 226 * the upper bound (not included) 227 * @throws IllegalArgumentException 228 * if {@code startInclusive > endExclusive} or if 229 * {@code startInclusive} is negative 230 * @return the random float 231 */ 232 public static float nextFloat(final float startInclusive, final float endExclusive) { 233 Validate.isTrue(endExclusive >= startInclusive, 234 "Start value must be smaller or equal to end value."); 235 Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative."); 236 237 if (startInclusive == endExclusive) { 238 return startInclusive; 239 } 240 241 return startInclusive + ((endExclusive - startInclusive) * RANDOM.nextFloat()); 242 } 243 244 /** 245 * <p> Returns a random float within 0 - Float.MAX_VALUE </p> 246 * 247 * @return the random float 248 * @see #nextFloat(float, float) 249 * @since 3.5 250 */ 251 public static float nextFloat() { 252 return nextFloat(0, Float.MAX_VALUE); 253 } 254}