在 ArrayList 中查找最常见的随机分配字符串
Find most common randomly assigned string in ArrayList
我正在开发一个模拟器,其中 Person 对象(存储在 ArrayList 中)"reproduce" 并制造婴儿,它们继承 "genes",表示为 4 个字母的字符串。在程序开始时,第一个人的基因库是随机生成的。
在计时器的每个滴答声中,我想计算所有 Person 对象中最常见的 "gene" 是什么。
这四个字母是:
1. G、Z、N、F
2. A、T、C、G
3. B、F、Q、N
4. A、C、T、E
在这种情况下有 256 种可能的组合,必须有比 256 种 if-else 语句更有效的检查。
人物 class(减去 get/set 方法)
public class Person {
static Random rand = new Random();
private Person mother;
private Person father;
private String genes;
private char sex;
private int age, numKids;
public Person() {
mother = null;
father = null;
genes = createGenes();
if (rand.nextDouble() <= 0.5)
sex = 'm';
else
sex = 'f';
age = 18;
numKids = 0;
}
public Person(Person m, Person f) {
mother = m;
father = f;
genes = inheritGenes(m, f);
if (rand.nextDouble() <= 0.5)
sex = 'm';
else
sex = 'f';
age = 0;
}
//create genes for original Persons
private String createGenes() {
String genetics = "";
double first = rand.nextDouble();
double second = rand.nextDouble();
double third = rand.nextDouble();
double fourth = rand.nextDouble();
if (first <= 0.25)
genetics += "G";
else if (first <= 0.68)
genetics += "Z";
else if (first <= 0.9)
genetics += "N";
else
genetics += "F";
if (second <= 0.65)
genetics += "A";
else if (second <= 0.79)
genetics += "T";
else if (second <= 0.85)
genetics += "C";
else
genetics += "G";
if (third <= 0.64)
genetics += "B";
else if (third <= 0.95)
genetics += "F";
else if (third <= 0.98)
genetics += "Q";
else
genetics += "N";
if (fourth <= 0.37)
genetics += "A";
else if (fourth <= 0.58)
genetics += "C";
else if (fourth <= 0.63)
genetics += "T";
else
genetics += "E";
return genetics;
}
//inherit genes from parents for new Persons
public String inheritGenes(Person m, Person f) {
String genetics = "";
double first = rand.nextDouble();
double second = rand.nextDouble();
double third = rand.nextDouble();
double fourth = rand.nextDouble();
if (first < 0.5) {
genetics += m.getGenes().charAt(0);
} else
genetics += f.getGenes().charAt(0);
if (second < 0.5) {
genetics += m.getGenes().charAt(1);
} else
genetics += f.getGenes().charAt(1);
if (third < 0.5) {
genetics += m.getGenes().charAt(2);
} else
genetics += f.getGenes().charAt(2);
if (fourth < 0.5) {
genetics += m.getGenes().charAt(3);
} else
genetics += f.getGenes().charAt(3);
return genetics;
}
}
从 List<Person>
中找到最常见基因的示例代码。我刚刚为 genes
添加了一个 getter String
:
String getGenes() {
return genes;
}
代码如下:
List<Person> people = new ArrayList<>();
for (int i = 0; i < 100; i++) {
people.add(new Person()); // 100 random genes
}
String mostCommonGene = people.stream()
.map(Person::getGenes)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.max(Comparator.comparingLong(Map.Entry::getValue))
.get()
.getKey();
System.out.println("Most common gene: " + mostCommonGene);
我们使用 Java 8 个流:
- 我们得到
people
列表的 stream()
。
- 我们
map()
(转换)每个 Person
到 String
- 他们的 genes
.
- 我们
collect()
基因流 和 groupingBy()
由 Function.identity()
和 Collectors.counting()
喂养。此步骤生成一个 Map<String, Long>
,它表示 map genes
及其频率。实际上,这计算了 people
列表中基因的出现次数。
- 然后我们在该地图上调用
entrySet()
,然后再次调用 stream()
- 现在我们有一个 流 地图条目(您可以将它们视为成对 - 一个对象内的基因及其频率。方便)。
- 我们调用
max()
来找到具有最高 value(解释为频率)的 entry。 Comparator.comparingLong()
告诉 max()
算法我们如何比较这些对,但是 对 不是 longs - 这就是为什么我们必须告诉它如何将 entry 转换为 long
- 我们得到 entry 的 entry.
- 然后我们调用
get()
,因为 max()
returns 和 Optional<T>
。我们只想要 T
(条目)。
- 最后,我们在 entry 上调用
getKey()
,表示一对最频繁的基因及其频率。如前所述,键是基因,值是它的频率。
如果您不熟悉此答案中描述的大多数概念,我强烈建议您了解 Java 8 Streams。习惯了就停不下来了
根据使用场景,使用额外的 Map<String,Long>
作为每个基因的计数器(为每个新的 Person 基因增加计数器)可能会更有效。
这种方法会使用更多的内存(Map<String,Long>
最多有 256 个元素)并且新的 Person 构造会有点慢(地图的更新),但是在每个 tick 上获取最常见的基因如果有许多 Person 对象处于活动状态,可能会快得多,因为这些对象已经在 Map 中进行了分组和计数,因此最多只应比较 256 个条目。
我正在开发一个模拟器,其中 Person 对象(存储在 ArrayList 中)"reproduce" 并制造婴儿,它们继承 "genes",表示为 4 个字母的字符串。在程序开始时,第一个人的基因库是随机生成的。
在计时器的每个滴答声中,我想计算所有 Person 对象中最常见的 "gene" 是什么。
这四个字母是:
1. G、Z、N、F
2. A、T、C、G
3. B、F、Q、N
4. A、C、T、E
在这种情况下有 256 种可能的组合,必须有比 256 种 if-else 语句更有效的检查。
人物 class(减去 get/set 方法)
public class Person {
static Random rand = new Random();
private Person mother;
private Person father;
private String genes;
private char sex;
private int age, numKids;
public Person() {
mother = null;
father = null;
genes = createGenes();
if (rand.nextDouble() <= 0.5)
sex = 'm';
else
sex = 'f';
age = 18;
numKids = 0;
}
public Person(Person m, Person f) {
mother = m;
father = f;
genes = inheritGenes(m, f);
if (rand.nextDouble() <= 0.5)
sex = 'm';
else
sex = 'f';
age = 0;
}
//create genes for original Persons
private String createGenes() {
String genetics = "";
double first = rand.nextDouble();
double second = rand.nextDouble();
double third = rand.nextDouble();
double fourth = rand.nextDouble();
if (first <= 0.25)
genetics += "G";
else if (first <= 0.68)
genetics += "Z";
else if (first <= 0.9)
genetics += "N";
else
genetics += "F";
if (second <= 0.65)
genetics += "A";
else if (second <= 0.79)
genetics += "T";
else if (second <= 0.85)
genetics += "C";
else
genetics += "G";
if (third <= 0.64)
genetics += "B";
else if (third <= 0.95)
genetics += "F";
else if (third <= 0.98)
genetics += "Q";
else
genetics += "N";
if (fourth <= 0.37)
genetics += "A";
else if (fourth <= 0.58)
genetics += "C";
else if (fourth <= 0.63)
genetics += "T";
else
genetics += "E";
return genetics;
}
//inherit genes from parents for new Persons
public String inheritGenes(Person m, Person f) {
String genetics = "";
double first = rand.nextDouble();
double second = rand.nextDouble();
double third = rand.nextDouble();
double fourth = rand.nextDouble();
if (first < 0.5) {
genetics += m.getGenes().charAt(0);
} else
genetics += f.getGenes().charAt(0);
if (second < 0.5) {
genetics += m.getGenes().charAt(1);
} else
genetics += f.getGenes().charAt(1);
if (third < 0.5) {
genetics += m.getGenes().charAt(2);
} else
genetics += f.getGenes().charAt(2);
if (fourth < 0.5) {
genetics += m.getGenes().charAt(3);
} else
genetics += f.getGenes().charAt(3);
return genetics;
}
}
从 List<Person>
中找到最常见基因的示例代码。我刚刚为 genes
添加了一个 getter String
:
String getGenes() {
return genes;
}
代码如下:
List<Person> people = new ArrayList<>();
for (int i = 0; i < 100; i++) {
people.add(new Person()); // 100 random genes
}
String mostCommonGene = people.stream()
.map(Person::getGenes)
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet()
.stream()
.max(Comparator.comparingLong(Map.Entry::getValue))
.get()
.getKey();
System.out.println("Most common gene: " + mostCommonGene);
我们使用 Java 8 个流:
- 我们得到
people
列表的stream()
。 - 我们
map()
(转换)每个Person
到String
- 他们的genes
. - 我们
collect()
基因流 和groupingBy()
由Function.identity()
和Collectors.counting()
喂养。此步骤生成一个Map<String, Long>
,它表示 mapgenes
及其频率。实际上,这计算了people
列表中基因的出现次数。 - 然后我们在该地图上调用
entrySet()
,然后再次调用stream()
- 现在我们有一个 流 地图条目(您可以将它们视为成对 - 一个对象内的基因及其频率。方便)。 - 我们调用
max()
来找到具有最高 value(解释为频率)的 entry。Comparator.comparingLong()
告诉max()
算法我们如何比较这些对,但是 对 不是 longs - 这就是为什么我们必须告诉它如何将 entry 转换为long
- 我们得到 entry 的 entry. - 然后我们调用
get()
,因为max()
returns 和Optional<T>
。我们只想要T
(条目)。 - 最后,我们在 entry 上调用
getKey()
,表示一对最频繁的基因及其频率。如前所述,键是基因,值是它的频率。
如果您不熟悉此答案中描述的大多数概念,我强烈建议您了解 Java 8 Streams。习惯了就停不下来了
根据使用场景,使用额外的 Map<String,Long>
作为每个基因的计数器(为每个新的 Person 基因增加计数器)可能会更有效。
这种方法会使用更多的内存(Map<String,Long>
最多有 256 个元素)并且新的 Person 构造会有点慢(地图的更新),但是在每个 tick 上获取最常见的基因如果有许多 Person 对象处于活动状态,可能会快得多,因为这些对象已经在 Map 中进行了分组和计数,因此最多只应比较 256 个条目。