如何优雅地用List中的动物元素随机填充二维Cell数组?
问题描述
我有一个Cell类型的二维数组:public static Cell[][] island = new Cell[3][3];,每个Cell包含x、y坐标以及栖息其中的动物列表。我需要用public static List<Alive> allanimals = new ArrayList<>();列表中的动物随机填充这个数组。
我写了列表生成与填充的代码,但最终得到大量空单元格,而且觉得animalsInCell = allanimals.subList(initialcount, initialcount + randomdata);这段实现不够优雅。请问如何正确用allanimals里的元素填充Island数组?
我的Cell类定义如下:
@Data @AllArgsConstructor public class Cell extends Thread{ private int x; private int y; public List<Alive> animals; // method run() }
原填充代码:
public static void generateIsland() { for (int i = 0; i < 10; i++) { int random = (int) (Math.random() * 100); if (random < 50) { allanimals.add(new Bear(500,5,0,0)); } else { allanimals.add(new Sheep(70,0,0)); } } System.out.println("Randomly create all animals list" + allanimals); int initialcount = 0; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { try { int randomdata = r.nextInt(0, allanimals.size() ); List<Alive> animalsInCell = new ArrayList<>(); animalsInCell = allanimals.subList(initialcount, initialcount + randomdata); initialcount += randomdata; island[i][j] = new Cell(i, j, animalsInCell); } catch (Exception e) { island[i][j] = new Cell(i, j, new ArrayList<Alive>()); } } } }
问题分析
- 原代码中
randomdata取值范围是0到allanimals.size(),极易出现initialcount + randomdata超出列表长度的情况,触发异常后进入catch块生成空单元格。 subList返回的是原列表的视图,并非独立新列表,后续修改allanimals会同步影响单元格内的动物列表,不符合业务隔离需求。- 分配逻辑无约束,可能前几个单元格就耗尽所有动物,导致后续单元格全部为空。
优化方案
方案一:随机分配单只动物到单元格(简单直观)
每只动物随机分配到一个单元格,逻辑简单且避免空单元格(只要动物数量>0):
import java.util.Random; public static void generateIsland() { Random random = new Random(); // 生成动物列表 for (int i = 0; i < 10; i++) { if (random.nextBoolean()) { // 50%概率生成Bear,50%生成Sheep allanimals.add(new Bear(500, 5, 0, 0)); } else { allanimals.add(new Sheep(70, 0, 0)); } } System.out.println("Randomly create all animals list: " + allanimals); // 先初始化所有单元格的空动物列表 for (int i = 0; i < island.length; i++) { for (int j = 0; j < island[i].length; j++) { island[i][j] = new Cell(i, j, new ArrayList<>()); } } // 随机分配每只动物到某个单元格 for (Alive animal : allanimals) { int x = random.nextInt(island.length); int y = random.nextInt(island[0].length); island[x][y].getAnimals().add(animal); } }
方案二:随机划分动物到所有单元格(无动物剩余)
确保所有动物都被分配,且每个单元格的动物数量随机分布:
import java.util.ArrayList; import java.util.Collections; import java.util.Random; public static void generateIsland() { Random random = new Random(); // 生成动物列表 for (int i = 0; i < 10; i++) { if (random.nextBoolean()) { allanimals.add(new Bear(500, 5, 0, 0)); } else { allanimals.add(new Sheep(70, 0, 0)); } } System.out.println("Randomly create all animals list: " + allanimals); // 打乱动物列表,让分配更随机 Collections.shuffle(allanimals); int totalCells = island.length * island[0].length; int animalIndex = 0; // 遍历所有单元格分配动物 for (int i = 0; i < island.length; i++) { for (int j = 0; j < island[i].length; j++) { // 最后一个单元格拿走剩余所有动物 if (i == island.length - 1 && j == island[i].length - 1) { List<Alive> remainingAnimals = new ArrayList<>(allanimals.subList(animalIndex, allanimals.size())); island[i][j] = new Cell(i, j, remainingAnimals); } else { // 计算剩余单元格数量,避免提前耗尽动物 int remainingCells = totalCells - (i * island[i].length + j + 1); int maxAssign = allanimals.size() - animalIndex - remainingCells; int assignCount = maxAssign > 0 ? random.nextInt(1, maxAssign + 1) : 0; // 用新ArrayList包装subList结果,脱离原列表关联 List<Alive> cellAnimals = new ArrayList<>(allanimals.subList(animalIndex, animalIndex + assignCount)); island[i][j] = new Cell(i, j, cellAnimals); animalIndex += assignCount; } } } }
关键注意点
- 永远不要直接将
subList的返回值作为Cell的动物列表,必须用new ArrayList<>(subListResult)包装,避免和原列表产生关联。 - 确保
Random实例的线程安全性,建议在方法内声明或作为类成员变量初始化。 - 若要完全避免空单元格,可调整方案二的
assignCount最小值为1,同时保证动物数量≥单元格总数(9只)。
内容的提问来源于stack exchange,提问作者SoN
相关产品推荐
相关产品推荐

