Java中lambda表达式的使用(二)

简介: Java中lambda表达式的使用(二)

Java中lambda表达式的使用(一)+https://developer.aliyun.com/article/1413557

4.lambda表达式中的变量捕获

 lambda表达式可以看作对匿名内部类进行的语法上的精简,同时也可以进行变量的捕获

@FunctionalInterface
interface DemoTest {
    void func();
}

当使用被修改过的变量 -->依然报错

尽量使用被final修饰的变量

引用类变量

@FunctionalInterface
interface DemoTest {
    void func();
}
public class Demo10 {
    // 使用类变量  可以直接访问
    public static int a = 10;
    public static void main(String[] args) {
        // lambda表达式
        DemoTest demoTest = () -> {
            System.out.println(a);
        };
    }

对于类变量来说,在lambda表达式中可以直接引用,因为类变量是属于类的,是所有对象公用的,它本身就有"静态"的属性

五.在优先级队列中的使用

 优先级队列中往往涉及到比较,我们在实例化优先级队列的时候往往要传递一个比较器,规定比较的对象

// 使用匿名内部类实现Comparator接口
        PriorityQueue<Integer> priorityQueue = new PriorityQueue(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return  o2 - o1;
            }
        });

其实也能看出,Comparator方法应该是一个函数式接口,它属于"多个参数,有返回值"的类型(对应于上面的最后一种情况),此处就可以使用lambda表达式进行语法上的精简

// 使用lambda表达式实现优先级队列中的比较
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<>((o1,o2) ->{return o1-o2;});

Comparator的源码 -->多个参数,有返回值的接口

六.创建线程

创建线程的方式有很多种,可以采用匿名内部类,lambda表达式

1.匿名内部类创建线程

// 创建线程 ->使用匿名内部类
        Thread thread1 = new Thread() {
            @Override
            public void run() {
                System.out.println("hello thread");
            }
        };
        // 这种方式可以降低耦合性(推荐)
        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello thread2");
            }
        });

为什么可以使用匿名内部类创建一个线程呢?主要是因为Thread类实现了Runnable接口,这个接口是一个函数式接口,只有一个抽象方法run()

2.使用lambda表达式

 既然Thread可以通过匿名内部类方式创建线程,同时就可以使用lambda表达式来简化创建

// 方式1
        Thread thread1 = new Thread(() ->{
            System.out.println("hello thread1");
        });
        thread1.run();// 输出hello thread1
        //方式2  利用lambda表达式实例化一个runnable接口  降低耦合性
        Runnable runnable = () -> System.out.println("hello thread2");
        Thread thread2 = new Thread(runnable);
        thread2.run();// 输出hello thread2

七.lambda表达式在集合类中的使用(以后最常用的一种)

为了能够让Lambda和Java的集合类集更好的一起使用,集合当中,也新增了部分接口,以便与Lambda表达式对 接。

1.Collection接口

1.1forEach()

1.源码

forEach()在Iterable接口之下,源码如下:

default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }

对传入的集合的每个元素执行action操作,进一步观察

可以观察到。forEach()方法接受了一个Comsumer类型的参数action,接着会对每一个action执行对应的操作。Consumer是一个函数式接口,属于"一个参数但无返回值"的类型,内部有一个抽象方法accept用于接受参数并执行特定的操作

2.使用匿名内部类实现
List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("my");
        list.add("friends");
        list.add("!!!");
        list.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.print(s + " ");
            }
        });

3.使用lambda表达式
// lambda表达式
        list.forEach((s) -> System.out.print(s + " "));

1.2removeif()

 removeif()用于根据条件删除集合中的对应数据,如果有对应条件的数据,删除,并将标志位removed设置为true(注意:removeif不是只删除一个符合条件的数据,而是类似于removeAll一样的效果)

1.源码:
default boolean removeIf(Predicate<? super E> filter) {
        Objects.requireNonNull(filter);
        boolean removed = false;
        final Iterator<E> each = iterator();
        while (each.hasNext()) {
            if (filter.test(each.next())) {
                each.remove();
                removed = true;
            }
        }
        return removed;
    }
2.图解:

3.使用
List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("my");
        list.add("friends");
        list.add("!!!");
        // 1.先打印原数据
        list.forEach((s) -> System.out.print(s + " "));
        // 2.删除长度 <= 3的字符串
        boolean flg = list.removeIf(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.length() <= 3;
            }
        });
        System.out.println("");
        // 3.判断是否有删除操作
        System.out.println(flg);
        // 4.打印删除之后的数据
        list.forEach((s) -> System.out.print(s + " "));

打印结果:

2.List接口

2.1 sort

1.源码:
default void sort(Comparator<? super E> c) {
        Object[] a = this.toArray();
        Arrays.sort(a, (Comparator) c);
        ListIterator<E> i = this.listIterator();
        for (Object e : a) {
            i.next();
            i.set((E) e);
        }
    }
2.图解:

3.使用:
List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("my");
        list.add("friends");
        list.add("!!!");
        // 使用匿名内部类
        list.sort(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.compareTo(o2);// 从小到大排序
            }
        });
        // 使用lambda表达式
        list.sort((o1,o2) -> {
            return o1.compareTo(o2);
        });
        list.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.print(s + " ");
            }
        });

打印结果:

2.2 reolaceAll

1.源码:
default void replaceAll(UnaryOperator<E> operator) {
        Objects.requireNonNull(operator);
        final ListIterator<E> li = this.listIterator();
        while (li.hasNext()) {
            li.set(operator.apply(li.next()));
        }
    }
2.图解:

3.使用:
List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        // 打印原数据
        System.out.println(list.toString());
        // 使用匿名内部类
        list.replaceAll(new UnaryOperator<Integer>() {
            @Override
            public Integer apply(Integer integer) {
                return integer*2;// 将所有的值都设置为原来的两倍
            }
        });
        // 使用lambda表达式
        list.replaceAll((x) ->{return x*2;});
        // 打印修改之后的数据
        System.out.println(list.toString());

打印数据:

3.Map接口

3.1 forEach

1.源码:
default void forEach(BiConsumer<? super K, ? super V> action) {
        Objects.requireNonNull(action);
        for (Map.Entry<K, V> entry : entrySet()) {
            K k;
            V v;
            try {
                k = entry.getKey();
                v = entry.getValue();
            } catch(IllegalStateException ise) {
                // this usually means the entry is no longer in the map.
                throw new ConcurrentModificationException(ise);
            }
            action.accept(k, v);
        }
    }
2.图解:

3.使用:
Map<String,Integer> map = new HashMap<>();
        map.put("zs",1);
        map.put("ls",2);
        map.put("ww",3);
        // 使用匿名内部类
        map.forEach(new BiConsumer<String, Integer>() {
            @Override
            public void accept(String s, Integer integer) {
                System.out.println("key:" + s + " val:" + integer);
            }
        });
        System.out.println("==============");
        // 使用lambda表达式
        map.forEach((key,val) ->{
            System.out.println("key:" + key + " val:" + val);
        });

打印结果:


目录
相关文章
|
4天前
|
Java API
Java 8新特性之Lambda表达式与Stream API
【5月更文挑战第17天】本文将介绍Java 8中的两个重要特性:Lambda表达式和Stream API。Lambda表达式是一种新的编程语法,它允许我们将函数作为参数传递给其他方法,从而使代码更加简洁。Stream API是一种用于处理集合的新工具,它提供了一种高效且易于使用的方式来处理数据。通过结合使用这两个特性,我们可以编写出更加简洁、高效的Java代码。
13 0
|
6天前
|
Java 开发者
Java一分钟之-Lambda表达式与函数式接口
【5月更文挑战第12天】Java 8引入的Lambda表达式简化了函数式编程,与函数式接口结合,实现了代码高效编写。本文介绍了Lambda的基本语法,如参数列表、箭头符号和函数体,并展示了如何使用Lambda实现`Runnable`接口。函数式接口仅有一个抽象方法,可与Lambda搭配使用。`@FunctionalInterface`注解用于确保接口具有单一抽象方法。文章还讨论了常见的问题和易错点,如非函数式接口、类型冲突以及Lambda表达式的局部变量可见性,并提供了避免这些问题的策略。通过理解Lambda和函数式接口,开发者能提高代码可读性和效率。
44 4
|
1天前
|
Java API
Java 8新特性之Lambda表达式
【5月更文挑战第20天】本文将介绍Java 8中的一个重要特性——Lambda表达式。Lambda表达式是Java 8引入的一种新的编程语法,它允许我们将函数作为参数传递给方法,从而实现更加简洁、灵活的代码。本文将从Lambda表达式的基本概念、语法、使用方法以及优缺点等方面进行详细介绍,帮助读者更好地理解和应用Lambda表达式。
|
1天前
|
Java 程序员 API
Java 8 Lambda 表达式和Stream API:概念、优势和实战应用
【5月更文挑战第20天】在Java 8中,Lambda 表达式和Stream API是两个非常强大的特性,它们显著改变了Java程序员处理数据和编写代码的方式。本篇技术文章将深入探讨这些特性的概念、优点,并提供实战示例,帮助理解如何有效地利用这些工具来编写更简洁、更高效的代码。
18 6
|
6天前
|
Java API
Java 8新特性之Lambda表达式与Stream API实践指南
【5月更文挑战第15天】 随着Java语言的不断发展,Java 8作为一个重要的版本,引入了许多令人兴奋的新特性。其中,Lambda表达式和Stream API是Java 8最受关注的两个特性。本文将深入探讨Lambda表达式的基本概念、语法和使用场景,以及如何结合Stream API实现更加简洁、高效的代码编写。通过实例演示,帮助读者快速掌握这两个新特性,提高Java编程能力。
|
6天前
|
Java
Java正则表达式去掉非汉字字符
【5月更文挑战第11天】Java正则表达式去掉非汉字字符
18 3
|
6天前
|
Java API 开发者
Java中Lambda表达式的深入理解与应用
【5月更文挑战第12天】在Java 8之后,Lambda表达式已经成为了Java开发者必备的技能之一。Lambda表达式以其简洁、灵活的特点,大大提高了编程的效率。本文将深入探讨Lambda表达式的基本概念,语法规则,以及在实际开发中的应用,帮助读者更好地理解和使用Lambda表达式。
|
6天前
|
Java 程序员 API
Java 8新特性之Lambda表达式与Stream API的深度解析
【5月更文挑战第12天】本文将深入探讨Java 8中的两个重要新特性:Lambda表达式和Stream API。我们将从基本概念入手,逐步深入到实际应用场景,帮助读者更好地理解和掌握这两个新特性,提高Java编程效率。
44 2
|
Java
QuartZ Cron表达式在java定时框架中的应用
CronTrigger CronTriggers往往比SimpleTrigger更有用,如果您需要基于日历的概念,而非SimpleTrigger完全指定的时间间隔,复发的发射工作的时间表。 CronTrigger,你可以指定触发的时间表如“每星期五中午”,或“每个工作日9:30时”,甚至“每5分钟一班9:00和10:00逢星期一上午,星期三星期五“。
993 0
|
1天前
|
安全 Java 程序员
深入理解Java并发编程:线程安全与性能优化
【5月更文挑战第20天】本文将深入探讨Java并发编程的核心概念,包括线程安全和性能优化。我们将详细解析synchronized关键字、ReentrantLock类以及java.util.concurrent包中的高级工具类,如Semaphore、CountDownLatch和CyclicBarrier等。通过实例演示如何使用这些工具来提高多线程程序的性能和可靠性。