Skip to content

4. Lambda-Funktionen in Java 8

4.1. Beispiel-01 – Funktionale Schnittstellen und Lambdas

  

Betrachten wir den folgenden Code:


package dvp.java8.lambdas;

public class Exemple01 {
  public static void main(String[] args) {

    // Anonyme Klassen
    I1 ia1 = new I1() {
      @Override
      public void doSomething() {
        System.out.println("ia1.doSomething");
      }
    };

    I2 ia2 = new I2() {
      @Override
      public String getSomething(double value) {
        return String.format("ia2.getSomething(%s)", value);
      }
    };

    // Lambdas
    I1 ib1 = () -> System.out.println("ib1.lambda");
    I2 ib2 = (value) -> String.format("ib2.lambda(%s)", value);
    I1 ib3 = () -> {
      System.out.println("ib3.lambda");
    };
    I2 ib4 = (double value) -> {
      return String.format("ib4.lambda(%s)", value);
    };

    // App
    ia1.doSomething();
    System.out.println(ia2.getSomething(4.3));
    ib1.doSomething();
    System.out.println(ib2.getSomething(5.8));
    ib3.doSomething();
    System.out.println(ib4.getSomething(10.1));
  }
}

@FunctionalInterface
interface I1 {
  void doSomething();
}

@FunctionalInterface
interface I2 {
  String getSomething(double value);
}
  • Zeilen 41–44: Definieren eine funktionale Schnittstelle I1. Eine funktionale Schnittstelle ist eine Schnittstelle, die nur eine Methode enthält. Sie ist nicht an das Vorhandensein der Annotation [@FunctionalInterface] in Zeile 41 gebunden, die optional ist;
  • Zeilen 46–49: eine zweite funktionale Schnittstelle I2;
  • Zeilen 6–19: Die Schnittstellen I1 und I2 werden mit anonymen Klassen implementiert – die gängigste Lösung vor der Einführung von Lambda-Funktionen;
  • Zeilen 21–29: Die Schnittstellen I1 und I2 werden mit Lambda-Funktionen implementiert;
  • Zeilen 7–12: Implementierung der Schnittstelle I1 mit einer anonymen Klasse. Die Syntax zur Implementierung einer Schnittstelle I mit einer anonymen Klasse lautet wie folgt:
I i=new I(){
    @Override
    public T1 m1(...){
...
    }
    public T2 m2(...){
...
    }
}

wobei m1, m2, ... die durch die Schnittstelle I definierten Methoden sind.

  • Zeilen 14–19: Implementierung der Schnittstelle I2 mit einer anonymen Klasse;
  • Zeile 22: Implementierung der Schnittstelle I1 mit einer Lambda-Funktion. Hier wird die Tatsache genutzt, dass die funktionale Schnittstelle nur eine Methode hat. Die Lambda-Funktion implementiert dann diese einzige Methode M. Ihre Syntax lautet wie folgt:
(T1 param1, T2 param2, ...) -> {implémentation de la méthode M ;}

Die Typen T1, T2 und Tn können weggelassen werden, wenn der Compiler sie aus dem Kontext ableiten kann (Typinferenz).

  • Zeile 22: Implementierung der Methode [I1.doSomething] mit folgender Signatur:

void doSomething();

[doSomething] ist eine Methode ohne Parameter, die keinen Rückgabewert liefert. Ihre Lambda-Implementierung kann wie in Zeile 22 oder wie in den Zeilen 24–26 geschrieben werden, d. h., man kann den Code der Lambda-Funktion in geschweifte Klammern setzen. Wenn dieser Code wie hier nur eine Anweisung enthält, können diese geschweiften Klammern weggelassen werden;

  • Zeile 23: Implementierung der Methode [I1.getSomething] mit folgender Signatur:

String getSomething(double value);

[getSomething] akzeptiert einen Parameter vom Typ [double] und gibt ein Ergebnis vom Typ [String] zurück. Ihre Lambda-Implementierung kann die in Zeile 23 oder die in den Zeilen 27–29 sein. In der Implementierung in Zeile 23:

  • wird der Typ des Parameters [value] weggelassen. In diesem Fall wird der Typ [double] verwendet, der in der Signatur von [getSomething] zu finden ist;
  • Der Lambda-Code ist nicht in Klammern gesetzt. Das Ergebnis des Lambda-Ausdrucks ist dann der Wert des einzigen Ausdrucks in diesem Code, hier: String.format("ib2.lambda(%s)", value);

In der Implementierung in den Zeilen 27–29:

  • wird der Typ des Parameters [value] explizit deklariert;
  • Zur Ausgabe des Ergebnisses des Lambda-Ausdrucks wird ein [return] verwendet. In diesem Fall müssen geschweifte Klammern gesetzt werden;
  • Zeilen 32–37: Hier werden die verschiedenen anonymen Funktionen und Lambda-Ausdrücke aufgerufen;

Das Ergebnis sieht wie folgt aus:

1
2
3
4
5
6
ia1.doSomething
ia2.getSomething(4.3)
ib1.lambda
ib2.lambda(5.8)
ib3.lambda
ib4.lambda(10.1)

4.2. Beispiel-02 – Die funktionale Schnittstelle Predicate<T>

  

Meistens haben wir es mit funktionalen Schnittstellen aus Bibliotheken zu tun und nicht mit funktionalen Schnittstellen, die wir selbst definieren. Hier befassen wir uns mit der funktionalen Schnittstelle [Predicate], die im Paket [java.util.function] definiert ist, welches die meisten funktionalen Schnittstellen von Java 8 enthält. Diese ist wie folgt definiert:

Image

Wir haben gesagt, dass eine funktionale Schnittstelle nur eine Methode hat. Hier gibt es jedoch vier. Eine weitere Neuerung in Java 8 war die Einführung des Konzepts der Standardmethode einer Schnittstelle, gekennzeichnet durch das Schlüsselwort [default]. Wir haben hier drei solcher Methoden. Diese Methoden zeichnen sich dadurch aus, dass sie eine Standardimplementierung haben. Eine Klasse, die eine Schnittstelle mit Standardmethoden implementiert, ist daher nicht verpflichtet, diese Methoden zu implementieren. Somit muss eine Klasse, die die Schnittstelle [Predicate] implementieren möchte, nur eine Methode zwingend implementieren: die Methode [test]. Die Schnittstelle [Predicate] ist somit tatsächlich eine funktionale Schnittstelle. Man sagt daher, dass eine funktionale Schnittstelle eine Schnittstelle ist, deren Implementierung nur eine obligatorische Methode enthält. Wenn sie mehr als eine Methode hat, müssen die anderen das Schlüsselwort [default] tragen.

Die Methode [Predicate<T>.test] nimmt einen Parameter vom Typ T entgegen und gibt einen booleschen Wert zurück. Diese Schnittstelle wird im Allgemeinen zum Filtern von Sammlungen verwendet. Um ihre Verwendung zu veranschaulichen, verwenden wir die folgenden Daten:


package dvp.data;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class Personne {

  public enum Sexe {HOMME,FEMME};

  // Daten
  private String nom;
  private int age;
  private double poids;
  private Sexe sexe;

  // Konstruktoren
  public Personne() {

  }

  public Personne(String nom, Sexe sexe, int age, double poids) {
    this.nom = nom;
    this.sexe=sexe;
    this.age = age;
    this.poids = poids;
  }

  // Getter und Setter
...

  // toString
  @Override
  public String toString(){
    try {
      return new ObjectMapper().writeValueAsString(this);
    } catch (JsonProcessingException e) {
      return e.getMessage();
    }
  }
}
  • Zeilen 32–38: Die Methode [toString] gibt die Zeichenkette jSON der Person zurück;

Die Klasse [Personnes] definiert eine Liste mit 3 Personen:


package dvp.data;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.Arrays;
import java.util.List;

public class Personnes {
  private static List<Personne> personnes = Arrays.asList(new Personne("jean", Personne.Sexe.HOMME, 20, 70),
    new Personne("marie", Personne.Sexe.FEMME, 10, 30), new Personne("camille", Personne.Sexe.FEMME, 30, 55));

  public static List<Personne> get() {
    return personnes;
  }

  public static String toString(List<Personne> liste) {
    try {
      return new ObjectMapper().writeValueAsString(liste);
    } catch (JsonProcessingException e) {
      return e.getMessage();
    }
  }
}
  • Zeilen 10–11: Die Liste mit 3 Personen;
  • Zeilen 13–15: eine statische Methode, um diese Liste zu erhalten;
  • Zeilen 17–23: eine statische Methode, mit der die Zeichenfolge jSON aus einer als Parameter übergebenen Liste von Personen abgerufen werden kann;

Diese Daten werden vom folgenden Code verarbeitet:


package dvp.java8.lambdas;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

import dvp.data.Personne;
import dvp.data.Personnes;

public class Exemple02 {
  public static void main(String[] args) {
    // Prädikat, implementiert durch eine anonyme Klasse
    Predicate<Personne> filterPoids=new Predicate<Personne>() {
      @Override
      public boolean test(Personne personne) {
        return personne.getPoids()<50;
      }
    };
// Prädikat, implementiert durch ein Lambda
    Predicate<Personne> filterAge = p -> p.getAge() < 28;
    // Personenliste
    List<Personne> personnes = Personnes.get();
    // Anzeigen
    System.out.println(Personnes.toString(filterPersonnes(personnes, filterAge)));
    System.out.println(Personnes.toString(filterPersonnes(personnes, filterPoids)));
  }

  private static List<Personne> filterPersonnes(List<Personne> personnes, Predicate<Personne> filter) {
      // [filter] filtert die Liste [personnes]
    List<Personne> personnesFiltrées = new ArrayList<>();
    for (Personne p : personnes) {
      if (filter.test(p)) {
        personnesFiltrées.add(p);
      }
    }
    return personnesFiltrées;  }
}
  • Zeilen 13–18: Implementierung der Schnittstelle `Predicate<Person>` durch eine anonyme Klasse. Es handelt sich um einen Filter für das Gewicht der Person;
  • Zeile 20: Implementierung der Schnittstelle `Predicate<Personne>` durch eine Lambda-Funktion. Es handelt sich um einen Filter nach dem Alter der Person. Nach dem bisher Gesagten hätte sie auch wie folgt geschrieben werden können:

        Predicate<Personne> filterAge = (Personne p) -> {
            return (p.getAge() < 28);
        };

aber die Version in Zeile 20 ist prägnanter. Der Typ des Parameters *p wird aus dem Kontext abgeleitet. Hier wird ein Typ [Predicate<Personne>] gebildet. Die implementierte Methode hat dann die Signatur [boolean test(Personne param)]. Der implizite Typ von p* in Zeile 20 ist also der Typ [Personne];

  • Zeile 22: Es wird eine vordefinierte Liste von Personen abgerufen;
  • Zeile 24: Diese werden nach ihrem Alter gefiltert;
  • Zeile 25: Sie werden nach ihrem Gewicht gefiltert. In beiden Fällen wird die Zeichenfolge jSON aus der so gefilterten Liste angezeigt;
  • Zeilen 28–37: Eine statische Methode, die
    • als Parameter eine Liste der zu filternden Personen und den Filter akzeptiert. Dieser ist eine Instanz der Schnittstelle [Predicate<Personne>]. Im weiteren Sinne bezeichnen wir hier und an anderen Stellen im Dokument eine Instanz einer Schnittstelle I als eine Instanz einer Klasse C, die I implementiert;
    • gibt als Ergebnis die so gefilterte Liste zurück;
  • Zeile 32: Es wird die Methode [test] der Schnittstelle [Predicate] verwendet. Je nach dem an die Methode übergebenen Filter wird die Methode [test]:

return personne.getPoids()<50;

oder


return p.getAge() < 28

Die Ausführung der Klasse [Exemple02] liefert folgendes Ergebnis:

[{"nom":"jean","age":20,"poids":70.0,"sexe":"HOMME"},{"nom":"marie","age":10,"poids":30.0,"sexe":"FEMME"}]
[{"nom":"marie","age":10,"poids":30.0,"sexe":"FEMME"}]

4.3. Beispiel-03 – die funktionale Schnittstelle Function<T,R>

  

Die funktionale Schnittstelle Function<T,R> ist wie folgt definiert:

Image

Die einzige Methode der Schnittstelle hat die Signatur R apply(T t). Sie wird im Allgemeinen verwendet, um aus einem Typ Collection<T> einen neuen Typ Collection<R> zu erstellen. Zur Veranschaulichung dieser Schnittstelle verwenden wir den folgenden Code:


package dvp.java8.lambdas;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import dvp.data.Personne;
import dvp.data.Personnes;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

public class Exemple03 {
  public static void main(String[] args) throws JsonProcessingException {
    // Implementierung mit anonymer Klasse
    Function<Personne, String> mapToName = new Function<Personne, String>() {
      @Override
      public String apply(Personne personne) {
        return personne.getNom();
      }
    };
    // Implementierung mit Lambda
    Function<Personne, Integer> mapToAge = p -> p.getAge();
    // Personenliste
    List<Personne> personnes = Personnes.get();
    // jSON
    ObjectMapper jsonMapper = new ObjectMapper();
    // Anzeigen
    System.out.println(jsonMapper.writeValueAsString(mapPersonnes(personnes, mapToName)));
    System.out.println(jsonMapper.writeValueAsString(mapPersonnes(personnes, mapToAge)));
  }

  // Umwandlung von List<Person> in List<T>
  private static <T> List<T> mapPersonnes(List<Personne> personnes, Function<Personne, T> mapper) {
    List<T> maps = new ArrayList<>();
    for (Personne p : personnes) {
      maps.add(mapper.apply(p));
    }
    return maps;
  }
}
  • Zeilen 15–20: Die Schnittstelle [Function<Personne, String>] wird mit einer anonymen Klasse implementiert, die die Umwandlung von „Person“ in „String“ vornimmt;
  • Zeile 22: Wir implementieren die Schnittstelle [Function<Personne, Integer>] mit einem Lambda-Ausdruck, der die Umwandlung von „Person“ in „Integer“ vornimmt;
  • Zeilen 33–39: Eine statische Methode, die
    • zwei Parameter akzeptiert: Der erste vom Typ List<Personne> ist eine Liste von Personen, die transformiert werden sollen. Der zweite vom Typ Function<Person, T> ist eine Funktion, die aus jeder Person der Liste ein Objekt vom Typ T erstellt;
    • als Ergebnis einen Typ List<T> liefert, bei dem jedes Element aus der Umwandlung „Person“ -> „T“ stammt;
  • Zeilen 35–37: Die Transformation „Person“ → „T“ wird angewendet. Ist der zweite Parameter der Methode das Objekt „[mapToName]“, wird eine Transformation „Person“ → „String“ durchgeführt. Handelt es sich um das Objekt [mapToAge], wird eine Transformation von „Person“ nach „Integer“ durchgeführt;

Das Ergebnis lautet wie folgt:

["jean","marie","camille"]
[20,10,30]

4.4. Beispiel-04 – Die funktionale Schnittstelle Consumer<T>

  

Die funktionale Schnittstelle Consumer<T> ist wie folgt definiert:

Image

Die einzige Methode der Schnittstelle hat die Signatur: void accept(T t). Diese Methode verarbeitet (verbraucht) ihren Parameter und gibt kein Ergebnis zurück. Zur Veranschaulichung verwenden wir den folgenden Code:


package dvp.java8.lambdas;

import java.util.List;
import java.util.function.Consumer;

import dvp.data.Personne;
import dvp.data.Personnes;

public class Exemple04 {
    public static void main(String[] args) {
        // Liste der Personen
        List<Personne> personnes = Personnes.get();
        // anonyme Implementierung
        Consumer<Personne> consumerAge = new Consumer<Personne>() {
            @Override
            public void accept(Personne personne) {
                System.out.printf(" age de %s = %s%n", personne.getNom(), personne.getAge());
            }
        };
        // Lambda-Implementierung
        Consumer<Personne> consumerPoids = p -> System.out.printf(" poids de %s = %s%n", p.getNom(), p.getPoids());        
        // Anzeigen
        for (Personne p : personnes) {
            consumerAge.accept(p);
        }
        System.out.println("--------");
        for (Personne p : personnes) {
            consumerPoids.accept(p);
        }
    }
}
  • Zeilen 14–19: Die Schnittstelle [Consumer<Personne>] wird durch eine anonyme Klasse implementiert, deren Methode [accept] den Namen und das Alter der Person anzeigt;
  • Zeile 21: Die Schnittstelle [Consumer<Personne>] wird durch eine Lambda-Funktion implementiert, deren implizite Methode [accept] den Namen und das Gewicht der Person anzeigt;
  • Zeilen 23–25: Die Liste der Personen wird von der Implementierung [consumerAge] verwendet;
  • Zeilen 27–29: Die Liste der Personen wird von der Implementierung [consumerPoids] verarbeitet;

Die Ergebnisse lauten wie folgt:

1
2
3
4
5
6
7
 age de jean = 20
 age de marie = 10
 age de camille = 30
--------
 poids de jean = 70.0
 poids de marie = 30.0
poids de camille = 55.0

4.5. Beispiel-05 – die Funktionsschnittstelle BiConsumer<T,U>

  

Die Funktionsschnittstelle BiConsumer<T,U> ist wie folgt definiert:

Image

Die einzige Methode der Schnittstelle hat die Signatur: void accept(T t, U u). Sie nimmt den Typ T mit der Zusatzinformation U u entgegen. Wir veranschaulichen ihre Verwendung anhand des folgenden Codes:


package dvp.java8.lambdas;

import dvp.data.Personne;
import dvp.data.Personnes;

import java.util.List;
import java.util.function.BiConsumer;

public class Exemple05 {
  public static void main(String[] args) {
    // Personenliste
    List<Personne> personnes = Personnes.get();
    // anonyme Implementierung
    BiConsumer<Personne, Integer> biconsumerAge = new BiConsumer<Personne, Integer>() {
      @Override
      public void accept(Personne personne, Integer integer) {
        personne.setAge(personne.getAge() + integer);
        System.out.printf("age de %s = %s%n", personne.getNom(), personne.getAge());
      }
    };
    // Lambda-Implementierung
    BiConsumer<Personne, Integer> biconsumerPoids = (p, i) -> {
      p.setPoids(p.getPoids() + i);
      System.out.printf("poids de %s = %s%n", p.getNom(), p.getPoids());
    };
    // Anzeigen
    for (Personne p : personnes) {
      biconsumerAge.accept(p, 100);
    }
    System.out.println("--------");
    for (Personne p : personnes) {
      biconsumerPoids.accept(p, 200);
    }
  }
}
  • Zeilen 14–20: Implementierung der Schnittstelle BiConsumer<T,U> mit einer anonymen Klasse. Die Methode [apply] verwendet ihren zweiten Parameter, um das Alter der als ersten Parameter übergebenen Person zu aktualisieren. Anschließend gibt sie das Ergebnis aus;
  • Zeilen 22–25: Implementierung der Schnittstelle BiConsumer<T,U> mit einer Lambda-Funktion. Die implizite Methode [apply] verwendet ihren zweiten Parameter, um das Gewicht der als ersten Parameter übergebenen Person zu aktualisieren. Anschließend gibt sie das Ergebnis aus;
  • Zeilen 27–29: Die Liste der Personen wird mit der Implementierung [biconsumerAge] verarbeitet;
  • Zeilen 31–33: Die Liste der Personen wird mit der Implementierung [biconsumerPoids] verarbeitet;

Die folgenden Ergebnisse werden erzielt:

1
2
3
4
5
6
7
age de jean = 120
age de marie = 110
age de camille = 130
--------
poids de jean = 270.0
poids de marie = 230.0
poids de camille = 255.0

4.6. Beispiel-06 – die Funktionsschnittstelle BiFunction<T,U,R>

  

Die Funktionsschnittstelle BiFunction<T,U,R> ist wie folgt definiert:

Image

Die einzige Methode der Schnittstelle hat die Signatur: R apply(T t, U u). Diese Methode ähnelt der Methode [BiConsumer.apply], doch während letztere kein Ergebnis zurückgibt, liefert die Methode [BiFunction.apply] ein Ergebnis. Wir veranschaulichen ihre Verwendung mit dem folgenden Code:


package dvp.java8.lambdas;

import java.util.List;
import java.util.function.BiFunction;

import dvp.data.Personne;
import dvp.data.Personnes;

public class Exemple06 {
    public static void main(String[] args) {
        // Personenliste
        List<Personne> personnes = Personnes.get();
        // anonyme Implementierung
        BiFunction<Personne, Integer, Integer> biFunctionAge = new BiFunction<Personne, Integer, Integer>() {
            @Override
            public Integer apply(Personne personne, Integer integer) {
                return personne.getAge() + integer;
            }
        };
        // Lambda-Implementierung
        BiFunction<Personne, Integer, Double> biFunctionPoids = (p, i) -> {
            return p.getPoids() + i;
        };
        // Anzeigen
        for (Personne p : personnes) {
            System.out.printf("age de %s = %s%n", p.getNom(), biFunctionAge.apply(p, 100));
        }
        System.out.println("--------");
        for (Personne p : personnes) {
            System.out.printf("poids de %s = %s%n", p.getNom(), biFunctionPoids.apply(p, 200));
        }
    }
}
  • Zeilen 14–19: Die Schnittstelle BiFunction<Person, Integer, Integer> wird mit einer anonymen Klasse implementiert. Die Methode [apply] dieser Klasse gibt das Alter der als ersten Parameter übergebenen Person zurück, erhöht um den Wert des zweiten Parameters;
  • Zeilen 21–23: Die Schnittstelle BiFunction<Person, Integer, Double> wird mit einer Lambda-Funktion implementiert. Die Methode [apply] gibt das Gewicht der als ersten Parameter übergebenen Person zurück, erhöht um den Wert des zweiten Parameters;
  • Zeilen 25–27: Die Implementierung [biFunctionAge] wird auf die Personen angewendet;
  • Zeilen 29–31: Die Implementierung [biFunctionPoids] wird auf die Personen angewendet;

Die Ergebnisse lauten wie folgt:

age de jean = 120
age de marie = 110
age de camille = 130
--------
poids de jean = 270.0
poids de marie = 230.0
poids de camille = 255.0

Neben den Lambda-Funktionen wurde in Java 8 der Typ Stream&lt;T&gt; eingeführt, der einen Strom von Elementen des Typs T modelliert. Diese Elemente können aufeinanderfolgenden Transformationen unterzogen werden, die durch Lambda-Funktionen implementiert werden. Wenn dies möglich ist und mehrere Prozessoren zur Verfügung stehen, können diese Transformationen manchmal parallel ausgeführt werden.

4.7. Beispiel-07 – Die funktionale Schnittstelle Supplier&lt;T&gt;

  

Die funktionale Schnittstelle Supplier**&lt;T&gt;** ist wie folgt definiert:

Image

Die einzige Methode der Schnittstelle hat die Signatur: T get(), deren Aufgabe es ist, ein Objekt vom Typ T bereitzustellen.

Wir veranschaulichen diese funktionale Schnittstelle mit dem folgenden Code:


package dvp.java8.lambdas;

import java.util.List;
import java.util.Random;
import java.util.function.Supplier;

import dvp.data.Personne;
import dvp.data.Personnes;

public class Exemple07 {
    public static void main(String[] args) {
        // anonyme Implementierung
        Supplier<Personne> supplier = new Supplier<Personne>() {
            // Personenliste
            List<Personne> personnes = Personnes.get();

            // Schnittstellenimplementierung
            @Override
            public Personne get() {
                int i = new Random().nextInt(personnes.size());
                return personnes.get(i);
            }
        };
        // Auswertung
        for (int i = 0; i < 5; i++) {
            affiche(supplier);
        }
    }

    // Personenanzeige
    public static void affiche(Supplier<Personne> supplier) {
        System.out.println(supplier.get());
    }
}
  • Zeilen 13–28: Implementierung eines Typs Supplier<Personne>;
  • Zeilen 31–33: Die statische Methode [affiche] erwartet einen Parameter vom Typ Supplier<Personne>;
  • Zeilen 25–27: Ausführung der Instanz Supplier<Personne>;

Es werden folgende Ergebnisse erhalten:

1
2
3
4
5
{"nom":"camille","age":30,"poids":55.0,"sexe":"FEMME"}
{"nom":"marie","age":10,"poids":30.0,"sexe":"FEMME"}
{"nom":"jean","age":20,"poids":70.0,"sexe":"HOMME"}
{"nom":"jean","age":20,"poids":70.0,"sexe":"HOMME"}
{"nom":"camille","age":30,"poids":55.0,"sexe":"FEMME"}