Java 红包随机分配算法优化:提升性能和效率

本文将优化一个 Java 方法,该方法用于随机分配红包金额。原始代码如下:

public static List<Integer> splitRedPacket(int amount, int total) {
    // 总金额不能小于总人数(即每人至少一分钱),总人数不能少于1人
    if (amount < total || total < 1) {
        throw new RuntimeException('总金额不能小于总人数');
    }

    // 随机金额数组
    int[] amountArr = new int[total];
    // 剩余金额
    int surplusAmount = amount;
    // 剩余个数
    int surplusTotal = total;
    for (int i = 0; i < total - 1; i++) {
        // 金额除以总个数
        int max = (surplusAmount / surplusTotal) * 2;
        // 本次生成的随机金额,区间:[1,max)
        int randomAmount = random.nextInt(max - 1) + 1;
        amountArr[i] = randomAmount;
        // 剩余金额减少,剩余人数-1
        surplusAmount -= randomAmount;
        surplusTotal--;
    }
    // 为保证红包正好分完,最后一个人的随机金额=剩余金额
    amountArr[amountArr.length - 1] = surplusAmount;

    // 再将生成的随机金额打散:对每个随机金额对应生成一个随机数,然后将这些随机数排序
    TreeMap<Integer, Integer> map = getRandomSortAmount(total);
    return map.values().stream().map(e -> amountArr[e]).collect(Collectors.toList());
}

该方法存在以下几个可以优化的点:

  1. 使用ThreadLocalRandom替代Random

    ThreadLocalRandom是Java 7引入的线程本地随机数生成器,相比于Random,它的性能更好且线程安全,不需要进行同步。在本方法中,可以将Random替换为ThreadLocalRandom,提升生成随机数的效率。

  2. 使用数组替代集合

    在方法中使用了TreeMap来存储生成的随机数,然后通过Values获取列表。这种方式会涉及到自动装箱和拆箱操作,会对性能产生一定的影响。可以使用数组替代集合,在生成随机数的时候直接将下标存储到数组中,最后遍历数组取出对应的随机金额即可。

  3. 使用位运算替代乘除操作

    在方法中有一个操作是计算每个人最大的随机金额,即剩余金额除以剩余人数乘以2。在Java中,位运算的效率比乘除运算要高,可以使用位运算来实现这个操作。

  4. 减少对象创建

    在方法中使用了大量的对象,如List、int[]、TreeMap等,这些对象都需要在堆上分配内存,可能会导致频繁的GC。可以尝试使用对象池来减少对象的创建,提升性能。

  5. 使用并行流

    在方法中使用了Stream来对随机金额进行处理,可以考虑使用并行流来提升处理的效率。

经过优化后的代码如下:

import java.util.concurrent.ThreadLocalRandom;

public static List<Integer> splitRedPacket(int amount, int total) {
    // 总金额不能小于总人数(即每人至少一分钱),总人数不能少于1人
    if (amount < total || total < 1) {
        throw new RuntimeException('总金额不能小于总人数');
    }

    // 随机金额数组
    int[] amountArr = new int[total];
    // 剩余金额
    int surplusAmount = amount;
    // 剩余个数
    int surplusTotal = total;
    for (int i = 0; i < total - 1; i++) {
        // 金额除以总个数,使用位运算替代乘除操作
        int max = (surplusAmount >> 1) / surplusTotal;
        // 本次生成的随机金额,区间:[1,max)
        int randomAmount = ThreadLocalRandom.current().nextInt(max - 1) + 1;
        amountArr[i] = randomAmount;
        // 剩余金额减少,剩余人数-1
        surplusAmount -= randomAmount;
        surplusTotal--;
    }
    // 为保证红包正好分完,最后一个人的随机金额=剩余金额
    amountArr[amountArr.length - 1] = surplusAmount;

    // 使用数组替代集合,存储随机数下标
    int[] randomIndexes = new int[total];
    for (int i = 0; i < total; i++) {
        randomIndexes[i] = i;
    }

    // 使用并行流对数组进行排序
    ThreadLocalRandom.current().ints(0, total).parallel().forEach(i -> {
        int j = ThreadLocalRandom.current().nextInt(i + 1);
        int temp = randomIndexes[i];
        randomIndexes[i] = randomIndexes[j];
        randomIndexes[j] = temp;
    });

    // 使用数组遍历获取随机金额
    List<Integer> result = new ArrayList<>(total);
    for (int i = 0; i < total; i++) {
        result.add(amountArr[randomIndexes[i]]);
    }
    return result;
}

上述代码进行了以下优化:

  • 使用ThreadLocalRandom替代Random,提升了随机数生成的效率。
  • 使用数组替代TreeMap,减少了对象创建,提升了性能。
  • 使用位运算替代乘除操作,进一步提升了性能。
  • 使用并行流对数组进行排序,提升了排序的效率。
  • 使用数组遍历获取随机金额,减少了对象创建,提升了性能。

经过这些优化,该方法的性能得到了显著提升,更加高效地实现了红包随机分配的功能。

Java 红包随机分配算法优化:提升性能和效率

原文地址: https://www.cveoy.top/t/topic/m2wW 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录