Java 如何洗牌ArrayList,但洗牌后特定索引保持不变?

Java 如何洗牌ArrayList,但洗牌后特定索引保持不变?,java,arraylist,Java,Arraylist,在我的ArrayList中,每个数字都根据其在ArrayList中的位置指定了颜色。奇数索引中的数字为红色,偶数索引中的数字为蓝色,10的倍数索引中的数字为黑色。我需要对列表进行洗牌,这样在洗牌之后,红色的数字仍然是奇数索引,蓝色的数字仍然是偶数索引,黑色的数字仍然是十个索引的倍数。我知道如何洗牌整个列表,但不知道像这样的具体事情。我该怎么做呢 以下是上下文的代码: /*学期2作业5-游戏轮*/ /*游戏轮类*/ 导入java.util.*; 导入java.lang.*; 公共类游戏机 { //

在我的ArrayList中,每个数字都根据其在ArrayList中的位置指定了颜色。奇数索引中的数字为红色,偶数索引中的数字为蓝色,10的倍数索引中的数字为黑色。我需要对列表进行洗牌,这样在洗牌之后,红色的数字仍然是奇数索引,蓝色的数字仍然是偶数索引,黑色的数字仍然是十个索引的倍数。我知道如何洗牌整个列表,但不知道像这样的具体事情。我该怎么做呢

以下是上下文的代码:

/*学期2作业5-游戏轮*/ /*游戏轮类*/ 导入java.util.*; 导入java.lang.*; 公共类游戏机 { //组成轮子的切片列表 私有列表切片; //当前选定切片在控制盘上的位置 私人国际邮政局; /*创建一个包含40个预设切片的控制盘,然后将其随机保留 *颜色图案相同。 */ 公共游戏机 { 切片=新阵列列表; currentPos=0; 初始游戏轮; 爬 } /*旋转滚轮,以便选择不同的切片。返回该值 *切片注意:当前切片后面的20个切片更有可能 *比其他20人还多。 */ 公共切片转盘 { //自旋功率范围为1-100(含1-100) 整数幂=intMath.random*100+1; int newPos=currentPos+power%s.size; currentPos=newPos; 返回slices.getcurrentPos; } /*构造函数的助手方法。随机化切片的位置 *在轮子上,但不改变颜色的图案 *也就是说,红色切片仍处于奇数索引,黑色切片处于奇数索引 *10的倍数,以及所有其他偶数指数的蓝色切片。 */ 私人空间争夺 { } //Helper方法,用于初始化控制盘中的切片 私人游戏机 { slices.addnew Sliceblack,8000; 对于int i=1;i<40;i++ { 如果i%2==1 slices.addnew Slicered,i*10; 否则,如果i%10==0 slices.addnew Sliceblack,i*200; 其他的 slices.addnew Sliceblue,i*100; } } //返回此GameWheel的切片列表 公共列表{ 返回切片; } } 下面是如何创建切片的:

/* Slice class*/
public class Slice
{
  private String color;
  private int prizeAmount;


  // Creates a slice with color c, and cash prize p
  public Slice(String c, int p) {
   color = c;
   prizeAmount = p;
  }


  // Returns the cash prize in dollars for this slice
  public int getPrizeAmount() {
    return prizeAmount;
  }


  // Returns the color of this slice as a string
  public String getColor() {
    return color;
  }


  /* Returns a string representation of the slice in the following format: 
   * Color: red, prize amount: $50.
   */
  public String toString() {
    return "Color: " + color + ", Prize Amount: $" + prizeAmount;      
  }
}

非常感谢您的帮助

我认为您可以创建3个不同的列表并分别对它们进行洗牌。之后,使用无序列表重新创建原始列表:

public static List<Slice> shuffle(List<Slice> slices) {
    final int total = slices.size();
    List<Slice> red = new ArrayList<>();
    List<Slice> blue = new ArrayList<>();
    List<Slice> black = new ArrayList<>();

    int i = 0;

    for (Slice slice : slices) {
        if (i % 2 == 1)
            red.add(slice);
        else if (i % 10 == 0)
            black.add(slice);
        else
            blue.add(slice);
        i++;
    }

    Collections.shuffle(red);
    Collections.shuffle(blue);
    Collections.shuffle(black);

    Iterator<Slice> itRed = red.iterator();
    Iterator<Slice> itBlue = blue.iterator();
    Iterator<Slice> itBlack = black.iterator();
    slices.clear();

    for (int j = 0; j < total; j++) {
        if (j % 2 == 1)
            slices.add(itRed.next());
        else if (j % 10 == 0)
            slices.add(itBlack.next());
        else
            slices.add(itBlue.next());
    }

    return slices;
}

没有像中那样的“简单”,通过现有的方法,如Collections.shuffle way;你必须自己编写这个功能,但是你当然可以使用一些现有的东西来帮助你

一种有点迂回的方法是“解构和重构”:编写一种方法,将单个列表分解为3个单独的列表,每种颜色1个,然后洗牌,然后使用明显的算法将三个单独的列表“重构”回单个大列表,如果索引可被10整除,则从黑名单中获取下一个,否则,如果可被2整除,则从蓝色列表中抓取,否则从红色列表中抓取

另一种方法是自己实现洗牌算法。对于上下文,您需要查找Collections.shuffle的实现也使用的。需要了解的关键事项:

要获得介于0和N之间的随机数,请在random的实例上调用.nextIntn,生成一个实例,一次,并继续重用它。不要使用普通的int Math.random*n,这是一个非常错误的鸽子洞原理,也不要使用非惯用java

fisher yates主要涉及从开始索引0到倒数第二个元素的列表,即索引为list.size-2的元素。对于每个元素,使用一个统一的随机选择的元素(它本身或它上面的任何元素)交换它

换言之,要洗牌1,2,3,4,5,我们从第0个元素1开始,然后从它自身和向上选择任意元素进行交换。这是5个元素的选择,所以我们调用rnd.nextInt5来解决这个问题。这个随机数可以是0,在这种情况下“你用它自己交换1”,意思是,它保持在原来的位置嘿,shuffle意味着随机;有时,在洗牌一副牌后,一张牌会在牌堆中的同一个位置结束!。然后对于下一个元素,使用2;在索引1中,您可以从索引本身选取任何索引,因此从索引1一直到最后,我们称之为rnd.nextInt4,依此类推

在本练习中,棘手的一点是找出可以与exist交换的“在您上方”的有效位置(这将是您传递给rnd.nextinkx的参数),以及如何将nextInt调用提供给您的数字转换为您现在需要交换的索引

请注意,此算法完全在适当的位置工作;不需要任何额外的列表或数组。您只需要一个临时变量来启用交换

这听起来像是家庭作业,所以我不去了 为你预先考虑答案。希望这足以让你自己写。祝你好运

试试这个解决方案:

公共空洗牌列表切片{ Map slicesByColor=slices.stream .CollectionGroupingBySlice::getColor.entrySet.stream .peek->Collections.shufflee.getValue .CollectToMap.Entry::getKey,e->e.getValue.iterator; 对于int i=0;i
[Color: black, Prize Amount: $8000, Color: red, Prize Amount: $10, Color: blue, Prize Amount: $200, Color: red, Prize Amount: $30, Color: blue, Prize Amount: $400, Color: red, Prize Amount: $50, Color: blue, Prize Amount: $600, Color: red, Prize Amount: $70, Color: blue, Prize Amount: $800, Color: red, Prize Amount: $90, Color: black, Prize Amount: $2000]
输出后:

[Color: black, Prize Amount: $2000, Color: red, Prize Amount: $90, Color: blue, Prize Amount: $800, Color: red, Prize Amount: $70, Color: blue, Prize Amount: $200, Color: red, Prize Amount: $10, Color: blue, Prize Amount: $400, Color: red, Prize Amount: $50, Color: blue, Prize Amount: $600, Color: red, Prize Amount: $30, Color: black, Prize Amount: $8000]

遍历列表,并为每个索引确定是奇数、偶数还是10的倍数。然后生成一个随机数<列表大小,直到该随机数也是奇数、偶数或10的倍数,具体取决于当前索引。交换当前索引和随机索引的内容。