如何用枚举聚合事件

How to aggregate the occurrence with enum

我有一个 ScenarioGenerator class 来生成 Scenario。在 Audit class 中,我设置了函数来决定要生成多少个场景,并希望打印出每个枚举类型的出现(在本例中为 Gender)。

我提到了 Counting an Occurrence in an Array (Java)

我用频率的方法统计了发生的次数,但是当生成的场景很多的时候,不知道如何聚合数据。我试过的是:

  1. 生成场景并将每个场景添加到 ArrayList
  2. 对于每个场景,我获取乘客ArrayList,并将它们的属性保存在不同的集合中。
  3. 对于每个集合,打印出它的值和计数。

我可以简单地这样做:

int maleCount = Collections.frequency(genderCollection, Gender.MALE);
System.out.println(Gender.MALE.toString().toLowerCase() + ":" +maleCount);

但是,如果我有更多的枚举和属性,这种方法就会变得冗长且效率低下。有什么办法可以解决这个问题吗?

这是我的一部分 Audit class:

public class Audit {

private Scenario scenario = new Scenario();
private ScenarioGenerator scenarioGenerator = new ScenarioGenerator();
private Person person = new Person();

private String auditType;
private int nubmerOfSimulation;

public enum Gender {
    MALE, FEMALE, UNKNOWN;
}

public Audit() {

}

// create a specific number of random scenarios
// the concept similar to gamePlayed and gameWon in the last project
public void run(int runs) {
    this.nubmerOfSimulation = runs;
    ArrayList<Scenario> scenarios = new ArrayList<Scenario>();//create a arrayList to store each scenario

    for (int i = 0; i < runs; i++) {
        Scenario singleScenario = scenarioGenerator.generate();
        scenarios.add(singleScenario); // save each scenario into a scenario arrayList
    }
    survialCalculator(scenarios);        
}

public int survialCalculator(ArrayList<Scenario> scenarios) {
    //person attribute arrayList
    ArrayList<Gender> genderCollection = new ArrayList<Gender>();

    for (Scenario scenario : scenarios) { // for each scenario, getting its passengers and pedestrians
        ArrayList<Character> passengers =  scenario.getPassengers();
        for (Character passenger : passengers) {
            if (passenger instanceof Person) {
                Gender gender = ((Person) passenger).getGender();
                //System.out.println(gender);
                genderCollection.add(gender);    
        }
    }

    //try to print out the elements in the collection and its frequency, but failed
    for(Gender genderElement : genderCollection) {
        int genderCount = Collections.frequency(genderCollection, genderElement);
        System.out.println(genderElement.toString().toLowerCase()+ ":" + genderCount);
    }

    return 1;

}

这是我的一部分 ScenarioGenerator:

public class ScenarioGenerator {


private Person person = new Person();
private Random random = new Random();   

private int passengerCountMinimum;
private int passengerCountMaximum;

private int pedestrianCountMininum;
private int pedestrianCountMaximum;

private ArrayList<Character> passengers = new ArrayList<Character>();
private ArrayList<Character> pedestrians = new ArrayList<Character>();

public Person getRandomPerson() {
    //need age, gender, bodyType, profession, pregnancy
    int age = random.nextInt(100);
    int profession = random.nextInt(person.getProfessionEnumLength());
    int gender = random.nextInt(person.getGenderEnumLength());
    int bodyType = random.nextInt(person.getBodyTypeEnumLength());
    int pregnancy = random.nextInt(2);

    Person people = new Person(age, 
                               Profession.values()[profession], 
                               Gender.values()[gender],
                               BodyType.values()[bodyType], 
                               pregnancy == 1 ? true : false);
    return people;
}

public Animal getRandomAnimal() {
    //species, isPet
    int age = random.nextInt(100);
    int gender = random.nextInt(person.getGenderEnumLength());
    int bodyType = random.nextInt(person.getBodyTypeEnumLength());
    boolean isPet = random.nextBoolean();


    String [] species = {"cat", "dog"};
    int idx = random.nextInt(species.length);
    String pickSpecies = species[idx];


    Animal creature = new Animal(age, Gender.values()[gender], BodyType.values()[bodyType] , pickSpecies); 
    creature.setIsPet(isPet);

    return creature;       
}
//getters and setter of min and max numbers of passengers and pedestrians
public Scenario generate() {

    //random number of passengers and pedestrians with random characteristics
    //randomly red light or green light
    //random condition "You" in the car
    //abide by the minimum and maximum counts from above setters

    //get random numbers abide by the setters
    int numberOfPassengers = ThreadLocalRandom.current().nextInt(getPassengerCountMin(), getPassengerCountMax()+1);
    int numberOfPedestrains =ThreadLocalRandom.current().nextInt(getPedestrianCountMin(), getPedestrianCountMax()+1);

    boolean legalCrossing = random.nextBoolean();

    //generate the number from the total numbers of passenger and pedestrians
    int numberOfPersonPassenger = ThreadLocalRandom.current().nextInt(0, numberOfPassengers+1);
    int numberOfAnimalPassenger = numberOfPassengers - numberOfPersonPassenger;

    int numberOfPersonPedestrian = ThreadLocalRandom.current().nextInt(0, numberOfPedestrains+1);
    int numberOfAnimalPedestrian = numberOfPedestrains - numberOfPersonPedestrian;

    //generate the number of person passengers
    for (int i = numberOfPersonPassenger; i > 0; i--) {
        Person person = getRandomPerson();
        passengers.add(person);
    }

    //remaining of the number of passengers should be animals
    //no matter it is pet of not
    for (int i = numberOfAnimalPassenger; i > 0; i--) {
        Animal animal = getRandomAnimal();
        passengers.add(animal);
    }

    for (int i = numberOfPersonPedestrian; i > 0; i--) {
        Person person = getRandomPerson();
        pedestrians.add(person);
    }

    for (int i =numberOfAnimalPedestrian; i > 0; i--) {
        Animal animal = getRandomAnimal();
        pedestrians.add(animal);
    }
    Scenario scenario = new Scenario(passengers, pedestrians, legalCrossing);

 return scenario;

}

这是我的一部分 Scenario class:

public class Scenario {
private Random random;

private ArrayList<Character> passenagers = new ArrayList<Character>();
private ArrayList<Character> pedestrians = new ArrayList<Character>();

private boolean legalCrossing;


public Scenario() {

}

public Scenario(ArrayList<Character> passengers, ArrayList<Character> pedestrians, boolean isLegalCrossing) {
    this.passenagers = passengers;
    this.pedestrians = pedestrians;
    this.legalCrossing = isLegalCrossing;
}
//getters and setters

主要class是调用方法:

public static void main(String[] args) throws Exception {

    ethicalEngine.generate();

}
public void generate() { 
    Audit audit = new Audit();
    audit.run(5); 
}

您可以考虑使用 Guava Multiset. As Stated here this data structure is more efficent when you have more attributes to count as the access to the number lies most of the time in O(1)

您可以在 List<Gender> 上使用 groupingBy 流操作来获取包含计数的所有性别类型的地图。

Map<Gender, Long> counted = genderCollection.stream()
            .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

然后这样打印

for (Map.Entry<Gender, Long> item : counted.entrySet()) {
    System.out.println(item.getKey().toString()+ ":" + item.getValue());
}