Java函数式编程Lambda和Stream流

一、概述

优点
  • 大数据量下处理集合效率高,自动创建并发流,提高多线程性能
  • 代码可读性高
  • 消灭嵌套
编程思想

​ 面向对象思想需要关注对象做什么,函数式编程主要关注对数据的处理

二、Lambda表达式

2.1 概述

Lambda是JDK8中的一个语法糖,可以对某些匿名内部类的写法进行简化。它是函数式编程的一个重要体现,让我们可以不用关注是什么对象,而是更关注对数据进行了什么操作。

函数式接口:指的是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口,这样的接口可以隐式转换为 Lambda 表达式

2.2 核心原则

可推导可省略

2.3 基本公式

(参数列表)->{代码}

例一

new Thread(new Runnable(){
		@override
		public void run() {
				System.out.println("balabala");
		}
}).start();

改为Lambda表达式

new Thread(()->{
	System.out.println("balabala");
}).start();

例二

public static <R> R typeConver(Function<String, R> function) {
	String str = "123";
	R result = function.apply(str);
	return result;
}

改为Lambda表达式第一步

Integer result = typeConver(new Function<String, Interger>(){
	@Override
	public Interger apply(String s){
		return Integer.valueOf(s);
	}
});
System.out.println(result);

第二步

Integer result = typeConver(s -> Integer.valueOf(s));
System.out.println(result);

2.4 省略规则

  • 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值
  • 可选参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号
  • 可选大括号:如果主体包含了一个语句,就不需要使用大括号
  • 可选返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指明表达式返回了一个数值

2.5 变量作用域

Lambda表达式可以引用类成员和局部变量,但是会将这些变量隐式的转化成final

String separator = ","; 
Arrays.asList( "a", "b", "c" ).forEach( 
    ( String e ) -> System.out.print( e + separator ) ); 
final String separator = ","; 
Arrays.asList( "a", "b", "c" ).forEach( 
    ( String e ) -> System.out.print( e + separator ) ); 

两者等价。

同时,Lambda 表达式的局部变量可以不用声明为final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义)

int num = 1; 
Arrays.asList(1,2,3,4).forEach(e -> System.out.println(num + e)); 
num =2; 
//报错信息:Local variable num defined in an enclosing scope must be final or effectively final 
int num = 1; 
Arrays.asList(1,2,3,4).forEach(num -> System.out.println(num)); 
//报错信息:Variable 'num' is already defined in the scope 

三、Stream流

3.1 概述

Stream使用的是函数式编程模式,可以被用来对集合或数组进行链状流式的操作。

3.2 示例

@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
public class Author {
    private Long id;
    private String name;
    private String intro;
    private Integer age;
    private List<Book> books;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
public class Book {
    private Long id;
    private String name;
    private String category;
    private Integer score;
    private String intro;
}
public static List<Author> getAuthors() {

    List<Book> books1 = new LinkedList<>();
    List<Book> books2 = new LinkedList<>();
    List<Book> books3 = new LinkedList<>();

    books1.add(new Book(11L,"book11","category11",18, "intro1"));
    books1.add(new Book(12L,"book12","category12",17, "intro12"));

    books2.add(new Book(21L,"book21","category21",27, "intro2"));
    books2.add(new Book(22L,"book22","category22",28, "intro21"));
    books2.add(new Book(23L,"book23","category23",29, "intro23"));

    books3.add(new Book(31L,"book31","category31",39, "intro31"));
    books3.add(new Book(32L,"book32","category32",32, "intro32"));
    books3.add(new Book(33L,"book33","category33",33, "intro33"));
    books3.add(new Book(34L,"book34","category34",34, "intro34"));

    Author author1 = new Author(1L,"author1","intro1",11, books1);
    Author author2 = new Author(2L,"author2","intro2",22, books2);
    Author author3 = new Author(3L,"author3","intro3",33, books3);

    List<Author> authors = new LinkedList<>();
    authors.add(author1);
    authors.add(author2);
    authors.add(author3);

    return authors;
}
    public static void main(String[] args) {
        List<Author> authors = getAuthors();
        Stream<Author> stream = authors.stream();
        stream
                .distinct()
                .filter(author -> author.getAge()<=22)
                .forEach(System.out::println);

        System.out.println("ccccc"+authors);
        stream.forEach(System.out::println);
    }
    

请添加图片描述

NOTE:

  • Stream 操作不改变原有数据,author的值没有变化
  • 终结操作后,stream流不可再用,因为已经被操作或者关闭

学习过程中一个好用的工具

请添加图片描述

可以查看stream每一步对数据的处理。

3.3 常用操作

请添加图片描述

3.3.1 创建流

单列集合

对象.Stream()即可

List<Author> authors = getAuthors();
Stream<Author> stream = authors.stream();

数组

Arrays.stream(arr)或者是用Stream.of来创建

Integer[] arr = [1,2,3,4,5];
Stream<Interger> stream = Arrays.stream(arr);
Stream<Interger> stream2 = Stream.of(arr);

双列集合\

先转化为单列形式,再转化

Map<String, Integer> map = new HashMap<>();
map.put("age1",11);
map.put("age2",22);
map.put("age3",33);
Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
Stream<Map.Entry<String, Integer>> stream = entrySet.stream();
3.3.2 中间操作
  • distinct
  • filter
  • map
  • sorted
  • limit
  • skip
  • flatMap
3.3.3 终结操作
  • forEach
  • count
  • min&max
  • collect
  • anyMatch
  • allMatch
  • findAny
  • findFirst
  • reduce

3.4 注意事项

  • 惰性求值,没有终结操作,中间操作是不能执行的。
  • 流是一次性的,一旦这个流对象经过终结操作后,这个流不可再被使用。
  • 不会影响原数据,上面已给示例。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值