Lambda系列教材 (三)- java 集合的聚合操作

步骤1:传统方式与聚合操作方式遍历数据
步骤2:Stream和管道的概念
步骤3:管道源
步骤4:中间操作
步骤5:结束操作
步骤6:练习-聚合操作
步骤7:答案-聚合操作

步骤 1 : 传统方式与聚合操作方式遍历数据

遍历数据的传统方式就是使用for循环,然后条件判断,最后打印出满足条件的数据

for (Hero h : heros) {

   if (h.hp > 100 && h.damage < 50)

      System.out.println(h.name);

}


使用聚合操作方式,画风就发生了变化:

heros

    .stream()

    .filter(h -> h.hp > 100 && h.damage < 50)

    .forEach(h -> System.out.println(h.name));

传统方式与聚合操作方式遍历数据

package lambda;

import java.util.ArrayList;

import java.util.List;

import java.util.Random;

import charactor.Hero;

public class TestAggregate {

    public static void main(String[] args) {

        Random r = new Random();

        List<Hero> heros = new ArrayList<Hero>();

        for (int i = 0; i < 5; i++) {

            heros.add(new Hero("hero " + i, r.nextInt(1000), r.nextInt(100)));

        }

        System.out.println("初始化后的集合:");

        System.out.println(heros);

        System.out.println("查询条件:hp>100 && damage<50");

        System.out.println("通过传统操作方式找出满足条件的数据:");

        for (Hero h : heros) {

            if (h.hp > 100 && h.damage < 50)

                System.out.println(h.name);

        }

        System.out.println("通过聚合操作方式找出满足条件的数据:");

        heros

            .stream()

            .filter(h -> h.hp > 100 && h.damage < 50)

            .forEach(h -> System.out.println(h.name));

    }

}

步骤 2 : Stream和管道的概念

heros

    .stream()

    .filter(h -> h.hp > 100 && h.damage < 50)

    .forEach(h -> System.out.println(h.name));


要了解聚合操作,首先要建立Stream管道的概念
Stream 和Collection结构化的数据不一样,Stream是一系列的元素,就像是生产线上的罐头一样,一串串的出来。
管道指的是一系列的聚合操作。

管道又分3个部分
管道源:在这个例子里,源是一个List
中间操作: 每个中间操作,又会返回一个Stream,比如.filter()又返回一个Stream, 中间操作是“懒”操作,并不会真正进行遍历。
结束操作:当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作。 结束操作不会返回Stream,但是会返回int、float、String、 Collection或者像forEach,什么都不返回, 结束操作才进行真正的遍历行为,在遍历的时候,才会去进行中间操作的相关判断

注: 这个Stream和I/O章节的InputStream,OutputStream是不一样的概念。

步骤 3 : 管道源

把Collection切换成管道源很简单,调用stream()就行了。

heros.stream()


但是数组却没有stream()方法,需要使用

Arrays.stream(hs)


或者

Stream.of(hs)

package lambda;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.HashMap;

import java.util.List;

import java.util.Random;

import charactor.Hero;

public class TestAggregate {

    public static void main(String[] args) {

        Random r = new Random();

        List<Hero> heros = new ArrayList<Hero>();

        for (int i = 0; i < 5; i++) {

            heros.add(new Hero("hero " + i, r.nextInt(1000), r.nextInt(100)));

        }

        //管道源是集合

        heros

        .stream()

        .forEach(h->System.out.println(h.name));

         

        //管道源是数组

        Hero hs[] = heros.toArray(new Hero[heros.size()]);

        Arrays.stream(hs)

        .forEach(h->System.out.println(h.name));

         

    }

}

步骤 4 : 中间操作

每个中间操作,又会返回一个Stream,比如.filter()又返回一个Stream, 中间操作是“懒”操作,并不会真正进行遍历。
中间操作比较多,主要分两类
对元素进行筛选 和 转换为其他形式的流
对元素进行筛选:
filter 匹配
distinct 去除重复(根据equals判断)
sorted 自然排序
sorted(Comparator<T>) 指定排序
limit 保留
skip 忽略
转换为其他形式的流
mapToDouble 转换为double的流
map 转换为任意类型的流

中间操作

package charactor;

      

public class Hero implements Comparable<Hero>{

    public String name; 

    public float hp;

         

    public int damage;

         

    public Hero(){

            

    }

    public String getName() {

        return name;

    }

    public void setName(String name) {

        this.name = name;

    }

    public float getHp() {

        return hp;

    }

    public void setHp(float hp) {

        this.hp = hp;

    }

    public int getDamage() {

        return damage;

    }

    public void setDamage(int damage) {

        this.damage = damage;

    }

    public Hero(String name) {

        this.name =name;

    }

    //初始化name,hp,damage的构造方法

    public Hero(String name,float hp, int damage) {

        this.name =name;

        this.hp = hp;

        this.damage = damage;

    }

    

    @Override

    public int compareTo(Hero anotherHero) {

        if(damage<anotherHero.damage)

            return 1;  

        else

            return -1;

    }

    

    @Override

    public String toString() {

        return "Hero [name=" + name + ", hp=" + hp + ", damage=" + damage + "] ";

    }

        

}

package lambda;

  

import java.util.ArrayList;

import java.util.List;

import java.util.Random;

import charactor.Hero;

  

public class TestAggregate {

  

    public static void main(String[] args) {

        Random r = new Random();

        List<Hero> heros = new ArrayList<Hero>();

        for (int i = 0; i < 5; i++) {

            heros.add(new Hero("hero " + i, r.nextInt(1000), r.nextInt(100)));

        }

        //制造一个重复数据

        heros.add(heros.get(0));

        System.out.println("初始化集合后的数据 (最后一个数据重复):");

        System.out.println(heros);

        System.out.println("满足条件hp>100&&damage<50的数据");

          

        heros

            .stream()

            .filter(h->h.hp>100&&h.damage<50)

            .forEach(h->System.out.print(h));

          

        System.out.println("去除重复的数据,去除标准是看equals");

        heros

            .stream()

            .distinct()

            .forEach(h->System.out.print(h));

        System.out.println("按照血量排序");

        heros

            .stream()

            .sorted((h1,h2)->h1.hp>=h2.hp?1:-1)

            .forEach(h->System.out.print(h));

          

        System.out.println("保留3个");

        heros

            .stream()

            .limit(3)

            .forEach(h->System.out.print(h));

          

        System.out.println("忽略前3个");

        heros

            .stream()

            .skip(3)

            .forEach(h->System.out.print(h));

          

        System.out.println("转换为double的Stream");

        heros

            .stream()

            .mapToDouble(Hero::getHp)

            .forEach(h->System.out.println(h));

          

        System.out.println("转换任意类型的Stream");

        heros

            .stream()

            .map((h)-> h.name + " - " + h.hp + " - " + h.damage)

            .forEach(h->System.out.println(h));

          

    }

}

步骤 5 : 结束操作

当进行结束操作后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作。 结束操作不会返回Stream,但是会返回int、float、String、 Collection或者像forEach,什么都不返回,。
结束操作才真正进行遍历行为,前面的中间操作也在这个时候,才真正的执行。
常见结束操作如下:
forEach() 遍历每个元素
toArray() 转换为数组
min(Comparator<T>) 取最小的元素
max(Comparator<T>) 取最大的元素
count() 总数
findFirst() 第一个元素

结束操作

package lambda;

  

import java.util.ArrayList;

import java.util.Arrays;

import java.util.List;

import java.util.Random;

import org.omg.Messaging.SYNC_WITH_TRANSPORT;

import charactor.Hero;

  

public class TestAggregate {

  

    public static void main(String[] args) {

        Random r = new Random();

        List<Hero> heros = new ArrayList<Hero>();

        for (int i = 0; i < 5; i++) {

            heros.add(new Hero("hero " + i, r.nextInt(1000), r.nextInt(100)));

        }

        System.out.println("遍历集合中的每个数据");

        heros

            .stream()

            .forEach(h->System.out.print(h));

        System.out.println("返回一个数组");

        Object[] hs= heros

            .stream()

            .toArray();

        System.out.println(Arrays.toString(hs));

        System.out.println("返回伤害最低的那个英雄");

        Hero minDamageHero =

        heros

            .stream()

            .min((h1,h2)->h1.damage-h2.damage)

            .get();

        System.out.print(minDamageHero);

        System.out.println("返回伤害最高的那个英雄");

        Hero mxnDamageHero =

                heros

                .stream()

                .max((h1,h2)->h1.damage-h2.damage)

                .get();

        System.out.print(mxnDamageHero);      

         

        System.out.println("流中数据的总数");

        long count = heros

                .stream()

                .count();

        System.out.println(count);

        System.out.println("第一个英雄");

        Hero firstHero =

                heros

                .stream()

                .findFirst()

                .get();

         

        System.out.println(firstHero);

         

    }

}


更多内容,点击了解: https://how2j.cn/k/lambda/lambda-stream/700.html

原文地址:https://www.cnblogs.com/Lanht/p/12615479.html