Java 8 Streams: How to call once the Collection.stream() method and retrieve an array of several aggregate values with different fields -


i'm starting stream api in java 8.

here person object use:

public class person {      private string firstname;     private string lastname;     private int age;     private double height;     private double weight;      public person(string firstname, string lastname, int age, double height, double weight) {       this.firstname = firstname;       this.lastname = lastname;       this.age = age;       this.height = height;       this.weight = weight;     }      public string getfirstname() {       return firstname;     }     public string getlastname() {       return lastname;     }     public int getage() {       return age;     }     public double getheight() {       return height;     }     public double getweight() {       return weight;     }    } 

here code initializes list of objects person , gets number of objects filtered specific firstname, maximum age , minimum height, weight average, , create array of objects containing these values:

list<person> personslist = new arraylist<person>();  personslist.add(new person("john", "doe", 25, 1.80, 80)); personslist.add(new person("jane", "doe", 30, 1.69, 60)); personslist.add(new person("john", "smith", 35, 174, 70));  long count = personslist.stream().filter(p -> p.getfirstname().equals("john")).count(); int maxage = personslist.stream().maptoint(person::getage).max().getasint(); double minheight = personslist.stream().maptodouble(person::getheight).min().getasdouble(); double avgweight = personslist.stream().maptodouble(person::getweight).average().getasdouble();  object[] result = new object[] { count, maxage, minheight, avgweight }; system.out.println(arrays.tostring(result)); 

is possible single call stream() method , return array of objects directly ?

object[] result = personslist.stream()...count()...max()...min()...average() 

i asked similar question previously: java 8 streams: how call once collection.stream() method , retrieve array of several aggregate values time cannot use summarystatistics() method because use different fields (age, height, weight) retrieve aggregate values.


edit 2016-01-07

i tested solutions of tricore , tagir valeev, , computed running time each solution.

it seems tricore solution more efficient tagir valeev.

tagir valeev's solution seems not save time compared solution (using multiple streams).

here test class:

public class streamtest {    public static class person {      private string firstname;     private string lastname;     private int age;     private double height;     private double weight;      public person(string firstname, string lastname, int age, double height, double weight) {       this.firstname = firstname;       this.lastname = lastname;       this.age = age;       this.height = height;       this.weight = weight;     }      public string getfirstname() {       return firstname;     }      public string getlastname() {       return lastname;     }      public int getage() {       return age;     }      public double getheight() {       return height;     }      public double getweight() {       return weight;     }    }    public static abstract class process {      public void run() {       stopwatch timer = new stopwatch();       timer.start();       dorun();       timer.stop();       system.out.println(timer.gettime());     }      protected abstract void dorun();    }    public static void main(string[] args) {     list<person> personslist = new arraylist<person>();      (int = 0; < 1000000; i++) {       int age = random(15, 60);       double height = random(1.50, 2.00);       double weight = random(50.0, 100.0);       personslist.add(new person(randomstring(10, mode.alpha), randomstring(10, mode.alpha), age, height, weight));     }      personslist.add(new person("john", "doe", 25, 1.80, 80));     personslist.add(new person("jane", "doe", 30, 1.69, 60));     personslist.add(new person("john", "smith", 35, 174, 70));     personslist.add(new person("john", "t", 45, 179, 99));      // query mutiple streams     new process() {       protected void dorun() {         queryjava8(personslist);       }     }.run();      // query 'tricore' method     new process() {       protected void dorun() {         queryjava8_1(personslist);       }     }.run();      // query 'tagir valeev' method     new process() {       protected void dorun() {         queryjava8_2(personslist);       }     }.run();   }    // --------------------   // java 8   // --------------------    private static void queryjava8(list<person> personslist) {     long count = personslist.stream().filter(p -> p.getfirstname().equals("john")).count();     int maxage = personslist.stream().maptoint(person::getage).max().getasint();     double minheight = personslist.stream().maptodouble(person::getheight).min().getasdouble();     double avgweight = personslist.stream().maptodouble(person::getweight).average().getasdouble();      object[] result = new object[] { count, maxage, minheight, avgweight };     system.out.println("java8: " + arrays.tostring(result));    }    // --------------------   // java 8_1 - tricore   // --------------------    private static void queryjava8_1(list<person> personslist) {     object[] objects = personslist.stream().collect(collector.of(() -> new personstatistics(p -> p.getfirstname().equals("john")),         personstatistics::accept, personstatistics::combine, personstatistics::tostatarray));     system.out.println("java8_1: " + arrays.tostring(objects));   }    public static class personstatistics {     private long firstnamecounter;     private int maxage = integer.min_value;     private double minheight = double.max_value;     private double totalweight;     private long total;     private final predicate<person> firstnamefilter;      public personstatistics(predicate<person> firstnamefilter) {       objects.requirenonnull(firstnamefilter);       this.firstnamefilter = firstnamefilter;     }      public void accept(person p) {       if (this.firstnamefilter.test(p)) {         firstnamecounter++;       }        this.maxage = math.max(p.getage(), maxage);       this.minheight = math.min(p.getheight(), minheight);       this.totalweight += p.getweight();       this.total++;     }      public personstatistics combine(personstatistics personstatistics) {       this.firstnamecounter += personstatistics.firstnamecounter;       this.maxage = math.max(personstatistics.maxage, maxage);       this.minheight = math.min(personstatistics.minheight, minheight);       this.totalweight += personstatistics.totalweight;       this.total += personstatistics.total;        return this;     }      public object[] tostatarray() {       return new object[] { firstnamecounter, maxage, minheight, total == 0 ? 0 : totalweight / total };     }   }    // --------------------   // java 8_2 - tagir valeev   // --------------------    private static void queryjava8_2(list<person> personslist) {     // @formatter:off     collector<person, ?, object[]> collector = multicollector(             filtering(p -> p.getfirstname().equals("john"), collectors.counting()),             collectors.collectingandthen(collectors.mapping(person::getage, collectors.maxby(comparator.naturalorder())), optional::get),             collectors.collectingandthen(collectors.mapping(person::getheight, collectors.minby(comparator.naturalorder())), optional::get),             collectors.averagingdouble(person::getweight)     );     // @formatter:on      object[] result = personslist.stream().collect(collector);     system.out.println("java8_2: " + arrays.tostring(result));   }    /**    * returns collector combines results of supplied collectors    * object[] array.    */   @safevarargs   public static <t> collector<t, ?, object[]> multicollector(collector<t, ?, ?>... collectors) {     @suppresswarnings("unchecked")     collector<t, object, object>[] cs = (collector<t, object, object>[]) collectors;     // @formatter:off       return collector.<t, object[], object[]> of(           () -> stream.of(cs).map(c -> c.supplier().get()).toarray(),           (acc, t) -> intstream.range(0, acc.length).foreach(               idx -> cs[idx].accumulator().accept(acc[idx], t)),           (acc1, acc2) -> intstream.range(0, acc1.length)               .maptoobj(idx -> cs[idx].combiner().apply(acc1[idx], acc2[idx])).toarray(),           acc -> intstream.range(0, acc.length)               .maptoobj(idx -> cs[idx].finisher().apply(acc[idx])).toarray());      // @formatter:on   }    /**    * filtering() collector (which added in jdk-9, see jdk-8144675)    */   public static <t, a, r> collector<t, a, r> filtering(predicate<? super t> filter, collector<t, a, r> downstream) {     biconsumer<a, t> accumulator = downstream.accumulator();     set<characteristics> characteristics = downstream.characteristics();     return collector.of(downstream.supplier(), (acc, t) -> {       if (filter.test(t))         accumulator.accept(acc, t);     } , downstream.combiner(), downstream.finisher(), characteristics.toarray(new collector.characteristics[characteristics.size()]));   }    // --------------------   // helper methods   // --------------------    public static enum mode {     alpha,     alphanumeric,     numeric   }    private static string randomstring(int length, mode mode) {     stringbuffer buffer = new stringbuffer();     string characters = "";      switch (mode) {       case alpha:         characters = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";         break;        case alphanumeric:         characters = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz1234567890";         break;        case numeric:         characters = "1234567890";         break;     }      int characterslength = characters.length();      (int = 0; < length; i++) {       double index = math.random() * characterslength;       buffer.append(characters.charat((int) index));     }     return buffer.tostring();   }    private static int random(int min, int max) {     random rand = new random();     return rand.nextint((max - min) + 1) + min;   }    private static double random(double min, double max) {     return min + math.random() * (max - min);   }  } 

here collector

public class personstatistics {     private long firstnamecounter;     private int maxage = integer.min_value;     private double minheight = double.max_value;     private double totalweight;     private long total;     private final predicate<person> firstnamefilter;      public personstatistics(predicate<person> firstnamefilter) {         objects.requirenonnull(firstnamefilter);         this.firstnamefilter = firstnamefilter;     }      public void accept(person p) {         if (this.firstnamefilter.test(p)) {             firstnamecounter++;         }          this.maxage = math.max(p.getage(), maxage);         this.minheight = math.min(p.getheight(), minheight);         this.totalweight += p.getweight();         this.total++;     }      public personstatistics combine(personstatistics personstatistics) {         this.firstnamecounter += personstatistics.firstnamecounter;         this.maxage = math.max(personstatistics.maxage, maxage);         this.minheight = math.min(personstatistics.minheight, minheight);         this.totalweight += personstatistics.totalweight;         this.total += personstatistics.total;          return this;     }      public object[] tostatarray() {         return new object[]{firstnamecounter, maxage, minheight, total == 0 ? 0 : totalweight / total};     } } 

you can use collector follows

public class personmain {     public static void main(string[] args) {         list<person> personslist = new arraylist<>();          personslist.add(new person("john", "doe", 25, 180, 80));         personslist.add(new person("jane", "doe", 30, 169, 60));         personslist.add(new person("john", "smith", 35, 174, 70));         personslist.add(new person("john", "t", 45, 179, 99));          object[] objects = personslist.stream().collect(collector.of(                 () -> new personstatistics(p -> p.getfirstname().equals("john")),                 personstatistics::accept,                 personstatistics::combine,                 personstatistics::tostatarray));         system.out.println(arrays.tostring(objects));     } } 

Comments

Popular posts from this blog

how to insert data php javascript mysql with multiple array session 2 -

multithreading - Exception in Application constructor -

windows - CertCreateCertificateContext returns CRYPT_E_ASN1_BADTAG / 8009310b -