可变基于状态和不可变事件的数据模型的计算成本

时间:2017-01-22 12:41:35

标签: java android performance list immutability

提前道歉,这是一个漫长的道歉。我目前正在为Snooker这项运动创建一个记分牌应用。基本规则是玩家必须以交替的方式将红球和彩球放在一起,直到没有红色为止。之后,剩余的彩球按价值顺序进行封装。起初我使用了传统的可变Java数据模型,如下所示:

public class Player {
    public enum PlayerPosition { PLAYER_ONE, PLAYER_TWO };

    String name;
    int score;
    int currentBreak;
}

public class Frame {
    Player playerOne, playerTwo;
    PlayerPosition breakingPlayer, playerAtTable;
    int redsOnTable;
    Ball[] remainingColours = new Ball[] { YELLOW, GREEN, BROWN, BLUE, PINK, BLACK };
}

因此,当球被盆栽时,该球的值将被添加到Player的{​​{1}}并且score减少。这个问题是在存储中断的总数时,封装的球的顺序不是。但是,通过添加盆球的顺序,我现在将冗余数据引入数据模型,因为redsOnTable现在可以通过查看盆球的顺序来计算。

所以我开始想知道redsOnTable是否可以被视为一系列事件,例如。

  • 红球盆栽
  • 黑球盆栽
  • 红球盆栽
  • 休息结束
  • 红球盆栽
  • ...

从中可以通过遍历此事件列表来计算所有其他信息(例如Frame,玩家的最高休息时间,表中剩余的总数),缺点是由于迭代而导致的计算成本要高得多每次需要检索统计信息时,此列表。我确实尝试了这样的事情,将每个玩家的突破分为redsOnTable

List<List<Ball>>

但这导致了一个错误,我无法确定游戏是否在最终颜色运行(黄色,绿色等),以及非常混乱的修复,所以我想转移到将所有事件存储在一个@AutoValue public abstract class Break implements Parcelable { public abstract List<Ball> getBallOrder(); public static Break create(List<Ball> balls) { return new AutoValue_Break(balls); } } @AutoValue public abstract class Frame implements Parcelable { public abstract int getStartingReds(); public abstract List<Break> getBreakHistory(); public abstract PlayerPosition getPlayerPositionAtTable(); public abstract PlayerPosition getBreakingPlayer(); public abstract Builder toBuilder(); } 。此列表目前每次刷新将被读取5次(确定桌面上的玩家,获得玩家得分(x2),获得桌面上剩余的总数,获得桌面上剩余的最低值球),但我可以重构它所以我可以在一次迭代中获取所有这些信息。

所以我的问题归结为:

  • 与传统的可变数据模型相比,基于事件的不可变数据模型所需的额外计算成本是否可能对最近的低端Android手机的性能产生重大影响?
  • 是否有比List<Event>更有效的类我可以用来存储和迭代这些事件(即跳到下一个ArrayList事件,获取列表中的红球事件数量)。假设这个列表可以在长时间的安全战中轻松地进行100多个事件。
  • 我需要记住经常迭代的长列表吗?

编辑:关于该Color Run错误。一旦所有的红色都被盆栽,其余的彩球必须按价值顺序进行盆栽,并且不会被更换回到桌子上。这里可以发生许多情况:

1:

  • 玩家最后一个红色
  • 玩家一壶颜色(不是黄色)
  • 玩家一不会黄色,休息结束
  • 玩家二现在必须击中黄色

2:

  • 玩家最后一个红色
  • 球员一次错过了他们的下一次投篮(或犯规),休息结束
  • 玩家二现在必须击中黄色

3:

  • 玩家最后一个红色
  • 播放器一盆黄色,黄色放回桌上
  • 玩家一不会把黄色,休息结束
  • 玩家二必须击中黄色

因此,如果我们纯粹是通过盆栽订单而不是使用EndOfBreak事件,那么这就会产生一个问题,因为接下来的球可能会或可能不会被放回到表。

  • 在情景1中我们知道黄色是接下来的球,因为在最终红色不是黄色之后球被盆栽。
  • 在情景2中,最后一个球是红色的,所以我们必须检查最后的红色是否作为当前休息的一部分进行封装,以确定我们是否处于颜色运行状态。如果我们只是在没有包含EndOfBreak事件的情况下进行球倒计时,那就不可能了。
  • 在情景3中,最后一个球盆是不明确的,因为它是黄色的。如果我们没有EndOfBreak信息,应用程序如何知道黄色是否还在桌面上?

正如我之前提到的,我确实想出了一个修复程序,但它非常繁琐,但仍然有一些不起作用的边缘情况,这就是为什么我要将EndOfBreak作为事件包含在内在此列表中。

0 个答案:

没有答案