文章目录
一、概述
优点
- 大数据量下处理集合效率高,自动创建并发流,提高多线程性能
- 代码可读性高
- 消灭嵌套
编程思想
面向对象思想需要关注对象做什么,函数式编程主要关注对数据的处理
二、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 注意事项
- 惰性求值,没有终结操作,中间操作是不能执行的。
- 流是一次性的,一旦这个流对象经过终结操作后,这个流不可再被使用。
- 不会影响原数据,上面已给示例。