– lambda表达式是实现接口的一种方式
– 必须是接口,且接口中有且只有一个方法
– 格式:(参数) -> {主体}
– lambda表达式无需关注其他内容,只看被重写方法的参数列表和方法体即可
package com.haohao.learn;
import java.util.function.IntPredicate;
public class Hello {
public static void main(String[] args) {
//lambdao表达式格式
printNum((int value) -> {
return value % 2 == 0;
});
//常规匿名内部类格式
printNum(new IntPredicate() {
@Override
public boolean test(int value) {
return value % 2 == 0;
}
});
}
//IntPredicate是一个接口,有且只有一个test方法,符合lambda表达式要求
public static void printNum(IntPredicate predicate){
int[] arr = {1,2,3,4,5,6,7,8,9,10};
for (int a : arr) {
if (predicate.test(a)){
System.out.println(a);
}
}
}
}
jdk8的Stream使用的是函数式编程模式,可以用来对集合或者数组进行链状流式的操作,使得对数组或集合的操作更方便
public class Author {
public static void main(String[] args) {
ArrayList<String> strings = new ArrayList<>();
strings.add("艾瑞莉娅");
strings.add("瑞文");
strings.add("菲奥娜");
strings.add("丽桑卓");
strings.add("薇恩");
strings.add("薇恩");
//过滤
//遍历
strings.stream()//转换成Stream流
.distinct()//去重
.filter(s -> s.length() < 4)//过滤
.forEach(s -> System.out.println(s));//遍历
}
}
ArrayList<String> strings = new ArrayList<>();
Stream<String> stream = strings.stream();
– 数组:Arrays.stream(数组)/Stream.of(数组)
Integer[] ints = {1,2,3,4};
Stream<Integer> stream1 = Arrays.stream(ints);
Stream<Integer> stream2 = Stream.of(ints);
– 双列集合:
HashMap<String, Integer> map = new HashMap<>();
map.put("易",11);
map.put("赵信",15);
map.put("泰达米尔",25);
//Set> entries = map.entrySet();
//Stream> stream = entries.stream();
Stream<Map.Entry<String, Integer>> stream = map.entrySet().stream();
//前置
ArrayList<String> strings = new ArrayList<>();
Stream<String> stream = strings.stream();
strings.add("艾瑞莉娅");
strings.add("瑞文");
strings.add("菲奥娜");
strings.add("丽桑卓");
strings.add("薇恩");
strings.add("薇恩");
– filter:对流中的元素进行条件过滤,符合条件的才能继续留在流中
strings.stream()//转换成Stream流
.filter(s -> s.length() < 4)//过滤
.forEach(s -> System.out.println(s));//遍历
– map:对流中的元素进行计算或元素类型的转换
strings.stream()
.map(s -> s.length())//将元素转为int类型
.forEach(integer -> System.out.println(integer));
– distinct:去除流中的重复元素,依赖的是Object的equals来判断是否是相同对象的,所以要重写equals方法
strings.stream()
.distinct()
.forEach(s -> System.out.println(s));
– sorted:对流中的元素进行排序,用到Comparable相关,实体类需实现Comparable接口,重写compareTo方法,定义比较规则234567890-=
strings.stream()
.sorted()
.forEach(s -> System.out.println(s));
– limit:设置流最大长度,超出部分被抛弃
strings.stream()
.limit(2)
.forEach(s -> System.out.println(s));
– skip:跳过流中的前n和元素,返回剩下的元素
strings.stream()
.skip(2)
.forEach(s -> System.out.println(s));
– flatMap:map只能把一个对象转换成另一个对象来作为流中的元素,而faltMap可以把一个对象转换成多个对象作为流中的元素
ArrayList<String> strings = new ArrayList<>();
strings.add("艾/瑞/莉/娅");
strings.add("瑞/文");
strings.add("菲/奥/娜");
strings.add("丽/桑/卓");
strings.add("薇/恩");
strings.add("薇/恩");
strings.stream()
.flatMap(s -> Arrays.stream(s.split("/")))
.forEach(s -> System.out.println(s));
ArrayList<String> strings = new ArrayList<>();
strings.add("艾/瑞/莉/娅");
strings.add("瑞/文");
strings.add("菲/奥/娜");
strings.add("丽/桑/卓");
strings.add("薇/恩");
strings.add("薇/恩");
List<String> collect = strings.stream()
.flatMap(s -> Arrays.stream(s.split("/")))
.collect(Collectors.toList());
System.out.println(collect);
– 查找与匹配
T result = identity;//identity是自己赋的初始值,类型和Stream流中的元素类型一致
for(T element : this stream)//遍历Stream流中的每一个元素
result = accumulator.apply(result,element)//在这里指定计算逻辑并将结果返回给result
return result;
ArrayList<String> strings = new ArrayList<>();
strings.add("瑞文");
strings.add("艾瑞莉娅");
strings.add("菲奥娜");
strings.add("丽桑卓");
strings.add("薇恩");
strings.add("薇恩");
Integer reduce = strings.stream()
.map(s -> s.length())
.reduce(0, (i, element) -> i + element);//第一个参数是初始值,第二个参数是lambda表达式,定义了如何计算
System.out.println(reduce);
//一般使用Optional的静态方法:ofNullable即可直接将数据封装为Optiona对象,该方法不论传入的值是否为空都没问题
Optional<String> opt = Optional.ofNullable("aaa");
//若确定传入的参数不为空,也可使用Optional的静态方法:of来封装对象
Optional<String> opt = Optional.of("aaa");
– 安全消费值:一般使用Optional对象的ifPresent方法来消费其值,这个方法会判断内部封装的数据是否为空,不为空时才会执行具体的消费代码
– 安全获取值:Optional的get方法,但是可能有异常,推荐使用orElseGet/orElseThrow
//orElseGet:当数据不为空,则获取该数据,如果数据为空,则根据传入的参数来创建对象作为默认值返回
Optional<ArrayList<String>> strings1 = Optional.ofNullable(strings);//将列表转为Optional类型的对象
try {
strings1.orElseThrow((Supplier<Throwable>) () -> new RuntimeException("数据为null"))
} catch (Throwable throwable) {
throwable.printStackTrace();
}
//orElseThrow:获取数据,若数据不为空则获取数据,若为空则根据传入的参数来创建异常,抛出
– 过滤:filter方法对数据进行过滤,类似中间操作的filter方法
– 判断:建议使用ifPresent()方法
– 数据转换:map方法可以进行类型转换,类似中间操作的map方法
在使用lambda表达式时,若方法体中只有一个方法调用(直接引用其他方法)的话,可以用方法引用进一步简化代码
类名/对象名::方法名
Stream提供了方法可以直接将包装类转为基本数据类型,如:mapToInt,mapToLong,mapToDouble,flatMapToDouble等
当流中有大量元素时,我们可以使用并行流去提高操作效率,实质上并行流就是把任务分配给多个线程完成,自己代码实现比较麻烦复杂,使用Stream的话,只需修改一个方法的调用即可使用并行流实现
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Integer res;
integerStream.parallel()//调用parallel方法即可将流转换成并行流
.peek(num -> System.out.println(num + " -> " + Thread.currentThread().getName()))//peek方法是调试方法