class NonDominatedFronts {

	protected List<Collection<Individual>> generateFronts(Collection<Individual> individuals) {
		List<Collection<Individual>> fronts = new ArrayList<>();
		// Assigns an id to each individual that corresponds to its index in an
		// array.
		Map<Individual, Integer> indexMap = new HashMap<>();
		int index = 0;
		for (Individual individual : individuals) {
			indexMap.put(individual, index++);
		}
		// Initializes a map where an individual is assigned to the individuals
		// that it dominates.
		Map<Individual, List<Individual>> dominatedIndividualsMap = new HashMap<>();
		// Creates an array where for each individual, the number of individuals
		// that dominate it is stored.
		int[] dominatingIndividualNumber = new int[individuals.size()];
		for (Individual e : individuals) {
			dominatedIndividualsMap.put(e, new ArrayList<>());
			dominatingIndividualNumber[indexMap.get(e)] = 0;
		}
		determineDomination(individuals, dominatedIndividualsMap, dominatingIndividualNumber, indexMap);
		// The first front consists of individuals that are dominated by zero
		// other individuals.
		List<Individual> f1 = new ArrayList<>();
		for (Individual i : individuals) {
			if (dominatingIndividualNumber[indexMap.get(i)] == 0) {
				f1.add(i);
			}
		}
		fronts.add(f1);
		List<Individual> currentFront = f1;
		// Creates the subsequent fronts. Front f_i is made up by individuals
		// that
		// are not dominated if all individuals from fronts f_j with j < i are
		// removed.
		while (!currentFront.isEmpty()) {
			List<Individual> nextFront = getNextFront(currentFront, dominatedIndividualsMap, dominatingIndividualNumber,
					indexMap);
			if (!nextFront.isEmpty()) {
				fronts.add(nextFront);
			}
			currentFront = nextFront;
		}
		return fronts;
	}

	public  NonDominatedFronts(Collection<Individual> individuals);

}