Stream流式编程操作

简介

在诺大的江湖中,啊基和啊坝两人游走于其中,啊基感叹自己要多学一些武功,于是啊基告别了啊坝,开始了自己为期两年半的练习…

流的构建

  1. 静态方法Stream.of,通过显式值创建一个流
Stream<String> stream = Stream.of("老虎", "狮子", "熊猫");
stream.forEach(System.out::println);
//输出结果:
老虎
狮子
熊猫
  1. 静态方法Arrays.stream从数组创建一个流
int[] numbers= {1,2,3,4};
IntStream stream= Arrays.stream(numbers);
stream.forEach(System.out::println);
//输出结果:
1
2
3
4
  1. 由文件生成流
        Stream<String> lines=null;
		try {
			lines=Files.lines(Paths.get("myDog.txt"),Charset.defaultCharset());	
			lines.forEach(System.out::println);
		} catch (IOException e) {
			
			e.printStackTrace();
		}finally {
			lines.close();
		}

  1. 集合转成stream
String[] numbers= {"1","2","3","4"};
List<String> mylist = Arrays.asList(numbers);
mylist.stream().forEach(System.out::println);
//输出结果:
1
2
3
4

中间操作

设置基础值:

List<Animal>  list = Arrays.asList(
                new Animal("老虎",8,150,"北京市"),
                new Animal("狮子",5,160,"北京市"),
                new Animal("熊猫",13,130,"四川"),
                new Animal("金丝猴",23,60,"四川"),
                new Animal("长颈鹿",8,260,"天津"),
                new Animal("狗",18,90,"上海"));

@Data
public class Animal {
    private String name;
    private Integer age;
    private Integer height;
    private String home;
 }
调试功能
  • peek() 操作的目的是帮助调试,它允许你无修改地查看流中的元素。
  • skip()返回一个扔掉了前n个元素的流。如果流中元素不足n个,则返回一个空流
  • limit(n):该方法会返回一个不超过给定长度的流
list.stream().skip(2).peek(System.out::println)
                .map(Animal::getName).limit(3).forEach(System.out::println);
//输出结果:
Animal(name=熊猫, age=13, height=130, home=四川)
熊猫
Animal(name=金丝猴, age=23, height=60, home=四川)
金丝猴
Animal(name=长颈鹿, age=8, height=260, home=天津)
长颈鹿

排序
  • sorted():进行排序,它可以把 Lambda 函数作为参数传入 或者传入一个 Comparator 参数
     按照age字段进行排序:
     
       //方式1
        list.stream().sorted((d1,d2)->d1.getAge() - d2.getAge()).forEach(System.out::println);
        //或者 方式2
        list.stream().sorted(Comparator.comparingInt(Animal::getAge)).forEach(System.out::println);
//输出结果:
Animal(name=狮子, age=5, height=160, home=北京市)
Animal(name=老虎, age=8, height=150, home=北京市)
Animal(name=长颈鹿, age=8, height=260, home=天津)
Animal(name=熊猫, age=13, height=130, home=四川)
Animal(name=狗, age=18, height=90, home=上海)
Animal(name=金丝猴, age=23, height=60, home=四川)
移除元素
  • distinct():可用于消除流中的重复元素。相比创建一个 Set 集合来消除重复,该方法的工作量要少得多。

  • filter(Predicate):过滤操作,保留如下元素:若元素传递给过滤函数产生的结
    果为 true。

查找age大于2并且去重:

list.stream().filter(u->u.getAge() > 2).map(Animal::getAge).distinct().forEach(System.out::println);
//输出结果:
8
5
13
23
18

应用函数到元素
  • map(Function):将函数操作应用在输入流的元素中,并将返回值传递到输出流
    中。
  • mapToInt(ToIntFunction):操作同上,但结果是 IntStream。
  • mapToLong(ToLongFunction):操作同上,但结果是 LongStream。
  • mapToDouble(ToDoubleFunction):操作同上,但结果是 DoubleStream。
 获取前两个的name和age :
 list.stream().map(Animal::getName).limit(2).forEach(System.out::println);
 list.stream().mapToLong(Animal::getAge).limit(2).forEach(System.out::println);
 //输出结果:
老虎
狮子
8
5
IntStream  age  =list.stream().mapToInt(x -> x.getAge());
System.out.println(age.sum());
//输出结果:
75
扁平化

flatMap() 做了两件事:将产生流的函数应用在每个元素上(与 map() 所做的相
同),然后将每个流都扁平化为元素,因而最终产生的仅仅是元素。

  • flatMap(Function):当 Function 产生流时使用。
  • flatMapToInt(Function):当 Function 产生 IntStream 时使用。
  • flatMapToLong(Function):当 Function 产生 LongStream 时使用。
  • flatMapToDouble(Function):当 Function 产生 DoubleStream 时使用。
将{"Hello", "World"}进行扁平化,拆分成多个字母:

String[] strings = {"Hello", "World"};
        Stream.of(strings)
                .map(s -> s.split(""))
                .flatMap(s -> Stream.of(s))
                .distinct().forEach(System.out::println);
 //输出结果:
H
e
l
o
W
r
d
数值
  • boxed()方法:要把原始流转换成一般流(这里每个int都会装箱成一个Integer)
IntStream  age  = list.stream().mapToInt(x -> x.getAge());
Stream<Integer>  intAge = age.boxed();
System.out.println(intAge);
 //输出结果:
 java.util.stream.IntPipeline$4@73c6c3b2

IntStream和LongStream的静态方法中可以应用:

  • range方法(左闭右开)
  • rangeClosed方法(左闭右闭)
在1到20间,查找大于15的值:

IntStream  test = IntStream.range(1,20).filter(x -> x> 15);
test.forEach(x->{System.out.print(" "+x);});
 //输出结果:
 16 17 18 19
在1到10间,查找大于5的值:
 IntStream  test = IntStream.rangeClosed(1,10).filter(x -> x> 5);
 test.forEach(x->{System.out.print(" "+x);});
 //输出结果:
  6 7 8 9 10

Optional 类

啊基在练习中,发现总有一些空流,他想有没有一个新的武功,可作为流元素
的持有者,即使查看的元素不存在也能友好地提示(也就是说,不会发生异常)?
在这里插入图片描述

创建 Optional
  • empty():生成一个空 Optional。
  • of(value):将一个非空值包装到 Optional 里。
  • ofNullable(value):针对一个可能为空的值,为空时自动生成 Optional.empty,
    否则将值包装在 Optional 中
Optional optional = Optional.ofNullable(list);
System.out.println(optional);
 //输出结果:
Optional[[Animal(name=老虎, age=8, height=150, home=北京市), Animal(name=狮子, age=5, height=160, home=北京市), Animal(name=熊猫, age=13, height=130, home=四川), Animal(name=金丝猴, age=23, height=60, home=四川), Animal(name=长颈鹿, age=8, height=260, home=天津), Animal(name=狗, age=18, height=90, home=上海)]]

便利函数
  • ifPresent(Consumer):当值存在时调用 Consumer,否则什么也不做。
    对于Consumer的描述: Consumer功能介绍
  • orElse(otherObject):如果值存在则直接返回,否则生成 otherObject。
  • orElseGet(Supplier):如果值存在则直接返回,否则使用 Supplier 函数生成一
    个可替代对象。
    【 1.当Optonal的值是空值时,无论orElse还是orElseGet都会执行,返回值是它们各自的执行结果返回。
    2.而当返回的Optional有值时,orElse中会执行但返回值是Optional的值,而orElseGet不会执行.
    3. orElse和orElseGet使用区别
  • orElseThrow(Supplier):如果值存在直接返回,否则使用 Supplier 函数生成一
    个异常
    对于Supplier的描述:Supplier功能介绍

【Supplier表示结果的提供者,该结果返回一个对象且不接受任何参数,而Consumer表示一个操作,其接受单个输入参数且不返回任何结果】

 ifPresent(Consumer)返回列表中第一个元素的name:
 
Optional<Animal> optional = Optional.ofNullable(list.get(0));
        optional.ifPresent(
                x ->
                { System.out.println(x.getName()); }
        );
//输出结果:    
老虎
对象操作

• filter(Predicate):对 Optional 中的内容应用 Predicate 并将结果返回。如果
Optional 不满足 Predicate ,将 Optional 转化为空 Optional 。如果 Optional
已经为空,则直接返回空 Optional 。

• map(Function):如果 Optional 不为空,应用 Function 于 Optional 中的内容,
并返回结果。否则直接返回 Optional.empty。

• flatMap(Function):同 map(),但是提供的映射函数将结果包装在 Optional 对
象中,因此 flatMap() 不会在最后进行任何包装。

Optional ww = Optional.ofNullable(list).map(yy ->
        {
            return yy.get(2).getName();
        });
        System.out.println("ww值:"+ ww);
//输出结果:        
ww值:Optional[熊猫]

终端操作

终端操作将会获取流的最终结果,至此我们无法再继续往后传递流。可以说,终端
操作总是我们在流管道中所做的最后一件事。

数组
  • toArray():将流转换成适当类型的数组。
  • toArray(generator):在特殊情况下,生成自定义类型的数组
Object[] arr = list.stream().map(m -> m.getName()).toArray();
System.out.println("数组值:"+ JSONObject.toJSONString(arr));
//输出结果:  
数组值:["老虎","狮子","熊猫","金丝猴","长颈鹿","狗"]
String[] dd1 = list.stream().map(z -> z.getName()).toArray(String[]::new);
System.out.println("数组值dd1:"+ JSONObject.toJSONString(dd1));
//输出结果:
数组值dd1:["老虎","狮子","熊猫","金丝猴","长颈鹿","狗"]
循环
  • forEach(Consumer) 常见的比如 System.out::println 作为 Consumer 函数。
  • forEachOrdered(Consumer):保证 forEach 按照原始流顺序操作。
list.stream().map(z -> z.getName()).forEach(System.out::println);
//输出结果:
老虎
狮子
熊猫
金丝猴
长颈鹿
狗
list.stream().map(z -> z.getName()).forEachOrdered(System.out::println);
//输出结果:
老虎
狮子
熊猫
金丝猴
长颈鹿
狗
集合

可以说是内容最繁多、功能最丰富的部分了。从字面上去理解,就是把一个流收集起来,最终可以是收集成一个值也可以收集成一个新的集合

  • collect(Collector):使用 Collector 收集流元素到结果集合中。
  • collect(Supplier, BiConsumer, BiConsumer):同上,第一个参数 Supplier 创
    建了一个新的结果集合,第二个参数 BiConsumer 将下一个元素收集到结果集
    合中,第三个参数 BiConsumer 用于将两个结果集合合并起来

可以参考:Stream操作时Collectors工具类

组合

也称归约,也称缩减,顾名思义,是把一个流缩减成一个值,能实现对集合求和、求乘积和求最值操作。

  • reduce(BinaryOperator):使用 BinaryOperator 来组合所有流中的元素。因为
    流可能为空,其返回值为 Optional。
  • reduce(identity, BinaryOperator):功能同上,但是使用 identity 作为其组
    合的初始值。因此如果流为空,identity 就是结果。
  • reduce(identity, BiFunction, BinaryOperator):更复杂的使用形式(暂不介
    绍),这里把它包含在内,因为它可以提高效率。通常,我们可以显式地组合 map()
    和 reduce() 来更简单的表达它。

详细的reduce()功能可以参考:Stream 流中 Reduce 操作

List<Integer> numbers=Arrays.asList(2,3,4,8);
        int sum=numbers.stream().reduce(0, (a,b)->a+b);
        System.out.println("sum="+sum);
 //输出结果:
sum=17
匹配

• anyMatch(Predicate):如果流的任意一个元素提供给 Predicate 返回 true ,结
果返回为 true。在第一个 true 是停止执行计算。

是否有age>15的值:

        if(list.stream().map(Animal::getAge).anyMatch(x -> x> 15)){
            System.out.println("有");
        }else{
            System.out.println("无");
        }
 //输出结果:
 有
  • allMatch(Predicate) :元素是否都能匹配。如果流的每个元素提供给 Predicate 都返回 true ,结果返回为 true。在第一个 false 时,则停止执行计算。
是否所有值age>15:

        if(list.stream().map(Animal::getAge).allMatch(x -> x> 15)){
            System.out.println("有");
        }else{
            System.out.println("无");
        }
        
 //输出结果:
 无        

• noneMatch(Predicate):如果流的每个元素提供给 Predicate 都返回 false 时,结
果返回为 true。在第一个 true 时停止执行计算。

查找
  • findAny()方法将返回当前任意流元素的 Optional,如果流为空返回 Optional.empty
返回任意一个name:

System.out.println(list.stream().map(Animal::getName).findAny());
//输出结果:
Optional[老虎]
  • findFirst():返回第一个流元素的 Optional,如果流为空返回 Optional.empty。
返回第一个name:

System.out.println(list.stream().map(Animal::getName).findFirst());
//输出结果:
Optional[老虎]
信息

• count():流中的元素个数。
• max(Comparator):根据所传入的 Comparator 所决定的 “最大” 元素。
• min(Comparator):根据所传入的 Comparator 所决定的 “最小” 元素。

获取age中的最大值:

int mm = list.stream().map(z -> z.getAge()).max(Integer::compare).get();
System.out.println("mm值:"+ mm);
//输出结果:
mm值:23
数字流信息
  • average() :求取流元素平均值。
  • max() 和 min():数值流操作无需 Comparator。
  • sum():对所有流元素进行求和。
  • summaryStatistics():生成可能有用的数据。目前并不太清楚这个方法存在的
    必要性,因为我们其实可以用更直接的方法获得需要的数据。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值