我有这样一种方法,它获取我的个人列表(类有公共字段fitnessValue
)。我把所有的fitnessValue
和起来,然后在fitnessValue
和0之间画一个随机值。最后,我检查fitnessValue
累积和超过我之前计算的点的每一个个体,并返回第一个通过的点。
public Individual pickRandomIndividual(List<Individual> pool) {
Double totalScore = 0d;
Double runningScore = 0d;
for (Individual ind : pool) {
totalScore += ind.fitnessValue;
}
Double rnd = Math.random() * totalScore;
for (Individual ind : pool) {
if (rnd >= runningScore &&
rnd <= runningScore + ind.fitnessValue) {
return ind;
}
runningScore += ind.fitnessValue;
}
return null;
}
我想用Java 8流重构这个函数。你知道我怎么能做到吗?
我把它改了一点,变成:
Double fitnessSum = genePool.stream()
.mapToDouble(individual -> individual.fitnessValue)
.sum();
Double runningScore = 0d;
Double rnd = random() * fitnessSum;
for (Individual g : genePool) {
if (rnd >= runningScore && rnd <= runningScore + g.fitnessValue) {
return g;
}
runningScore += g.fitnessValue;
}
return null;
不过,我不知道如何把累积和部分变成一条小溪。也许整个逻辑实现得不好?我只想从列表中画一个Individual
,这取决于个人的fitnessValue
有多大。
发布于 2018-05-26 10:52:19
你必须记住,流并不是解决一切问题的方法。例如,在这种情况下,您需要跟踪多个值,即当前个体,以及累积和(并且必须在满足某个条件后立即返回一个值)。是的,有一些方法可以用流来实现这一点,但是我认为在这种情况下最好用一个简单的循环来实现它,就像您已经拥有的那样。
几个边注:
double
而不是包装类。Random
实例。< 0
,例如: double fitnessSum = genePool.stream() .mapToDouble(个人-> individual.fitnessValue) .sum();double余数= Math.random() * fitnessSum;}返回genePool.get(genePool.size() - 1);发布于 2018-05-26 13:38:48
在只迭代一次的情况下,从Iterator中选择随机元素的经典解决方案也有这种变化:
Double fitnessSum = 0.0;
Individual chosen = null;
for (Individual g : genePool) {
fitnessSum += g.fitnessValue;
if (Math.random() * fitnessSum < g.fitnessValue) {
chosen = g;
}
}
return g;
https://codereview.stackexchange.com/questions/195191
复制相似问题