Stream 与 map映射操作

一、Stream

1.1 简介

集合更多的是数据结构的封装,主要用来存储数据。如果需要对数据进行多次加工(比如:筛选、排序、 聚合等),可以使用Stream API。

Stream 将要处理的元素集合看作是一种流,在流的过程中,借助Stream API对流中的元素进行操作, 整个流操作就是一条流水线,将元素放在流水线上一个个地进行处理。

Stream实质上是对集合对象功能的增加,用来进行各种方便高效的操作。过程就像工人在流线上加工一 样。我们只需要告诉流你的要求,流便全在背后自行根据要求元素进行处理,而我们只需要得到最后的结果就可以了。

1.2 Stream创建

  • 通过Collection接口的stream()方法使用集合创建流

    List<String> list= Arrays.asList("AA","BB","CC");
    Stream<String> stream=list.stream();
    
  • 使用Arrays.stream(T[] array)方法使用数组创建流

    String[] strings={"AA","BB","CC"};
    Stream<String> stream= Arrays.stream(strings);
    
  • 使用StreamAPI中的静态方法来创建流

    Stream<String> stream=Stream.of("AA","BBB","CC");
    stream.filter(x->x.length()==3).forEach(System.out::println);
    Stream<Integer> stream1 = Stream.iterate(0, x -> x + 2);
    stream1.limit(10).forEach(System.out::println);
    Stream<Double> stream2=Stream.generate(Math::random);
    stream2.limit(3).forEach(System.out::println);
    
  • Files类的方法来创建流

    Files.lines();

    Files.list();

  • 合并流

    Stream<String> stream1 = Arrays.stream(new String[]{"AA", "BB", "CC"});
    Stream<String> stream2 = Arrays.stream(new String[]{"DD", "EE", "FF"});
    Stream<String> stream3 = Stream.concat(stream1, stream2);
    

1.3 Stream 分类

  1. 中间操作:每次操作返回一个新的流,可以有多个
  2. 中断操作:每个流只能进行一次终端操作,终端操作结束后,流无法再次使用,终端操作会产生一个新的值或集合

1.4 Stream特性

  1. 不存储数据,按照给定的规则,对数据进行加工计算,一般会输出结果或得到一个新的集合
  2. 不会改变数据源。通常情况下会产生一个新的集合或一个值
  3. 具有延迟执行特性。只有调用终端操作时,中间操作才会执行。

1.5 Stream和集合的差别

  1. 什么时候进行计算

    集合框架,里面包含当前数据结构中所有的值,我们可以对集合进行增加、删除、修改、检索数据的操作,集合中的元素都是已经计算好的。

    流是按需计算,是在用户要求的时候才会计算值

  2. 外部迭代和内部迭代

    集合使用外部迭代方式

    Stream使用内部迭代方式

1.6 Optional类

java8版本引入的一个新的容器类,可以代表一个值存在或不存在,不用返回容易出问题的 NullPointerException。Optional类可以仿有对象,也可以为空

常用方法 empty():创建一个空的Optional

of(T t):创建一个Optional,存储T对象,非空值,如果元素为空,报空指针异常,如果明确对象不为 null,使用of()方法

ofNullable(T t):创建一个Optional,存储T对象,可以有空值,如果元素为空,报 NoSuchElementException异常,对象可能是null,也可能非null,使用ofNullable()方法

get():获取Optional中的value值

isPresent():判断值是否存在,存在返回true,否则返回false

isEmpty():判断值是否存在,不存在返回true,否则返回false,在jdk11及以上版本使用

orElse(T t): 如果值不为空,则返回值,否则返回给定默认值

orElseGet(Supplier):如果值不为空,则返回值,否则,会执行作为参数传入的Supplier接口,并将返 回执行结果

总结Optional

  1. 解决什么问题

    解决java系统中出现的空指针异常的情况,简化if else对于对象是否为空的判断

  2. 不能解决的问题

    不能避免所有空指针异常

  3. 什么时候使用Optional

    主要用途作为返回类型。获取返回类型的实例后,可以提取里面的值(在有值的情况下),也可以提供其他 操作(没有值)和StreamAPI相结合使用

  4. 什么时候不能使用

    不要将其用在类中的字段类型,Optional不能序列化

    不要将其用在构造函数和方法的参数上。

1.7 流的操作

1.7.1 遍历/匹配/查找

属于终端操作

foreach:遍历操作

findFirst:查找第一个数据,返回Optional

findAny: 查找任意元素,返回Optional,如果是stream,返回第一个元素,相当于findFirst,如果使用的是parallelStream,返回随机一个元素

anyMatch:只要有一个元素符合判断条件,则返回true,否则返回false

noneMatch:每个元素都不符合判断条件,则返回true,否则返回false

allMatch:每个元素都符合判断条件,则返回true,否则返回false

public class TestStream1 {
    public static void main(String[] args) {
        List<Integer> list= Arrays.asList(12,23,31,56,43,42);
        //遍历
        // list.forEach(System.out::println);
        //list.stream().filter(x->x>25).forEach(System.out::println);
        //查找第一个
        /*Optional<Integer> first = list.stream().filter(x -> x >
        125).findFirst();
        System.out.println(first.orElse(100));*/
        //查找任意一个 主要应用于并行流
        /* Optional<Integer> any = list.stream().filter(x -> x >
        25).findAny();
        System.out.println(any.get());*/
        /*boolean b = list.stream().anyMatch(x -> x > 55);
        System.out.println("b = " + b);*/
        /*boolean b = list.stream().noneMatch(x -> x > 125);
        System.out.println("b = " + b);*/
        boolean b = list.stream().allMatch(x -> x > 5);
        System.out.println("b = " + b);
    }
}

1.7.2 过滤与切片

属于中间操作

1.7.2.1 过滤

过滤:也称作筛选,是按照一定的规则校验流中的元素,将所有符合条件的元素提取到一个新的流中的操作。

public class TestStream2 {
    public static void main(String[] args) {
        //对基本数据类型的过滤
        /* Stream<Integer> stream=Stream.of(5,8,21,32,21,19);
        stream.filter(x->x>20).forEach(System.out::println);*/
        //过滤引用类型
        List<Hero> list=new ArrayList<>();
        list.add(new Hero("亚瑟",10000));
        list.add(new Hero("项羽",14000));
        list.add(new Hero("项羽",14000));
        list.add(new Hero("米莱迪",5000));
        /*list.stream()
        .filter(hero->hero.getName().length()==2 && hero.getBlood()
        <=12000)
        //.filter(hero -> hero.getBlood()<=12000)
        .forEach(System.out::println);*/
        doFilter(hero -> hero.getName().length()==2,list);
    }
    public static void doFilter(Predicate<Hero> predicate,List<Hero> list){
    	list.stream().filter(predicate).forEach(System.out::println);
    }
}

1.7.2.2 切片

切片: 从集合中取出一部分相应的元素重新组成一个集合

  • 将集合截断: limit(long maxSize)操作,截断流,最大长度不超过maxSize
  • 在集合在跳过指定元素:skip(long n)操作,跳过前面元素,从第n个元素获取
  • 去重:distinct()操作,根据equals和hashCode方法进行比较,是否重复
public class TestStream3 {
    public static void main(String[] args) {
        List<Hero> list=new ArrayList<>();
        list.add(new Hero("亚瑟",10000));
        list.add(new Hero("项羽",14000));
        list.add(new Hero("项羽",14000));
        list.add(new Hero("米莱迪",5000));
        list.stream().filter(hero -> hero.getName().length()==2)
        //.limit(2)
        //.skip(2)
        .distinct() //hashset hashmap hashcode equals
        .forEach(System.out::println);
    }
}

1.7.3 聚合操作

属于终端操作

  • 取最大值

    max(new Comparator< T>)

  • 取最小值

    min(new Comparator< T>)

  • 统计个数

    count()

public class TestStream4 {
    public static void main(String[] args) {
        // max1();
        //min();
        //maxLength();
        count();
    }
    
    //获取一个整数集合中的最大值
    public static void max1() {
        List<Integer> list = Arrays.asList(12, 23, 31, 14, 8, 9, 100, 60);
        /*Integer max1 = Collections.max(list);
        System.out.println(max1);
        System.out.println("______________________");*/
        //默认规则排序
        /* Optional<Integer> max = stream.max(Integer::compareTo);
        if (max.isPresent())
        System.out.println(max.get());*/
        //自定义规则排序
        Stream<Integer> stream = list.stream().filter(x->x%2==1);
        Optional<Integer> max = stream.max((o1, o2)->o2 - o1);
        System.out.println(max.get());
    }
    
    public static void min() {
        List<Integer> list = Arrays.asList(12, 23, 31, 14, 8, 9, 100, 60);
        Stream<Integer> stream = list.stream().filter(x->x%2==1);
        Optional<Integer> min = stream.min(Integer::compareTo);
        if (min.isPresent())
        System.out.println(min.get());
    }
    //获取字符串长度最长的数据
    public static void maxLength(){
        List<String> list=Arrays.asList("AA","BBB","CC","DDDD","E");
        Stream<String> stream=list.stream();
        Optional<String> max =
        stream.max(Comparator.comparingInt(String::length));
        System.out.println(max.get());
    }
    public static void count(){
        List<Hero> list=new ArrayList<>();
        list.add(new Hero("亚瑟",10000));
        list.add(new Hero("项羽",14000));
        list.add(new Hero("项羽",14000));
        list.add(new Hero("米莱迪",5000));
        long count = list.stream().filter(hero ->
        hero.getName().length()==2).count();
        System.out.println(count);
    }
}

二、map映射操作

接收一个函数作为参数,这个函数会被应用到每个元素上,并将其映射成一个新的元素,用于转换其他形式或提取信息。

案例1:将集合中所有的浮点数都做四舍五入保留两位小数

public class TestMap {
    public static void main(String[] args) {
        List<Double> list= Arrays.asList(3.145,4.556,5.432,6.738);
        list.stream().map(TestMap::k2).forEach(System.out::println);
    }
    public static double k2(double x) {
    	return (int) ((x * 100) + 0.5) / 100d;//314.5
    }
}

案例2:属性的提取

public static void getHeroName() {
    List<Hero> heroList = Arrays.asList(new Hero("亚瑟", 10000),
    									new Hero("项羽", 14000),
    									new Hero("小乔", 5000));
    heroList.stream().map(Hero::getName).forEach(System.out::println);
    /*List<String> nameList = heroList.stream().map(Hero::getName)
    .collect(Collectors.toList());
    nameList.forEach(System.out::println);*/
}

案例3:对引用类型数据进行修改

public static void addBlood() {
    List<Hero> heroList = Arrays.asList(new Hero("亚瑟", 10000),
        new Hero("项羽", 14000),
        new Hero("小乔", 5000));
    //不改变原有数据
    heroList.stream().map(h->{
        Hero hero=new Hero(h.getName(),h.getBlood());
        hero.setBlood(hero.getBlood()+1000);
        return hero;
    }).forEach(System.out::println);
    //改变数据源中的数据
    /*heroList.stream().map(h -> {
    	h.setBlood(h.getBlood() + 1000);
    	return h;
    })
    .forEach(System.out::println);*/
    System.out.println("_________________________");
    heroList.forEach(System.out::println);
}

2.1 flatMap映射操作

接收一个函数作为参数,将流中的每个值都换成另一个流,把所有流连接成一个流。

案例:将两个字符集合合并成一个新的字符集合

public class TestFlatMap {
    public static void main(String[] args) {
        String str = "a,b,c,d,e";
        String str1 = "m,n,j";
        List<String> list = Arrays.asList(str, str1);
        Stream<String> stream = list.stream().flatMap(TestFlatMap::f);
        stream.forEach(System.out::println);
        /*Stream<Stream<String>> stream = list.stream().map(TestFlatMap::f);
        stream.forEach(s -> {
        s.forEach(System.out::println);
        }
        );*/
        //f(str).forEach(System.out::println);
        }
        public static Stream<String> f(String str) {//使用逗号方式分隔的字符串
        String[] strs = str.split(",");
        Stream<String> stream = Arrays.stream(strs);
        return stream;
    }
}

2.2 mapToInt mapToLong mapToDouble

以一个映射函数为参数,将流中每一个元素处理后成生一个新流

public static void testToInt1(){
    List<String> list=Arrays.asList("aabc","bbb","werwe","xxx");
    list.stream().mapToInt(String::length).forEach(System.out::println);
}
public static void testToInt(){
    List<Integer> list= Arrays.asList(12,23,34,45,56);
    list.stream().mapToInt(x->x*10).forEach(System.out::println);
}

三个函数生成新的流之后,可以进行很多后续操作,如求最大值、最小值、求和、求平均值、统计个数等相关操作

public class TestMapToInt {
    public static void main(String[] args) {
        //testToInt1();
        //maxAndMin();
        //sumAndAvg();
        //summary();
        range();
    }
    
    public static void range(){
        //闭区间,1和100都是包含的
        System.out.println(IntStream.rangeClosed(1, 100).sum());
        //左侧是闭区间,右侧开区间,1包含的,100是不包含的。
        int sum = IntStream.range(1, 100).sum();
        System.out.println(sum);
        //boxed将数值流转成Stream
        Stream<Integer> stream = IntStream.rangeClosed(1, 10).boxed();
        stream.forEach(System.out::println);
    }
    
    public static void summary(){
        IntSummaryStatistics x = Stream.of("1", "2", "3")
        .mapToInt(Integer::valueOf).summaryStatistics();
        System.out.println(x.getCount());
        System.out.println(x.getMax());
        System.out.println(x.getMin());
        System.out.println(x.getSum());
        System.out.println(x.getAverage());
    }
    
    public static void sumAndAvgAndCount(){
        List<Integer> list=Arrays.asList(12,23,34,43,32,21,9,56,78,21);
        int sum = list.stream().mapToInt(Number::intValue).sum();
        OptionalDouble average =
        list.stream().mapToInt(Number::intValue).average();
        long count = list.stream().mapToInt(Number::intValue).count();
        System.out.println("count = " + count);
        System.out.println("sum = " + sum);
        System.out.println("average.getAsDouble() = " +
        average.getAsDouble());
    }
    public static void maxAndMin(){
        List<Integer> list=Arrays.asList(12,23,34,43,32,21,9,56,78,21);
        OptionalInt max = list.stream().mapToInt(Number::intValue).max();
        OptionalInt min = list.stream().mapToInt(Number::intValue).min();
        System.out.println(max.getAsInt());
        System.out.println(min.getAsInt());
    }
}

2.3 归纳reduce

也称作缩减操作,是把一个流缩减成一个值,实现对集合求和、求乘积、求最大值、最小值操作。

属于终端操作

基本数据类型

public class TestReduce {
	public static void main(String[] args) {
        //求和
        Stream<Integer> stream = Stream.of(1, 12, 3, 4, 5);
        //使用mapToInt转成整数据的操作
        /* int sum = stream.mapToInt(Integer::intValue).sum();
        System.out.println(sum);*/
        //使用归约方式1
        /*Optional<Integer> reduce = stream.reduce(Integer::sum);
        System.out.println(reduce.get());*/
        //使用归约方式2
        /* Integer reduce = stream.reduce(0, Integer::sum);
        System.out.println(reduce);*/
        //求乘积
        /*Optional<Integer> reduce = stream.reduce((x, y) -> x * y);
        System.out.println(reduce.get());
        Integer reduce1 = stream.reduce(1, (x, y) -> x * y);
        System.out.println(reduce1);*/
        //求最大值
        /*Optional<Integer> reduce = stream.reduce((x, y) -> x > y ? x : y);
        System.out.println(reduce.get());*/
        //求最大值2
        /*Optional<Integer> reduce = stream.reduce(Integer::max);
        System.out.println(reduce.get());*/
        //求最小值
        Optional<Integer> reduce = stream.reduce(Integer::min);
        System.out.println(reduce.get());
    }
}

操作引用类型

public class TestReduceRef {
    public static void main(String[] args) {
        //求所有英雄的血量总和
        //求所有英雄中血量最高的英雄
        List<Hero> heroList = Arrays.asList(new Hero("亚瑟", 10000),
                                            new Hero("项羽", 14000),
                                            new Hero("小乔", 5000));
        //求和操作
        /* Integer reduce = heroList.stream().reduce(0,
        (sum, hero) -> sum += hero.getBlood(),
        Integer::sum);
        System.out.println(reduce);*/
        Integer x = heroList.stream().map(Hero::getBlood).reduce(0,Integer::sum);
        System.out.println(x);
        //最高值
        Integer max = heroList.stream().map(Hero::getBlood).reduce(0,Integer::max);
        System.out.println(max);
    }	
    
}

2.4 sorted 排序操作

属于中间操作

  • sorted()自然排序,要求流中元素要实现Comparable接口
  • sorted(Comparator comparator):自定义排序
public class Staff implements Comparable<Staff>{
    private String name;
    private Integer age;
    private Integer sal;
    public Staff() {
    }
    public Staff(String name, Integer age, Integer sal) {
        this.name = name;
        this.age = age;
        this.sal = sal;
    }
    public String getName() {
    	return name;
    }
    public void setName(String name) {
    	this.name = name;
    }
    public Integer getAge() {
    	return age;
    }
    public void setAge(Integer age) {
    	this.age = age;
    }
    public Integer getSal() {
    	return sal;
    }
    public void setSal(Integer sal) {
    	this.sal = sal;
    }
    @Override
    public String toString() {
        return "Staff{" +
        "name='" + name + '\'' +
        ", age=" + age +
        ", sal=" + sal +
            '}';
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Staff staff = (Staff) o;
        return Objects.equals(name, staff.name) && Objects.equals(age,
        staff.age) && Objects.equals(sal, staff.sal);
    }
    @Override
    public int hashCode() {
    	return Objects.hash(name, age, sal);
    }
    @Override
    public int compareTo(Staff o) {
    	return Integer.compare(this.age,o.age);
    }
}

public class TestSorted {
    public static void main(String[] args) {
        //自然排序
        List<Staff> list= Arrays.asList(
                                        new Staff("李白",22,10000),
                                        new Staff("杜甫",28,12000),
                                        new Staff("白居易",25,15000)
                                        );
        /* Collections.sort(list);
        list.forEach(System.out::println);*/
        // System.out.println("_________________________");
        list.stream().filter(s->s.getSal()>=12000).sorted().forEach(System.out::println);
    }
}

排序器自定义排序

public class TestSortedComparator {
    public static void main(String[] args) {
        List<Emp> list= Arrays.asList(
                                        new Emp("李白",22,10000),
                                        new Emp("杜甫",28,12000),
                                        new Emp("白居易",22,18000)
                                        );
        //按年龄升序排列
        /*list.stream().sorted(Comparator.comparingInt(Emp::getAge))
        .forEach(System.out::println);*/
        //按工资降序排列
        /*
        list.stream().sorted(Comparator.comparingInt(Emp::getSal).reversed())
        .forEach(System.out::println);*/
        //按年龄升序排列,如果年龄相同,再按工资升序排列
        /* list.stream().sorted(Comparator.comparingInt(Emp::getAge)
        .thenComparing(Emp::getSal)).forEach(System.out::println);*/
        //按年龄升序排列,如果年龄相同,按工资降序排列
        list.stream().sorted((o1, o2)-> {
            int compare = Integer.compare(o1.getAge(), o2.getAge());
            if (compare==0){
                return Integer.compare(o2.getSal(),o1.getSal());
            }else{
                return compare;
        }
        }).forEach(System.out::println);
    }
}

2.5 收集器

属于终端操作

把一个流收集起来,最终可以是收集成一个值,也可以收集成一个新的集合

因为流不存储数据,如果流操作完成之后,还想继续使用这些经过处理的数据,需要放到一个新的集合中,toList、toSet、toMap、toCollection等相关操作

2.5.1 生成一个新的集合

转list集合

List<Emp> list= Arrays.asList(
                                new Emp("李白",22,12000),
                                new Emp("杜甫",28,10000),
                                new Emp("白居易",25,11000),
                                new Emp("李贺",24,8000)
                                );
List<Emp> newList = list.stream().filter(e -> e.getName().startsWith("李")).collect(Collectors.toList());
newList.forEach(System.out::println);

转set操作

public static void toSet(){
    Set<Integer> set = Stream.of(1, 2, 3, 4, 5, 6, 7)
                        .filter(x -> x % 2 == 0)
                        .collect(Collectors.toSet());
    set.forEach(System.out::println);
}

转Map操作

public static void toMap(){
    List<Emp> list= Arrays.asList(
                                    new Emp("李白",22,12000),
                                    new Emp("杜甫",28,10000),
                                    new Emp("白居易",25,11000),
                                    new Emp("李贺",24,8000)
                                    );
    Map<String, Emp> map = list.stream().filter(e -> e.getSal() >=10000)
        .collect(Collectors.toMap(Emp::getName, e -> e));//key value
    map.forEach((k,v)-> System.out.println(k+"\t"+v));
}

转Collection操作

public static void toCollection(){
    ArrayList<String> collect = Stream.of("abc", "ddd", "xx")
    	.collect(Collectors.toCollection(ArrayList::new));
    collect.forEach(System.out::println);
}

2.5.2 统计与计算

counting:统计数量,可以用count替换

//统计人数
Long x = list.stream().filter(e -> e.getName().startsWith("李"))
.collect(Collectors.counting());
//可以替换
long y = list.stream().filter(e -> e.getName().startsWith("李")).count();
System.out.println(x);
System.out.println(y);

maxBy:获取最高值,可以用max替换

//获取最高值
Optional<Emp> collect = list.stream().filter(e -> e.getSal() >= 10000)
	.collect(Collectors.maxBy(Comparator.comparingInt(Emp::getSal)));
System.out.println(collect.get());
//可以替换
Optional<Emp> max = list.stream().filter(e -> e.getSal() >= 10000)
	.max(Comparator.comparingInt(Emp::getSal));
System.out.println(max.get());

minBy:获取最低值,可以用min替换

//获取最低值
Optional<Emp> min = list.stream().filter(e -> e.getSal() >= 10000)
	.collect(Collectors.minBy(Comparator.comparingInt(Emp::getSal)));
System.out.println(min.get());
//可以替换
Optional<Emp> min1 = list.stream().filter(e -> e.getSal() >= 10000)
	.min(Comparator.comparingInt(Emp::getSal));
System.out.println(min1.get());

summingInt:求和,可以用数值流的sum替换

//求和
Integer collect = list.stream().collect(Collectors.summingInt(Emp::getSal));
System.out.println(collect);
//可以替换
int sum = list.stream().mapToInt(Emp::getSal).sum();
System.out.println(sum);

averagingDouble:求平均值,可以用数值流的average替换

//求平均值
Double collect =
list.stream().collect(Collectors.averagingDouble(Emp::getSal));
System.out.println(collect);

summarizingInt:一次性获取所有相关信息,等价于数值流的summaryStatistics

//一次性获取所有信息
IntSummaryStatistics collect = list.stream()
.collect(Collectors.summarizingInt(Emp::getSal));
System.out.println(collect.getMax());
System.out.println(collect.getMin());
System.out.println(collect.getCount());
System.out.println(collect.getSum());
System.out.println(collect.getAverage());

2.5.3 分组

分区:partitioningBy,只能分成两组,符合条件的是一组,不符合条件的是另一组

调用该操作,最后会返回Map,key是Boolean类型,分成true和false

public class TestPartitioningBy {
    public static void main(String[] args) {
        List<Emp> list= Arrays.asList(
                                        new Emp("李白",22,12000),
                                        new Emp("杜甫",25,9000),
                                        new Emp("白居易",26,14000),
                                        new Emp("李贺",23,16000)
                                        );
        //true false
        Map<Boolean, List<Emp>> collect = list.stream()
            .collect(Collectors.partitioningBy(x -> x.getSal() >=
        10000));
        collect.forEach((k,v)-> {
        System.out.println(k);
        v.forEach(System.out::println);
        });
    }
}

分组:groupingBy,将集合分成多个Map,如可以按员工年龄分组,或者按工资

public class TestGroupingBy {
    public static void main(String[] args) {
        List<Employer> list= Arrays.asList(
                                            new Employer("李白",25,"研发部","男"),
                                            new Employer("杜甫",28,"研发部","女"),
                                            new Employer("陆游",27,"研发部","女"),
                                            new Employer("白居易",35,"测试部","男"),
                                            new Employer("李商隐",28,"测试部","女")
                                            );
        //按年龄大小进行分组
        Map<String, List<Employer>> listMap =
        list.stream().collect(Collectors.groupingBy(e -> {
            if (e.getAge() < 30)
            return "青年员工";
            else
            return "中年员工";
            }));
            listMap.forEach((k,v)->{
            System.out.println("员工分类:"+k);
            v.forEach(System.out::println);
        });
        //按部门进行分组
        /*Map<String, List<Employer>> map1 = list.stream()
        .collect(Collectors.groupingBy(Employer::getDept));
        map1.forEach((k,v)->{
        System.out.println("部门名称:"+k);
        v.forEach(System.out::println);
        });*/
        //按性别进行分组
        /* Map<String, List<Employer>> map1 = list.stream()
        .collect(Collectors.groupingBy(Employer::getGender));
        map1.forEach((k,v)->{
        if ("男".equals(k)) {
        System.out.println("性别:" + k);
        v.forEach(System.out::println);
        }
        });*/
        //分先性别进行分组,再按部门进行分组
        /* Map<String, Map<String, List<Employer>>> collect = list.stream()
        .collect(Collectors.groupingBy(Employer::getGender,
        Collectors.groupingBy(Employer::getDept)));
        collect.forEach((k,v)->{
        System.out.println("性别:"+k);
        v.forEach((k1,v1)->{
        System.out.println("部门名称:"+k1);
        v1.forEach(System.out::println);
        });
        });*/
    }
}


2.5.4 拼接操作joining

可以将Stream 中的元素,按指定的特殊符号进行拼接,得到一个字符串

  1. 无参方法,直接拼接
  2. 有一个参数方法,连接符号
  3. 有三个参数方法,连接符号,前缀(整个字符串的前缀),后缀(整个字符串的后缀)
public class TestJoining {
    public static void main(String[] args) {
        List<Employer> list= Arrays.asList(
                                            new Employer("李白",25,"研发部","男"),
                                            new Employer("杜甫",28,"研发部","女"),
                                            new Employer("陆游",27,"研发部","女"),
                                            new Employer("白居易",35,"测试部","男"),
                                            new Employer("李商隐",28,"测试部","女")
                                            );
        //将所有员工的姓名拼接成一个字符串
        //joining 无参,直接拼接
        /*String str = list.stream().map(Employer::getName)
        .collect(Collectors.joining());
        System.out.println("str = " + str);*/
        //一个参数,连接符号
        /*String str = list.stream().map(Employer::getName).collect(
        Collectors.joining("_")
        );
        System.out.println("str = " + str);*/
        //三个参数,连接符号,前缀,后缀
        String str = list.stream().map(Employer::getName).collect(
        Collectors.joining("_", "|", "|")
        );
        System.out.println("str = " + str);
    }
}

2.5.5 归约 reducing

public class TestReducing {
    public static void main(String[] args) {
        Stream<Integer> stream = Stream.of(1, 12, 3, 4, 5);
        //Optional<Integer> sum =
        stream.collect(Collectors.reducing(Integer::sum));
        Optional<Integer> reduce = stream.reduce(Integer::sum);
        System.out.println(reduce.get());
        //System.out.println(sum.get());
    }
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小郑在努力ing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值