    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 * @since 3.3
    025 */
    026public class RandomUtils {
    027
    028    /**
    029     * Random object used by random method. This has to be not local to the
    030     * random method so as to not return the same value in the same millisecond.
    031     */
    032    private static final Random RANDOM = new Random();
    033
    034    /**
    035     * <p>
    036     * {@code RandomUtils} instances should NOT be constructed in standard
    037     * programming. Instead, the class should be used as
    038     * {@code RandomUtils.nextBytes(5);}.
    039     * </p>
    040     *
    041     * <p>
    042     * This constructor is public to permit tools that require a JavaBean
    043     * instance to operate.
    044     * </p>
    045     */
    046    public RandomUtils() {
    047        super();
    048    }
    049
    050    /**
    051     * <p>
    052     * Returns a random boolean value
    053     * </p>
    054     *
    055     * @return the random boolean
    056     * @since 3.5
    057     */
    058    public static boolean nextBoolean() {
    059        return RANDOM.nextBoolean();
    060    }
    061
    062    /**
    063     * <p>
    064     * Creates an array of random bytes.
    065     * </p>
    066     *
    067     * @param count
    068     *            the size of the returned array
    069     * @return the random byte array
    070     * @throws IllegalArgumentException if {@code count} is negative
    071     */
    072    public static byte[] nextBytes(final int count) {
    073        Validate.isTrue(count >= 0, "Count cannot be negative.");
    074
    075        final byte[] result = new byte[count];
    076        RANDOM.nextBytes(result);
    077        return result;
    078    }
    079
    080    /**
    081     * <p>
    082     * Returns a random integer within the specified range.
    083     * </p>
    084     *
    085     * @param startInclusive
    086     *            the smallest value that can be returned, must be non-negative
    087     * @param endExclusive
    088     *            the upper bound (not included)
    089     * @throws IllegalArgumentException
    090     *             if {@code startInclusive > endExclusive} or if
    091     *             {@code startInclusive} is negative
    092     * @return the random integer
    093     */
    094    public static int nextInt(final int startInclusive, final int endExclusive) {
    095        Validate.isTrue(endExclusive >= startInclusive,
    096                "Start value must be smaller or equal to end value.");
    097        Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
    098
    099        if (startInclusive == endExclusive) {
    100            return startInclusive;
    101        }
    102
    103        return startInclusive + RANDOM.nextInt(endExclusive - startInclusive);
    104    }
    105
    106    /**
    107     * <p> Returns a random int within 0 - Integer.MAX_VALUE </p>
    108     *
    109     * @return the random integer
    110     * @see #nextInt(int, int)
    111     * @since 3.5
    112     */
    113    public static int nextInt() {
    114        return nextInt(0, Integer.MAX_VALUE);
    115    }
    116
    117    /**
    118     * <p>
    119     * Returns a random long within the specified range.
    120     * </p>
    121     *
    122     * @param startInclusive
    123     *            the smallest value that can be returned, must be non-negative
    124     * @param endExclusive
    125     *            the upper bound (not included)
    126     * @throws IllegalArgumentException
    127     *             if {@code startInclusive > endExclusive} or if
    128     *             {@code startInclusive} is negative
    129     * @return the random long
    130     */
    131    public static long nextLong(final long startInclusive, final long endExclusive) {
    132        Validate.isTrue(endExclusive >= startInclusive,
    133                "Start value must be smaller or equal to end value.");
    134        Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
    135
    136        if (startInclusive == endExclusive) {
    137            return startInclusive;
    138        }
    139
    140        return (long) nextDouble(startInclusive, endExclusive);
    141    }
    142
    143    /**
    144     * <p> Returns a random long within 0 - Long.MAX_VALUE </p>
    145     *
    146     * @return the random long
    147     * @see #nextLong(long, long)
    148     * @since 3.5
    149     */
    150    public static long nextLong() {
    151        return nextLong(0, Long.MAX_VALUE);
    152    }
    153
    154    /**
    155     * <p>
    156     * Returns a random double within the specified range.
    157     * </p>
    158     *
    159     * @param startInclusive
    160     *            the smallest value that can be returned, must be non-negative
    161     * @param endInclusive
    162     *            the upper bound (included)
    163     * @throws IllegalArgumentException
    164     *             if {@code startInclusive > endInclusive} or if
    165     *             {@code startInclusive} is negative
    166     * @return the random double
    167     */
    168    public static double nextDouble(final double startInclusive, final double endInclusive) {
    169        Validate.isTrue(endInclusive >= startInclusive,
    170                "Start value must be smaller or equal to end value.");
    171        Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
    172
    173        if (startInclusive == endInclusive) {
    174            return startInclusive;
    175        }
    176
    177        return startInclusive + ((endInclusive - startInclusive) * RANDOM.nextDouble());
    178    }
    179
    180    /**
    181     * <p> Returns a random double within 0 - Double.MAX_VALUE </p>
    182     *
    183     * @return the random double
    184     * @see #nextDouble(double, double)
    185     * @since 3.5
    186     */
    187    public static double nextDouble() {
    188        return nextDouble(0, Double.MAX_VALUE);
    189    }
    190
    191    /**
    192     * <p>
    193     * Returns a random float within the specified range.
    194     * </p>
    195     *
    196     * @param startInclusive
    197     *            the smallest value that can be returned, must be non-negative
    198     * @param endInclusive
    199     *            the upper bound (included)
    200     * @throws IllegalArgumentException
    201     *             if {@code startInclusive > endInclusive} or if
    202     *             {@code startInclusive} is negative
    203     * @return the random float
    204     */
    205    public static float nextFloat(final float startInclusive, final float endInclusive) {
    206        Validate.isTrue(endInclusive >= startInclusive,
    207                "Start value must be smaller or equal to end value.");
    208        Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative.");
    209
    210        if (startInclusive == endInclusive) {
    211            return startInclusive;
    212        }
    213
    214        return startInclusive + ((endInclusive - startInclusive) * RANDOM.nextFloat());
    215    }
    216
    217    /**
    218     * <p> Returns a random float within 0 - Float.MAX_VALUE </p>
    219     *
    220     * @return the random float
    221     * @see #nextFloat()
    222     * @since 3.5
    223     */
    224    public static float nextFloat() {
    225        return nextFloat(0, Float.MAX_VALUE);
    226    }
    227}