lamda
Lambda表达式(闭包),Lambda允许把函数作为一个方法的参数(函数作为参数传递方法中),或者把代码看成数据。Lamda表达式用于简化Java中接口式的匿名内部类。被称为函数式接口的概念。函数式接口就是一个具有 一个方法 的普通接口。像这样的接口可以被隐式的转换成Lambda表达式。
格式
(parameters) -> expression
或
(parameters) ->{ statements; }
- 例子
public class Java8Tester {
public static void main(String args[]){
Java8Tester tester = new Java8Tester();
// 类型声明
MathOperation addition = (int a, int b) -> a + b;
// 不用类型声明
MathOperation subtraction = (a, b) -> a - b;
// 大括号中的返回语句
MathOperation multiplication = (int a, int b) -> { return a * b; };
// 没有大括号及返回语句
MathOperation division = (int a, int b) -> a / b;
System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));
System.out.println("10 / 5 = " + tester.operate(10, 5, division));
// 不用括号
GreetingService greetService1 = message ->
System.out.println("Hello " + message);
// 用括号
GreetingService greetService2 = (message) ->
System.out.println("Hello " + message);
greetService1.sayMessage("Runoob");
greetService2.sayMessage("Google");
}
interface MathOperation {
int operation(int a, int b);
}
interface GreetingService {
void sayMessage(String message);
}
private int operate(int a, int b, MathOperation mathOperation){
return mathOperation.operation(a, b);
}
}
- 对字符串数组按字符串长度排序
package org.xxxx.demo01;
import java.util.Arrays;
import java.util.Comparator;
public class Demo01 {
public static void main(String[] args) {
// 定义字符串数组
String[] strArr = { "abc", "cd", "abce", "a" };
// 传统方法
// 匿名内部类
Arrays.sort(strArr, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return Integer.compare(s2.length(), s1.length());
}
});
// 输出排序结果
for (String s : strArr) {
System.out.println(s);
}
System.out.println("---------------------");
// Lambda表达式
Arrays.sort(strArr, (s1, s2) -> Integer.compare(s2.length(), s1.length()));
// 输出
for (String s : strArr) {
System.out.println(s);
}
}
}
- 用Lambda实现多线程
package org.xxxx.demo01;
public class Demo01 {
public static void main(String[] args) {
// Lambda表达式
new Thread(() -> System.out.println(1 + "hello world")).start();
System.out.println("----------------");
// 方法体
new Thread(() -> {
for (int i = 0; i < 10; i++) {
System.out.println(2 + "hello world");
}
}).start();
}
}
函数式接口
- @FunctionalInterface:该注解是定义一个lambda表达式的基础, 即是否是函数式接口可以标注也可以不标注。
-
函数式接口分类
- 系统与定义函数接口(Comparator, Runnable)
- 用户自定义函数接口(注解必须有,表达式是直接通过参数列表来实现的,只能有一个有效方法)
@FunctionalInterface
public interface MyInterface {
String info(String tip);
}
公共定义的函数式接口
-
Function<T, R>
- 有输入参数,有返回值
- 是对接收一个T类型参数,返回R类型的结果的方法的抽象
- 通过调用apply方法执行内容
- 例子:给定一个字符串,返回字符串长度
package org.xxxx.demo01;
import java.util.function.Function;
public class Demo01 {
public static void main(String[] args) {
// 定义字符串
String str = "helloworld";
// 调用方法
// 在调用的时候写方法体,方法比较灵活
int length = testFun(str, (s) -> s.length());
System.out.println(length);
}
// 方法
/**
*
* @param str 输入参数
* @param fun 表达式 String 为输入类型,Integer为输出类型
* @return 返回字符串长度
*/
public static int testFun(String str, Function<String, Integer> fun) {
// 执行
Integer length = fun.apply(str);
return length;
}
}
- 消费型接口:Consumer<T>
- 有输入参数,没返回值
- Consumer 使用accept对参数执行行为
- 例子:输出字符串
package org.xxxx.demo01;
import java.util.function.Consumer;
public class Demo01 {
public static void main(String[] args) {
// 创建字符串
String str = "hello world";
// 调用
testCon(str, (s) -> System.out.println(s));
}
/**
*
* @param str 传入参数
* @param con
*/
public static void testCon(String str, Consumer<String> con) {
// 执行
con.accept(str);
}
- 供给型接口:Supplier<T>
- 无传入参数,有返回值
- 该接口对应的方法类型不接受参数,但是提供一个返回值
- 使用get()方法获得这个返回值
package org.xxxx.demo01;
import java.util.function.Supplier;
public class Demo01 {
public static void main(String[] args) {
// 创建字符串
String str = "hello world";
// 调用
String sup = testSup(() -> str);
System.out.println(sup);
}
/**
*
* @param sup
* @return
*/
public static String testSup(Supplier<String> sup) {
// 执行
String s = sup.get();
return s;
}
- 断言型接口:Predicate<T>
- 有传入参数,有返回值Boolean
- 该接口对应的方法为接收一个参数,返回一个Boolean类型值
- 多用于判断与过滤,使用test()方法执行这段行为
- 需求:输入字符串,判断长度是否大于0
package org.xxxx.demo01;
import java.util.function.Predicate;
public class Demo01 {
public static void main(String[] args) {
// 创建字符串
String str = "hello world";
// 调用
boolean flag = testPre(str, (s) -> s.length() > 0);
System.out.println(flag);
}
/**
*
* @param str
* @param pre
* @return
*/
public static boolean testPre(String str, Predicate<String> pre) {
// 执行
boolean flag = pre.test(str);
return flag;
}
}
方法引用
某些lambda表达式里面仅仅是调用了一个已存在的方法,在这种情况下
直接通过方法名称引用方法的形式可读性更高一些,这种形式就是方法引用
方法引用是一种更简洁易懂的lambda 表达式替换
- 方法引用中::后只是方法名,不能加();
import java.util.ArrayList;
import java.util.List;
public class Demo01 {
public static void main(String[] args) {
// 创建集合
List<String> list = new ArrayList<>();
// 添加元素
list.add("e");
list.add("c");
list.add("a");
list.add("d");
list.add("b");
// 排序
list.sort((s1, s2) -> s1.compareTo(s2));
// 遍历
list.forEach((s) -> System.out.println(s));
list.forEach(System.out::println);
}
}
Stream
是用函数式编程方式在集合类上进行复杂操作的工具,更像一个高级版本的 Iterator
而和迭代器又不同的是,Stream 可以并行化操作
在Java1.8 中, 集合接口提供了两个方法来生成流:stream()串行流和parallelStream()并行流,即Stream的操作可以分为串行stream()和并行parallelStream()。举个例子来说:
List<String> strings = Arrays.asList("who","what","when","why","which");
List<String> filterd = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
- forEach 循环
List<String> stringList = Arrays.asList("who","what","when","why","which");
// 方式一:JDK1.8之前的循环方式
for(String string:stringList){
System.out.println(string);
}
// 方式二:使用Stream的forEach方法
stringList.stream().forEach(e -> System.out.println(e));
// 方式三:方式二的简化形式,因为方法引用也属于函数式接口,因此Lambda表达式可以用方法引用来代替
stringList.stream().forEach(System.out::println);
-
filter 过滤
- filter方法用于通过设置条件来过滤出满足条件的元素。举个例子来说,下面就是用于输出字符串列表中的空字符串的个数:
List<String> stringList = Arrays.asList("","welcome","","to","visit","my","","website");
long count = stringList.stream().filter(e -> e.isEmpty()).count();
System.out.println(count);
-
map 映射
- 是一种函数,用于映射每个元素执行某些操作得到对应的结果。举个例子来说,下面就是使用map来输出元素对应的平方数:
List<Integer> integerList = Arrays.asList(2,3,4,5,6);
List<Integer> integers = integerList.stream().map(i->i*i).collect(Collectors.toList());
integerList.stream().forEach(System.out::println);
-
flatMap 映射
- flatMap映射和map映射类似,不过它的每个元素转换得到的是Stream对象,会把子Stream中的元素压缩到父集合中,说白了就是将几个小的list合并成一个大的list。
List<String> fruitList = Arrays.asList("banana","orange","watermelon");
List<String> vegetableList = Arrays.asList("kale","leek","carrot");
List<String> transportList = Arrays.asList("car","bike","train");
//将多个元素合成一个复合类型集合,元素类型List<String>
List<List<String>> lists = Stream.of(fruitList,vegetableList,transportList).collect(Collectors.toList());
//将多个元素合成一个单一类型集合,元素类型String
List<String> flatMap = Stream.of(fruitList,vegetableList,transportList)
.flatMap(list ->list.stream())
.collect(Collectors.toList());
System.out.println(flatMap);
-
sorted 排序
- sorted方法用于对流进行排序。举个例子来说,下面的代码就是用于对字符串按照给定的规则进行排序并输出:
List<String> stringList = Arrays.asList("c","a","f","d","b","e");
stringList.stream().sorted((s1,s2) -> s1.compareTo(s2)).forEach(System.out::println);
-
distinct
- 缺点就是不能设置去重的条件
List<String> stringList = Arrays.asList("do","what","you","want","to","do","and","do","it");
stringList.stream().distinct().forEach(System.out::println);
-
of 生成Stream对象
- of方法用于生成Stream对象,注意它是Stream对象的方法。举个例子来说:
Stream<Object> objectStream= Stream.of("do","what","you","want","to","do","and","do","it");
objectStream.forEach(System.out::println);
-
count 计算总数
- count方法用于计算流中元素的总数。举个例子来说:
Stream<Object> objectStream = Stream.of("do","what","you","want","to","do","and","do","it");
long count = objectStream.count();
System.out.println(count);
-
min和max 最小/最大
- collect方法的使用较为复杂,这里仅仅介绍一些常用的方法即可。collect方法可以将Stream转为Collection对象或者是Object类型的数组等,举个例子来说:
List<String> stringList= Arrays.asList("do","what","you","want","to","do","and","do","it");
//Stream转Collection
stringList.stream().collect(Collectors.toList());
//Stream转Object[]数组
Object[] objects = stringList.stream().toArray();
-
collect
- collect方法的使用较为复杂,这里仅仅介绍一些常用的方法即可。collect方法可以将Stream转为Collection对象或者是Object类型的数组等,举个例子来说:
List<String> stringList= Arrays.asList("do","what","you","want","to","do","and","do","it");
//Stream转Collection
stringList.stream().collect(Collectors.toList());
//Stream转Object[]数组
Object[] objects = stringList.stream().toArray();