前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java8 新特性 -- Lambda 表达式的常规用法

Java8 新特性 -- Lambda 表达式的常规用法

原创
作者头像
啵啵肠
发布2023-11-20 14:44:12
1160
发布2023-11-20 14:44:12
举报

1、Java8 新特性 -- Lambda 表达式

1.1、单方法接口使用 Lambda 表达式
代码语言:c#
复制
public interface ITest {
    /**
     * go
     */
    void go();
}

public static void main(String[] args) {
        ITest t = ()->{
            System.out.println(333);
        };
    }

使用场景:单接口快速创建实现类。

1.2、Lambda 中的方法引用运算符 '::' 用法
代码语言:c#
复制
public void test(){}

public static void staticTest(){}

该运算符可用于以下场景:

(1)类::实例方法名

Person::test

(2)类::静态方法名

代码语言:java
复制
public class TestComponent {

    @FunctionalInterface
    public interface ITest {
        int p(int i);
    }

    public static void runTest(ITest test,int i){
        test.p(i);
    }
    public static int case1(int i) {
        return i;
    }

    public static void main(String[] args) {
        TestComponent.runTest(TestComponent::case1,7);
    }
}

(3)对象::实例方法名

代码语言:java
复制
public class TestComponent {

    @FunctionalInterface
    public interface ITest {
        int p(int i);
    }

    public static void runTest(ITest test,int i){
        test.p(i);
    }
    public int case1(int i) {
        return i;
    }

    public static void main(String[] args) {
        TestComponent testComponent = new TestComponent();
        TestComponent.runTest(testComponent::case1,7);
    }
}

后两种可以这样理解:“::” 是方法引用操作符,传递的是方法的引用,在接口调用唯一方法的时候就是在调用传递进来的方法引用,所以在以上语法的基础上,只要保持返回值和参数完全一致就能将方法传递进去。

1.3、Lambda 中的 stream() 做了哪些优化?

优化 1:操作并行。 Lambda 在执行操作方法的时候会尽可能的多执行用户操作。比如我们需要将一个集合排序、筛选等操作,常规处理可能会将集合进行多次迭代处理数据,而 stream api 在执行的时候会将这些操作放到一个迭代中操作。

优化 2:节省存储空间。 在我们的常规方法中,一个排序后的操作可能会放置到新的集合中存储,而在 stream 中是在触发结束装后才会进行计算操作,省去了中间的存储操作。

具体可参考 :www.cnblogs.com/CarpenterLe…

1.4、stream api

对象准备:

代码语言:less
复制
@Data
@Accessors(chain = true)
public class Person {

    private Integer id;

    private String name;
}

filter:过滤流,取匹配条件表达式的数据。

代码语言:scss
复制
public static void main(String[] args) {
        List<Person> list = new ArrayList<>();
        list.add(new Person().setName("都覅说").setId(1));
        list.add(new Person().setName("认为我").setId(7));
        list.add(new Person().setName("而为人发").setId(8));
        list.add(new Person().setName("都发").setId(10));
        list.add(new Person().setName("都发").setId(3));
        list.add(new Person().setName("过的").setId(4));
//        保留 id > 6 的数据
        list.stream().filter(p->p.getId() > 6).collect(Collectors.toList()).forEach(System.out::println);

    }

输出:
   Person(id=7, name=认为我)
   Person(id=8, name=而为人发)
   Person(id=10, name=都发)

map:转换流,将一种数据类型转换成另外一种数据类型,转换的类型取决于 Function 的 apply 返回的数据类型。

代码语言:scss
复制
    public static void main(String[] args) {
        List<Person> list = new ArrayList<>();
        list.add(new Person().setName("都覅说").setId(1));
        list.add(new Person().setName("认为我").setId(7));
        list.add(new Person().setName("而为人发").setId(8));
        list.add(new Person().setName("都发").setId(10));
        list.add(new Person().setName("都发").setId(3));
        list.add(new Person().setName("过的").setId(4));

        List<Integer> collect = list.stream().map(p -> 1).collect(Collectors.toList());
        System.out.println(collect);
        List<String> collect1 = list.stream().map(Person::getName).collect(Collectors.toList());
        System.out.println(collect1);
    }

    输出:
    [1, 1, 1, 1, 1, 1]
    [都覅说, 认为我, 而为人发, 都发, 都发, 过的]

mapToInt:转换流,将数据类型转换成 int 类型

代码语言:scss
复制
public static void main(String[] args) {
        List<Person> list = new ArrayList<>();
        list.add(new Person().setName("都覅说").setId(1));
        list.add(new Person().setName("认为我").setId(7));
        list.add(new Person().setName("而为人发").setId(8));
        list.add(new Person().setName("都发").setId(10));
        list.add(new Person().setName("都发").setId(3));
        list.add(new Person().setName("过的").setId(4));

        int[] ints = list.stream().mapToInt(Person::getId).toArray();
        System.out.println(Arrays.toString(ints));

//        求平均值
        double v = list.stream().mapToInt(Person::getId).average().orElse(0);
        System.out.println(v);
    }

    输出:
    [1, 7, 8, 10, 3, 4]
    5.5

mapToLong:转换流,将数据转换成 long 类型

mapToDouble:转换流,将数据类型转化成 double 类型

distinct:去重,去重规则是根据 equals 和 hashCode 方法来过滤的。

代码语言:less
复制
public static void main(String[] args) {
        List<Person> list = new ArrayList<>();
        list.add(new Person().setName("都覅说").setId(1));
        list.add(new Person().setName("认为我").setId(7));
        list.add(new Person().setName("而为人发").setId(8));
        list.add(new Person().setName("都发").setId(10));
        list.add(new Person().setName("都发").setId(10));
        list.add(new Person().setName("都发").setId(3));
        list.add(new Person().setName("过的").setId(4));
        list.add(new Person().setName("过的").setId(4));

        List<Person> collect = list.stream().distinct().collect(Collectors.toList());
        System.out.println(collect);

    }

[Person(id=1, name=都覅说), Person(id=7, name=认为我), Person(id=8, name=而为人发), Person(id=10, name=都发), Person(id=3, name=都发), Person(id=4, name=过的)]

sorted:排序

代码语言:less
复制
    public static void main(String[] args) {
        List<Person> list = new ArrayList<>();
        list.add(new Person().setName("都覅说").setId(1));
        list.add(new Person().setName("认为我").setId(7));
        list.add(new Person().setName("而为人发").setId(8));
        list.add(new Person().setName("都发").setId(10));
        list.add(new Person().setName("都发").setId(10));
        list.add(new Person().setName("都发").setId(3));
        list.add(new Person().setName("过的").setId(4));
        list.add(new Person().setName("过的").setId(4));

//        根据 ID 降序排列
        List<Person> collect = list.stream().sorted(Comparator.comparing(Person::getId).reversed()).collect(Collectors.toList());
        System.out.println(collect);

    }


     public static void main(String[] args) {
            List<Person> list = new ArrayList<>();
            list.add(new Person().setName("而为人发").setId(8).setPerson(new Person().setId(21)));
            list.add(new Person().setName("都发").setId(10).setPerson(new Person().setId(120)));

    //        根据 person 里面的 person 的 ID 升序排列
            List<Person> collect = list.stream().sorted(Comparator.comparing(Person::getPerson, Comparator.comparingInt(Person::getId))).collect(Collectors.toList());
            System.out.println(collect);

        }

        public static void main(String[] args) {
                List<Person> list = new ArrayList<>();
                list.add(new Person().setName("都覅说").setId(null));
                list.add(new Person().setName("认为我").setId(7));
                list.add(new Person().setName("都发").setId(null));
                list.add(new Person().setName("都发").setId(3));
                list.add(null);
                list.add(new Person().setName("过的").setId(4));

        //        根据 person 的 ID 升序排列,如果 person 对象是 null 或者 getId 是 null 则放置在前面排列
                List<Person> collect = list
                        .stream()
                        .sorted(Comparator.nullsFirst(
                                Comparator.comparing(Person::getId,Comparator.nullsFirst(Integer::compareTo))
                        ))
                        .collect(Collectors.toList());
                System.out.println(collect);

            }

输出:[null, Person(id=null, name=都覅说, person=null), Person(id=null, name=都发, person=null), Person(id=3, name=都发, person=null), Person(id=4, name=过的, person=null), Person(id=7, name=认为我, person=null)]



public static void main(String[] args) {
        List<Person> list = new ArrayList<>();
        list.add(new Person().setName("都覅说").setId(32).setAge(3));
        list.add(new Person().setName("认为我").setId(7).setAge(32));
        list.add(new Person().setName("都发").setId(3).setAge(24));
        list.add(new Person().setName("果然舒服").setId(3).setAge(33));
        list.add(new Person().setName("过的").setId(4).setAge(323));

//        先按照 id 升序排列,如果 ID 相同再按照 age 升序排列
        List<Person> collect = list
                .stream()
                .sorted(Comparator.comparing(Person::getId).thenComparing(Person::getAge))
                .collect(Collectors.toList());
        System.out.println(collect);

    }

peek:中间流操作,和 map 功能有点像,只不过没有替换操作,作用是用来调试中间状态的值。

代码语言:c#
复制
 List<String> arr = new ArrayList<>();
        arr.add("fgdf");
        arr.add("45rtfsd");
        arr.add("534werf");
        arr.add("fsdefg");
        arr.add("terttre");

        List<String> collect = arr.stream().peek(p -> p = "2").collect(Collectors.toList());
        System.out.println(collect);

        输出:[fgdf, 45rtfsd, 534werf, fsdefg, terttre]


        List<String> arr = new ArrayList<>();
                arr.add("fgdf");
                arr.add("45rtfsd");
                arr.add("534werf");
                arr.add("fsdefg");
                arr.add("terttre");

        // 一定要有终止操作,不然不会有输出
                arr.stream()
                        .peek(System.out::println)
                        .collect(Collectors.toList());

limit:保留前 n 条数据。

skip:跳过 n 条数据

forEach:遍历,可能不是按照集合的顺序遍历

forEachOrdered:按照顺序遍历

reduce:数据计算

代码语言:less
复制
public static void main(String[] args) {
        List<Person> list = new ArrayList<>();
        list.add(new Person().setName("都覅说").setId(32).setAge(3));
        list.add(new Person().setName("认为我").setId(7).setAge(32));
        list.add(new Person().setName("都发").setId(3).setAge(24));
        list.add(new Person().setName("果然舒服").setId(3).setAge(33));
        list.add(new Person().setName("过的").setId(4).setAge(323));

        Integer num = list.stream().map(Person::getAge).reduce(Integer::sum).orElse(0);

    }

collect:将流转换成对象类型

代码语言:scss
复制
public static void main(String[] args) {
// 最常用的用法
        List<Person> s = new ArrayList<>();
        s.add(new Person().setId(1).setName("jfgkj"));
        List<String> collect = s.stream().map(Person::getName).collect(Collectors.toList());
    }

分组 
    public static void main(String[] args) {
        List<Person> s = new ArrayList<>();
        s.add(new Person().setId(1).setName("jfgkj"));
        s.add(new Person().setId(2).setName("fdkgjhd"));
        s.add(new Person().setId(3).setName("fdkgjhd"));
//        groupingBy 里面填的就是 key 值,每操作一条数据,只要他们符合 key 的规则,就会放在一个集合里面,
//        比如下面,key 是 name,将 name 放在一个 map 里面,如果下一个 name 存在于 map 中的 name 中,就放置在 List 里面。
//        这里面的规则可以自己随便定义
        Map<String, List<Person>> collect = s.stream().collect(Collectors.groupingBy(Person::getName));
        System.out.println(collect);

    }

输出 {fdkgjhd=[TestComponent.Person(id=2, name=fdkgjhd), TestComponent.Person(id=3, name=fdkgjhd)], jfgkj=[TestComponent.Person(id=1, name=jfgkj)]}

min:最小值

max:最大值

count:统计数量

anyMatch:是否有匹配条件语句的数据

allMatch:数据是否全部匹配条件语句

noneMatch:数据是否全部不匹配

1.5、Predicate 与 Function

除了这些,JDK 中还预定义了很多 FunctionalInterface 类,这样我们就无需自己去重复定义一些类似的接口了。

Function

代码语言:typescript
复制
@FunctionalInterface
public interface Function<T, R> {

    /**
     * Applies this function to the given argument.
     *
     * @param t the function argument
     * @return the function result
     */
    R apply(T t);

    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }


    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }


    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

Function 可以接受任意的 Lambda 表达式,当然参数只能是一个的。

代码语言:text
复制
Function<Person, String> getName = Person::getName;

Function<T, R> 中 T 决定 参数类型,R 决定返回值类型。

Predicate

Predicate 相当于在 Function 的基础上限定了返回值的类型,常用于接收条件表达式。

代码语言:scss
复制
@FunctionalInterface
public interface Predicate<T> {

    boolean test(T t);


    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }


    default Predicate<T> negate() {
        return (t) -> !test(t);
    }


    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }


    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}
代码语言:text
复制
Predicate<Integer> s = t -> t > 1;

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、Java8 新特性 -- Lambda 表达式
    • 1.1、单方法接口使用 Lambda 表达式
      • 1.2、Lambda 中的方法引用运算符 '::' 用法
        • 1.3、Lambda 中的 stream() 做了哪些优化?
          • 1.4、stream api
            • 1.5、Predicate 与 Function
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档