diff --git a/src/main/java/fr/univamu/progav/td8/ExercicesStream.java b/src/main/java/fr/univamu/progav/td8/ExercicesStream.java new file mode 100644 index 0000000000000000000000000000000000000000..e0c1c94f787bbf3798f2ba1824d1cee5dc34d12b --- /dev/null +++ b/src/main/java/fr/univamu/progav/td8/ExercicesStream.java @@ -0,0 +1,123 @@ +package fr.univamu.progav.td8; + +import fr.univamu.progav.td1.ExercicesBoucles; + +import java.util.*; +import java.util.function.BiConsumer; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class ExercicesStream { + + public interface Person { + int age(); + String name(); + boolean isFemale(); + Person mother(); + Person father(); + List<Person> children(); + } + + // Exercice : compléter toutes les méthodes suivantes + + + // retourne vrai si la stream contient une femme + public static boolean hasFemale(Stream<Person> persons) { + // TODO + return false; + } + + + // retourne vrai si la stream contient un individu homme et mineur (moins de 18 ans) + public static boolean containsMinorMale(Stream<Person> persons) { + // TODO + return false; + } + + + // retourne un individu de la stream, femme et ayant au moins un enfant, + // null si aucun individu ne convient + public static Optional<Person> findMother(Stream<Person> persons) { + // TODO + return Optional.empty(); + } + + + // retourne vrai si tous les individus de la stream sont majeurs (âge >= 18) + public static boolean areAllMajor(Stream<Person> persons) { + // TODO + return false; + } + + + // retourne la liste de tous les hommes de la stream. + public static List<Person> males(Stream<Person> persons) { + // TODO + return List.of(); + } + + + // retourne le nombre de femmes de la stream + public static long nbFemales(Stream<Person> persons) { + // TODO + return 0L; + } + + // trouve un individu de la stream ayant un enfant, et retourne l'âge + // de cet enfant. + public static Optional<Integer> ageOfSomeChild(Stream<Person> persons) { + // TODO + return Optional.empty(); + } + + + // retourne la personne la plus agée de la stream, + public static Optional<Person> eldest(Stream<Person> persons) { + // TODO + return Optional.empty(); + } + + + // retourne une chaîne de caractères, comprenant les noms de toutes les + // personnes de la stream, dans l'ordre, séparés par une espace. + public static String names(Stream<Person> persons) { + // TODO + return ""; + } + + + // retourne l'âge moyen des individus de la stream + public static OptionalDouble averageAge(Stream<Person> persons) { + // TODO + return OptionalDouble.empty(); + } + + + private static class SexCount { + // TODO ajouter des propriétés pour compter le nombre d'hommes et de femmes + SexCount() {} + + void add(Person p) { + // TODO dénombrer p dans les statistiques + } + + void merge(SexCount count) { + // TODO fusionner les statistiques + } + + boolean areEquals() { + // TODO renvoyer vrai si les nombres de femmes et d'hommes sont égaux + return false; + } + } + // retourne vrai si les nombres d'hommes et de femmes sont égaux. + public static boolean hasAsManyMalesAsFemales(Stream<Person> persons) { + Supplier<SexCount> supplier = null; // TODO initialiser les 3 variables. + BiConsumer<SexCount, Person> accumulator = null; + BiConsumer<SexCount,SexCount> combiner = null; + return persons + .collect(supplier,accumulator,combiner) + .areEquals(); + } +} diff --git a/src/main/java/fr/univamu/progav/td8/TD8.md b/src/main/java/fr/univamu/progav/td8/TD8.md new file mode 100644 index 0000000000000000000000000000000000000000..fa5298272c4400ada22cf2cb23f027a96ee3decd --- /dev/null +++ b/src/main/java/fr/univamu/progav/td8/TD8.md @@ -0,0 +1,33 @@ +Exercice +======== + +Compléter les méthodes de la classe `ExercicesStream`. + +Vous devez utiliser des Stream. Il est interdit d'utiliser des boucles ou +des récursions. Il est interdit de convertir les streams en listes (sauf +pour calculer la liste à retourner dans la méthode ```males```). Toutes +les méthodes doivent avoir une seule instruction, l'instruction ```return```. + +La dernière méthode est la plus difficile, elle demande de construire un +collecteur à partir de trois éléments : +- un ```Supplier<R>```, ```R``` étant le type des objets effectuant la + collection, disons un collecteur. Ce ```Supplier``` permet de créer un + nouveau collecteur; +- un ```BiConsumer<R,People>```, qui est une fonction prenant un collecteur + et une personne collectée. C'est en général la méthode du collecteur + chargé d'accepter les personnes collectées l'une après l'autre. Le + collecteur met à jour son état interne pour tenir compte de la personne + collectée. +- un ```BiConsumer<R,R>```, qui est une fonction permettant de fusionner le + travail de deux collecteurs. Le premier collecteur agrège les données + récoltées par le deuxième collecteur dans son état interne. + +Pour nous, le collecteur est un objet calculant le nombre de personnes de +chaque sexe. Le premier argument sera donc son constructeur, le deuxième +sera sa méthode ```add```, et le troisième sa méthode ```merge```, chacun +pouvant être donné par une référence de méthode. Une fois le collecteur +effectué, il reste à utiliser la méthode ```areEquals()``` pour déterminer +si le nombre de femmes est égal au nombre d'hommes. + +Tous les tests de ```ExercicesStreamTest``` doivent passer à la fin de +l'exercice. \ No newline at end of file diff --git a/src/test/java/fr/univamu/progav/td8/ExercicesStreamTest.java b/src/test/java/fr/univamu/progav/td8/ExercicesStreamTest.java new file mode 100644 index 0000000000000000000000000000000000000000..3c3a1643c87cb50df8cb2e5e66e54b81ccd3cf35 --- /dev/null +++ b/src/test/java/fr/univamu/progav/td8/ExercicesStreamTest.java @@ -0,0 +1,169 @@ +package fr.univamu.progav.td8; + +import fr.univamu.progav.td8.ExercicesStream; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.OptionalDouble; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static fr.univamu.progav.td8.ExercicesStream.Person; +import static org.junit.jupiter.api.Assertions.*; + +class ExercicesStreamTest { + + private record MockPerson( + int age, + String name, + boolean isFemale, + Person mother, + Person father, + List<Person> children + ) implements Person { + @Override + public String toString() { + return this.name; + } + } + + private static final Person alfa = + new MockPerson(78,"Alfa",true,null,null, new ArrayList<>()); + private static final Person bravo = + new MockPerson(82,"Bravo",false,null,null, new ArrayList<>()); + private static final Person charlie = + new MockPerson(42,"Charlie",false, alfa,bravo,List.of()); + private static final Person delta = + new MockPerson(38,"Delta",false, alfa,bravo, new ArrayList<>()); + private static final Person echo = + new MockPerson(41,"Echo",true,null,null, new ArrayList<>()); + private static final Person foxtrot = + new MockPerson(7,"Foxtrot",true,echo,delta, List.of()); + private static final Person golf = + new MockPerson(25,"Golf",true,null,null, new ArrayList<>()); + private static final Person hotel = + new MockPerson(2,"Hotel",false,golf,null, List.of()); + private static final Person india = + new MockPerson(8,"India",true,null,null, List.of()); + private static final Person juliett = + new MockPerson(18,"Juliett",false,null,null,List.of()); + + static { + alfa.children().addAll(List.of(charlie, delta)); + bravo.children().addAll(List.of(charlie, delta)); + delta.children().add(foxtrot); + echo.children().add(foxtrot); + golf.children().add(hotel); + } + + private static final List<Person> ALL = + List.of(alfa,bravo,charlie,delta,echo,foxtrot,golf,hotel,india,juliett); + private static Stream<Person> femaleStream() { + return Stream.of(alfa, echo, foxtrot, golf, india); + } + private static Stream<Person> maleStream() { + return Stream.of(bravo,charlie,delta,hotel,juliett); + } + @Test + void hasFemale() { + assertTrue(ExercicesStream.hasFemale(ALL.stream())); + assertFalse(ExercicesStream.hasFemale(Stream.of(bravo,charlie,delta))); + assertTrue(ExercicesStream.hasFemale(Stream.of(alfa))); + assertFalse(ExercicesStream.hasFemale(Stream.of()), "Cas de la stream vide"); + } + + @Test + void containsMinorMale() { + assertTrue(ExercicesStream.containsMinorMale(ALL.stream())); + assertFalse(ExercicesStream.containsMinorMale(Stream.of(bravo,charlie,delta)), "Pas de mineurs"); + assertFalse(ExercicesStream.containsMinorMale(Stream.of(foxtrot,india)), "Pas d'hommes"); + assertFalse(ExercicesStream.containsMinorMale(Stream.of()), "Cas de la stream vide"); + } + + @Test + void findMother() { + Optional<Person> found = ExercicesStream.findMother(ALL.stream()); + assertTrue(found.isPresent()); + assertTrue(found.get().isFemale() && !found.get().children().isEmpty()); + assertEquals(Optional.of(golf),ExercicesStream.findMother(Stream.of(bravo,charlie,delta,golf,hotel,india))); + assertEquals(Optional.empty(), ExercicesStream.findMother(Stream.of(bravo,charlie,delta,foxtrot,hotel,india))); + assertEquals(Optional.empty(), ExercicesStream.findMother(Stream.of()), "Cas de la stream vide"); + } + + @Test + void areAllMajor() { + assertFalse(ExercicesStream.areAllMajor(ALL.stream())); + assertTrue(ExercicesStream.areAllMajor(Stream.of(alfa,bravo,charlie,delta,echo,golf))); + assertTrue(ExercicesStream.areAllMajor(Stream.of(alfa,bravo,charlie,delta,echo,golf,juliett)), "Cas d'un individu ayant 18 ans"); + assertFalse(ExercicesStream.areAllMajor(Stream.of(foxtrot,hotel,india))); + assertTrue(ExercicesStream.areAllMajor(Stream.of()), "Cas de la stream vide"); + } + + @Test + void ageOfSomeChild() { + Optional<Integer> maybeAge = + ExercicesStream.ageOfSomeChild(Stream.of(hotel, india, juliett, alfa, foxtrot, charlie)); + assertTrue(maybeAge.isPresent()); + assertTrue(List.of(charlie.age(),delta.age()).contains(maybeAge.get())); + assertTrue(ExercicesStream.ageOfSomeChild(Stream.of(charlie,foxtrot,hotel,india,juliett)).isEmpty()); + assertTrue(ExercicesStream.ageOfSomeChild(Stream.of()).isEmpty(),"Cas de la stream vide"); + } + + @Test + void males() { + List<Person> allMales = ExercicesStream.males(ALL.stream()); + List<Person> expected = ALL.stream().filter(p -> !p.isFemale()).toList(); + assertNotNull(allMales); + assertEquals(expected.size(), allMales.size(), "Nombre d'hommes incorrect"); + for (Person p : expected ) { + assertTrue(allMales.contains(p), p.name() + " est un homme qui n'est pas dans la stream"); + } + List<Person> neitherMaleNorFemale = ExercicesStream.males(femaleStream()); + assertNotNull(neitherMaleNorFemale); + assertTrue(neitherMaleNorFemale.isEmpty()); + List<Person> empty = ExercicesStream.males(Stream.of()); + assertNotNull(empty, "Cas de la stream vide"); + assertTrue(empty.isEmpty(), "Cas de la stream vide"); + } + + @Test + void nbFemales() { + assertEquals(0,ExercicesStream.nbFemales(Stream.of()), "Cas de la stream vide"); + assertEquals(5,ExercicesStream.nbFemales(ALL.stream())); + assertEquals(0,ExercicesStream.nbFemales(maleStream())); + } + + @Test + void eldest() { + assertTrue(ExercicesStream.eldest(Stream.of()).isEmpty(), "Cas de la stream vide"); + assertEquals(Optional.of(bravo),ExercicesStream.eldest(ALL.stream())); + } + + @Test + void names() { + String allNames = ExercicesStream.names(ALL.stream()).trim(); + assertEquals("Alfa Bravo Charlie Delta Echo Foxtrot Golf Hotel India Juliett",allNames); + assertEquals("",ExercicesStream.names(Stream.of()), "Cas de la liste vide"); + } + + @Test + void hasAsManyMalesAsFemales() { + assertTrue(ExercicesStream.hasAsManyMalesAsFemales(Stream.of()), "Cas de la liste vide"); + assertFalse(ExercicesStream.hasAsManyMalesAsFemales(Stream.of(alfa))); + assertFalse(ExercicesStream.hasAsManyMalesAsFemales(Stream.of(bravo))); + assertFalse(ExercicesStream.hasAsManyMalesAsFemales(femaleStream())); + assertFalse(ExercicesStream.hasAsManyMalesAsFemales(maleStream())); + assertTrue(ExercicesStream.hasAsManyMalesAsFemales(ALL.stream())); + } + + @Test + void averageAge() { + assertTrue(ExercicesStream.averageAge(Stream.of()).isEmpty(), "Cas de la liste vide"); + OptionalDouble average = ExercicesStream.averageAge(ALL.stream()); + assertTrue(average.isPresent()); + double expected = 34.1; + assertTrue(Math.abs(average.getAsDouble() - expected) < 0.1, "La moyenne correcte est " + expected); + } +} \ No newline at end of file