美文网首页
java1.8lambda表达式总结

java1.8lambda表达式总结

作者: 飞奔吧牛牛 | 来源:发表于2020-04-19 00:34 被阅读0次

一、基础

基本语法

[接口声明] = (参数)-> {代码。。。};

具体使用

1.表达式必须和接口绑定使用,符合接口的方法声明。
如某个接口:

public interface A {
    String get(int i);
}

声明接口时:

A a  = new A() {
    @Override
    public String get(int i) {
        return "hello " + i;
    }
};

使用lambda

A la = (int i) -> {
    return "lambda " + i;
};

但如果一个接口有多个方法,则无法使用lambda表达式。如

public interface B {
    String get(int i);
    void set();
}

default和static方法除外

public interface A {
    String get(int i);

    default int fun1() {
        return 0;
    }

    static String fun2() {
        return "A";
    }
}

2.参数:可以是0到n个参数,具体根据绑定的接口而定,且参数类型可以不写。

A la = (i) -> {
    return "lambda " + i;
};

3.返回值:如果代码块只有一行,可以没有大括号。
没有大括号时,不能用return关键字。
如果添加了大括号,或者有多行代码,必须通过关键字return返回。

//可以这样
A la2 = (i) -> "lambda " + i;
//也可以这样
A la2 = (i) -> {
    return "lambda " + i;
};
//而不能这样
A la2 = (i) -> return "lambda " + i;

java.util.function提供了大量的函数式接口供我们使用

Predicate,传入T类型,返回boolean
Consumer,传入T类型,消耗掉,返回void
function,传入T类型,返回E类型
Supplier,传入返回T类型
UnaryOperator,传入T,返回T
BinaryOperator,传入两个T类型,返回T类型
emmm,记不住~~~

如Predicate
 Predicate<String> pre1 = (name) -> "admin".equals(name);
 System.out.println(pre1.test("admin") ? "管理员" : "普通用户");

 打印结果:
 管理员

lambda对this关键字的优化

使用lambda表达式时,在表达式内部this代表的是该lambda表达式所属的对象。
正常情况下,在接口内部使用this,该this指的是这个接口,而不是声明该接口的对象(或者说该接口所属的对象)

public class Test{
    String s1 = "全局变量";
    public void testLambda() {
        String s2 = "局部变量";
        new Thread(new Runnable() {
            @Override
            public void run() {
                String s3 = "内部变量";
                System.out.println(this.s1);//报错!!!
                System.out.println(s2);
                System.out.println(s3);
            }
        }).start();
    }

    public static void main(String[] args) {
        new App().testLambda();
    }
}
public class Test {
    String s1 = "全局变量";
    public void testLambda() {
        String s2 = "局部变量";
        new Thread(() -> {
            String s3 = "内部变量";
            System.out.println(this.s1);//不报错!!!
            System.out.println(s2);
            System.out.println(s3);

        }).start();
    }

    public static void main(String[] args) {
        new App().testLambda();
    }
}

打印结果:
全局变量
局部变量
内部变量

方法重载对lambda表达式的影响

当遇到重载方法时,如果方法中传入的接口中的方法参数类型和返回值一样,则无法使用lambda。如

public class Test {

    public static void main(String[] args) {
        test(() ->{//报错!!!
            System.out.println("I1");
            return 1;
        });
    }
    //重载方法
    private static void test(A a) {
        a.printString();
    }
    private static void test(B b) {
        b.printInt();
    }

}

interface A {
    void printString();
}
interface B {
    void printInt();
}

二、lambda在集合中的应用

方法引用

1. 静态方法、实例方法引用

以List.sort() 为例
实体类:

class Person {
    private String name;
    private int age;

    public static int compareByAge(Person p1, Person p2) {
        return p1.age - p2.age;
    }

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    setter and getter...

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
数据源
        List<Person> persons = new ArrayList<>();
        persons.add(new Person("Tom", 28));
        persons.add(new Person("Jack", 30));
        persons.add(new Person("Dav", 20));
使用内部类方式
        //使用内部类方式
        persons.sort(new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                int i = o1.getAge() - o2.getAge();
                return i;
            }
        });
使用lambda方式
        //使用lambda方式
        persons.sort((a, b) -> a.getAge() - b.getAge());
        persons.sort(Comparator.comparingInt(Person::getAge));
先在任意一个类中定义参数为(Person p1, Person p2),返回类型为 int 的静态方法和普通方法
class PersonUtil {
    public int compareByAge(Person p1, Person p2) {
        return p1.getAge() - p2.getAge();
    }

    public static int compare(Person p1, Person p2) {
        return p1.getAge() - p2.getAge();
    }
}
静态方法引用,类名::静态方法名
//静态方法的引用,会默认将(Person, Person)参数传递给PersonUtil的compare方法
persons.sort(PersonUtil::compare);
实例方法引用,对象::普通方法名
//实例方法的引用
PersonUtil pu = new PersonUtil();
persons.sort(pu::compareByAge);
2. 构造方法引用

除了静态方法引用和实例方法引用还有构造方法引用。

interface IPerson {
    //通过指定类型的构造方法初始化对象数据,
    //即:Person类中必须有(String name, int age)类型参数的构造方法。
    Person initPerson(String name, int age);
}

//构造方法的引用
IPerson ip = Person::new;
Person wang = ip.initPerson("wang", 25);

Stream

Stream解耦了对数据的各种操作,比起传统的手动操作数据更方便。
例如:

List<String> list = new ArrayList<>();
list.add("abc");
list.add("adcd");
list.add("adcde");
list.add("adcdef");
//传统方式获取list中元素长度>=4的数据
List<String> result = new ArrayList<>();
for (String s : list) {
    if (s.length() >= 4) {
        result.add(s);
    }
}
System.out.println(result);
//使用Stream方式获取list中元素长度>=4的数据
List<String> collect = list.stream().filter(s -> s.length() >= 4).collect(Collectors.toList());
System.out.println(collect);

打印结果:
[adcd, adcde, adcdef]
[adcd, adcde, adcdef]
Stream概述
/**
 * 1. 获取Stream对象
 *      1.  从集合或数组中获取[**]
 *          Collection.stream(),如list.stream()
 *          Collection.parallelStream()
 *          Arrays.stream()
 *      2.  BufferReader
 *          BufferReader.lines()
 *      3.  静态方法
 *          java.util.stream.IntStream.range()..
 *          java.nio.file.Files.walk()..
 *      4.  自定义构建
 *          java.util.Spliterator
 *      5.  更多方式。。
 *          Random.ints()
 *          Pattern.splitAsStream()..
 * 2. 中间操作api
 *      操作结果是一个Stream,中间操作可以有一个或多个连续的中间操作,需要注意的是,中间操作只记录操作方式,
 *      不做具体执行,直到借宿操作发生时,才做数据的最终执行。
 *      中间操作:就是业务逻辑处理。
 *      中间操作过程:
 *              无状态:数据处理是,不搜前置中间操作的影响。
 *                      map/filter/peek/parallel/sequential/unordered
 *              有状态:数据处理时,受前置中间操作的影响。
 *                      distinct/sorted/limit/skip
 * 3. 终结操作 | 结束操作{Terminal}
 * 需要注意:一个Stream对象,只能由一个Terminal操作,这个操作一旦发生,就会真实的处理数据。
 * 终结操作:
 *          非短路操作:当前的Stream对象必须处理完集合中所有数据才能得到结果。
 *                      forEach/forEachOrdered/toArray/reduce/collect/min/max/count/iterator
 *          短路操作:当前的Stream对象在处理过程中,一旦满足某个条件,就可以得到结果。
 *                      anyMatch/allMatch/noneMatch/findFirst/findAnd等
 */

对比上面例子

list.stream()  //获取Stream
.filter(s -> s.length() >= 4)  //中间操作,返回一个Stream对象
.collect(Collectors.toList());  //终结操作

Stream的获取

//多个数据
Stream<String> stream1 = Stream.of("A", "B", "C");

//数组
String[] strArray = new String[]{"A", "B", "C"};
Stream<String> stream2 = Stream.of(strArray);

//列表
ArrayList<Object> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
Stream<Object> stream3= list.stream();

//集合
Set<String> set = new HashSet<>();
set.add("A");
set.add("B");
set.add("C");
Stream<String> stream4 = set.stream();

//map
HashMap<String, Integer> map = new HashMap<>();
map.put("A", 1);
map.put("B", 2);
map.put("C", 3);
Stream<Map.Entry<String, Integer>> stream5 = map.entrySet().stream();

Stream对象对于基本数据类型的封装

// int / long / double
IntStream.of(new int[] {10, 20, 30}).forEach(System.out::println);
IntStream.range(1,5).forEach(System.out::println);
IntStream.rangeClosed(1,5).forEach(System.out::println);

从Stream中获取指定的类型数据

Stream<String> stream1 = Stream.of("A", "B", "C");
//array
String[] arrayx = stream1.toArray(String[]::new);
//string
String stringx = stream1.collect(Collectors.joining());
//list
List<String> listx = stream1.collect(Collectors.toList());
//set
Set<String> setx = stream1.collect(Collectors.toSet());
//map
Map<String, String> mapx = stream1.collect(Collectors.toMap(x -> "key:" + x, y -> "val:" + y));

相关文章

  • java1.8lambda表达式总结

    一、基础 基本语法 [接口声明] = (参数)-> {代码。。。}; 具体使用 1.表达式必须和接口绑定使用,符合...

  • 表达式树

    表达式树中缀表达式转换为后缀表达式后缀表达式总结

  • 2020-03-28 正则表达式基础与高级

    史上最全正则表达式语法,文末附常用表达式! 正则表达式的回溯 总结:回溯越少效率越高

  • 正则表达式优化

    正则表达式优化——《精通正则表达式》总结 [TOC] 第4章:表达式的匹配原理 引擎 DFA (Determini...

  • vue(2) - 收藏集 - 掘金

    javascript 正则表达式总结 - 前端 - 掘金为什么要使用正则表达式 正则表达式通过由普通字符和特殊字符...

  • Java Web 基础知识目录

    Tomcat环境搭建sevelet编码问题Java Web 走过的坑servlet总结JSP总结EL表达式总结JS...

  • Java8的Lambda特性

    oracle官网教程 概述 背景 例子 使用Lambda表达式改进代码 总结 概述 Lambda表达式是Java8...

  • 真值函数判断--数学表达式

    这一章的数学表达式较多,或者说是集合语言相对丰富。我觉得可以直接把这个表达式和这章的总结贴出来,效果会更好。 总结...

  • jdk8 lambda表达式与stream流

    lambda表达式 首先创建两个java Bean 编写测试类 自己总结:lambda表达式的使用就是将对象(集合...

  • 常用正则表达式

    常用正则表达式 总结 正则表达式用于字符串处理、表单验证等场合,实用高效。现将一些常用的表达式收集于此,以备不时之...

网友评论

      本文标题:java1.8lambda表达式总结

      本文链接:https://www.haomeiwen.com/subject/tgzpyhtx.html