Lambda表达式与Stream流

目录

一.什么是Lambda表达式

二.语法格式

三.Lambda表达式使用

1.从匿名类到Lambda的转化

2.匿名内部类作为参数传递

3.函数式接口

4.作为参数传递Lambda表达式

5.方法引用

6.构造器引用

7.数组引用

四.Stream流

1.什么是Stream流

2.Stream流特点

3.操作步骤

4.创建流的例子

5.Stream流的中间操作

6.Stream流的终止操作


一.什么是Lambda表达式

Lambda 是一个匿名函数,可以将其理解为是一段可以传递的代码,或者说是将代码像数据一样进行传递。使用Lambda表达式可以写出更简洁、更灵活的代码。它作为一种更紧凑的代码风格,使 Java的语言表达能力得到了提升。

Lambda 表达式在Java 语言中引入了一个新的语法元 素和操作符 “->” , 该操作符被称 为 Lambda 操作符或箭头操作符。它将 Lambda 分为 两个部分:

  • 左侧:指定了 Lambda 表达式需要的所有参数
  • 右侧:指定了 Lambda 体,即 Lambda 表达式要执行 的功能。

二.语法格式

1.无参,无返回值

Runnable runnable = ()-> System.out.println("hello");

2.需要一个参数来传值

Consumer<String>stringConsumer = args-> System.out.println(args);

3.需要两个参数---代码块,代码块中只有return一条语句时,大括号{}可省略

//多语句时
        BinaryOperator<Long>binaryOperator = (x,y)->{
            System.out.println("hahaha");
            return x+y;
        };

//只有返回语句时
BinaryOperator<Long>binaryOperator1 = (x,y)->x+y;
//lambda表达式的类型是由编译器根据上下环境推断出来的,一般来说不用自己编写数据类型

三.Lambda表达式使用

1.从匿名类到Lambda的转化

直接上对比代码和图:

//原来创建Runnable的操作
Runnable runnable1 = new Runnable() {
      @Override
      public void run() {
      System.out.println("runnable1:hello world");
      }
};
runnable1.run();

//Lambda
Runnable runnable2 = ()-> System.out.println("runnable2:hello world");
runnable2.run();

结果:

2.匿名内部类作为参数传递

//原来使用匿名内部类作为参数传递
TreeSet<String> ts = new TreeSet<>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return Integer.compare(o1.length(),o2.length());
            }
        });

//lambda1
TreeSet<String>ts2 = new TreeSet<>(
                ((o1, o2) -> Integer.compare(o1.length(),o2.length()))
        );

//lambda2(更简单版)
TreeSet<String>ts2 = new TreeSet<>(
                (Comparator.comparingInt(String::length))
        );

3.函数式接口

函数式接口:只包含一个抽象方法的接口称为函数式接口。

public interface getage{
        public int getvalue();
    }

也可以在任意函数式接口上使用@FunctionalInterface注解标明,这样可以检查其函数式接口的正确性,同时也会在javadoc中生成一条说明,说明这个接口是一个函数式接口。

@FunctionalInterface
    public interface getage{
        public int getvalue();
    }

4.作为参数传递Lambda表达式

@FunctionalInterface
public interface GetName<T>{
       public T getValue(T t);
}

public String toUpperString(GetName<String>getName,String name){
      return getName.getValue(name);
}
@Test
public void test(){
     String string = toUpperString(str->str.toUpperCase(),"xiaolizi");
     System.out.println(string);
}

5.方法引用

  • (x)-> System.out.println(x);
    等价于
    System.out::println;
  • BinaryOperator<Double> binaryOperator = (x,y)->Math.pow(x,y);
    等价于
    BinaryOperator<Double> binaryOperator = Math::pow;
  • compare((x,y) -> x.equals(y),"abcdf","abcdf");
    等价于
    compare(String::equals,"abcdf","abcdf");

6.构造器引用

与函数式接口相结合,自动与函数式接口中方法兼容。 可以把构造器引用赋值给定义的方法,与构造器参数 列表要与接口中抽象方法的参数列表一致!

Function<Integer,MyClass>function = n->new MyClass(n);
等价于
Function<Integer,MyClass>function = MyClass::new;
这里的MyClass是一个函数式接口,请自行定义

7.数组引用

Function<Integer,Integer[]>function = n -> new Integer[];
等价于
Function<Integer,Integer[]>function = Integer[]::new;

四.Stream流

1.什么是Stream流

Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对 集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。 使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数 据库查询。也可以使用 Stream API 来并行执行操作。简而言之,  Stream API 提供了一种高效且易于使用的处理数据的方式。

Stream流是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。

2.Stream流特点

  • Stream 自己不会存储元素。
  • Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
  • Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

3.操作步骤

  1. 创建Stream:使用一个数据源获取一个流
  2. 中间操作/中间操作链:对数据源进行处理(使用Lambda表达式比较方便,同时Stream流还有一些内置方法)
  3. 终止操作:执行中间操作,并产生结果

4.创建流的例子

1.由数组创建

  • public static IntStream stream(int[] array)
  • public static LongStream stream(long[] array)
  • public static DoubleStream stream(double[] array)

2.由值创建

对象.stream().中间操作.终止操作;

5.Stream流的中间操作

假设我现在有一个Apple类,里面存放了苹果的颜色和重量

package Apple分类;

public class Apple {
    private String color;
    private float weight;


    public Apple(String color, float weight){
        this.color = color;
        this.weight =weight;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public float getWeight() {
        return weight;
    }

    public void setWeight(float weight) {
        this.weight = weight;
    }
    //这个toString不写的话会乱码的
    @Override
    public String toString() {
        return "Apple [" +
                "color='" + color + '\'' +
                ", weight=" + weight +
                ']';
    }
    //后面两个暂时用于去重
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Apple apple = (Apple) o;
        return Float.compare(apple.weight, weight) == 0 &&
                Objects.equals(color, apple.color);
    }

    @Override
    public int hashCode() {
        return Objects.hash(color, weight);
    }
}

然后我现在有这些苹果

package Apple分类;

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

public class AppleMain {

    public static void main(String[] args) {
        //我的苹果
        List<Apple> apples = Arrays.asList(
                new Apple("yello",150),
                new Apple("green",50),
                new Apple("red",100),
                new Apple("yello",100),
                new Apple("green",150),
                new Apple("red",50),
                new Apple("green",110),
                new Apple("green",90),
                new Apple("green",70),
                new Apple("red",110),
                new Apple("yello",50),
                new Apple("green",200),
                new Apple("red",150),
                new Apple("red",70),
                new Apple("red",70),
                new Apple("red",70)
        );
    }
}

(1). 过滤器filter()

现在,我要挑选绿色的苹果

apples.stream().filter(a -> a.getColor().equals("green")).forEach(System.out::println);

我现在不要绿苹果了,我想看看重量超过100的苹果有哪些

apples.stream().filter(a -> a.getWeight()>100).forEach(System.out::println);

那么,重量大于100且为绿色的苹果有哪些呢?

apples.stream().filter(a -> a.getWeight()>100).filter(a->a.getColor().equals("green")).forEach(System.out::println);

(2). 去重distinct()

现在,我想知道有多少种不同重量且不同颜色的苹果(去除重复项)

apples.stream().distinct().forEach(System.out::println);

(3). 排序sorted()

苹果顺序有点乱,我想按颜色排序看看

apples.stream().sorted(Comparator.comparing(Apple::getColor)).forEach(System.out::println);

按重量排序呢?

apples.stream().sorted(Comparator.comparing(Apple::getWeight)).forEach(System.out::println);

那么按颜色排序的同时按重量排序呢?

apples.stream().sorted(Comparator.comparing(Apple::getWeight)).sorted(Comparator.comparing(Apple::getColor)).forEach(System.out::println);

重量逆序呢?

apples.stream().sorted(Comparator.comparing(Apple::getWeight).reversed()).sorted(Comparator.comparing(Apple::getColor)).forEach(System.out::println);

(4). 截断流limit()

上面的排序之后的苹果太多了,我只要前5个

apples.stream().sorted(Comparator.comparing(Apple::getWeight).reversed()).sorted(Comparator.comparing(Apple::getColor)).limit(5).forEach(System.out::println);

(5). 跳过元素skip()

现在,我只想要前五个中的后两个,前三个苹果不要,我想跳过

apples.stream()
        .sorted(Comparator.comparing(Apple::getWeight).reversed())
        .sorted(Comparator.comparing(Apple::getColor))
        .limit(5)
        .skip(3)
        .forEach(System.out::println);

(6). 函数传递map()

突然之间,我又想知道有多少种颜色的苹果了,但是我不想知道他们的重量

apples.stream()
        .map(Apple::getColor)
        .distinct()
        .forEach(System.out::println);

我想知道的是他们大写的样子

apples.stream()
        .map(Apple::getColor)
        .map(String::toUpperCase)
        .distinct()
        .forEach(System.out::println);

6.Stream流的终止操作

以下操作因为都是终止操作,所以需要先赋值,再输出。

(1).判断是否存在anyMatch()

Boolean b = apples.stream().anyMatch(a->a.getColor().equals("green"));
System.out.println("green苹果存在? "+b);

Boolean o = apples.stream().anyMatch(a->a.getColor().equals("orange"));
System.out.println("orange苹果存在? "+o);

(2).判断所有选中元素是否相同allMatch()

Boolean g = apples.stream().allMatch(a->a.getColor().equals("green"));
System.out.println(g);

(3).是否没有匹配所有元素(当前元素是否不在集合中)noneMatch()

Boolean g = apples.stream().noneMatch(a->a.getColor().equals("green"));
System.out.println(g);
Boolean b = apples.stream().noneMatch(a->a.getColor().equals("black"));
System.out.println(b);

(4).找到第一个元素与找到一个元素findFirst()与findAny();

Optional<Apple> a = apples.stream().findFirst();
System.out.println(a);

Optional<Apple>b = apples.stream().findAny();
System.out.println(b);
//找元素一般是从第一个元素开始

  没有元素时:

(5).统计流中元素个数count()

long count = apples.stream().count();
System.out.println(count);

(6).最大值与最小值max()与min()

Optional<Float> optionalApple = apples.stream()
        .map(a->a.getWeight())
        .max(Float::compareTo);
System.out.println(optionalApple);

Optional<Float> optionalApple = apples.stream()
        .map(a->a.getWeight())
        .min(Float::compareTo);
System.out.println(optionalApple);

(7).内部迭代forEach()

apples.stream()
        .map(Apple::getColor)
        .map(String::toUpperCase)
        .distinct()
        .forEach(System.out::println);

(8).整合reduce()

目前我只知道调用sum求和

Optional<Float> optionalFloat = apples.stream()
        .map(Apple::getWeight)
        .distinct()
        .reduce(Float::sum);
System.out.println(optionalFloat);

 

 

暂时先到这了,其他的看我后序学习情况吧。。

  • 11
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值