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