java 1.8的新特性,lambda运行将函数作为一个方法的参数,也就是函数作为参数传递到方法中。 使用lambda表达式可以让代码更简洁。
Lambda表达式的使用场景:用以简化接口实现。
关于接口实现,可以有很多方式来实现。例如:设计接口的实现类、使用匿名内部类。Lambda比这两种都简单。
public class Demo1 {
public static void main(String[] args) {
Test test = () -> {
System.out.println("test");
};
test.test();
}
interface Test{
public void test();
}
}
lambda表达式只是一个匿名方法,当接口中的方法过多或过少的时候1,lambda表达式都是不适用的。
lambda表达式,只能实现函数式接口。
定义:如果一个接口中,要求实现类必须实现的抽象方法,有且只有一个,这样的接口,就是函数式接口口。
interface Test{
public void test();
}
这是一个注解,用在接口之前,判断这个接口是否是一个函数是接口。类似于@override
写Lambda表达式的时候,只需要关心参数列表和方法体。
(parameters)-> expression 或 (parameters) -> {statements;} 注:如果方法的参数列表中的参数数量 有且只有⼀个,此时,参数列表的小括号是可以省略不写的。
函数引用:引用⼀个已经存在的方法,使其替代lambda表达式完成接口的实现
接口设计:
@FunctionalInterface
interface A {
void test();
}
方法设计:
public static void testLambda(A a) {
a.test();
}
方法实现:
public static void main(String[] args) {
testLambda(() -> {
System.out.println("Lambda 表达式初体验");
});
}
常用函数接口:
接口设计:
@FunctionalInterface
interface Consumer<T> {
void accept(T t);
}
void accept(T t):对给定的参数执行此操作。
方法设计:
public static void testLambda(String str, Consumer<String> handle) {
handle.accept(str);
}
方法实现:
public static void main(String[] args) {
testLambda("lambda要处理的字符串", (s) -> {
System.out.println(Arrays.toString(s.toCharArray()));
});
}
接口设计:
@FunctionalInterface
interface Supplier<T> {
/**
* 无参数有返回值方法,泛型约束的是接口对应的返回值数据类型,要求
* 按照泛型约束返回对应的数据内容
*/
T get();
}
方法设计:
public static String testLambda(Supplier<String> s) {
return s.get();
}
//返回一个String类型的
方法实现:
public static void main(String[] args) {
String s1 = testLambda(() -> {
return "这里也是一个字符串";
});
System.out.println(s1);
}
Predicate:常用的四个方法:
boolean test(T t):对给定的参数进行判断(判断逻辑由Lambda表达式实现),返回一个布尔值
default Predicate negate():返回一个逻辑的否定,对应逻辑非
default Predicate and(Prduicate other):返回一个组合判断,对应短路与
default Predicate or(Predicate other):返回一个组合判断,对应短路或
接口设计:
// 过滤器接口,判断器接口,条件接口
@FunctionalInterface
interface Predicate<T> {
boolean test(T t);
}
方法设计:
public static Person[] filterPersonArrayUsingPredicate(Person[] array, Predicate<Person> filter) {
Person[] temp = new Person[array.length];
int count = 0;
for (int i = 0; i < array.length; i++) {
if (filter.test(array[i])) {
temp[count++] = array[i];
}
}
return temp;
}
方法实现:
public static void main(String[] args) {
Person[] array = new Person[5];
for (int i = 0; i < array.length; i++) {
int age = (int) (Math.random() * 50);
array[i] = new Person(i + 1, "张三", age, false);
}
Person[] temp = filterPersonArrayUsingPredicate(array, p -> p.getAge() > 10);
for (Person person : temp) {
System.out.println(person);
}
}
输出结果:
Person{id=2, name='张三', age=28, gender=false}
Person{id=4, name='张三', age=42, gender=false}
Person{id=5, name='张三', age=29, gender=false}
null
null
Function
R apply(T t);将此函数应用于给定的函数。
接口设计:
@FunctionalInterface
interface Function<T,R>{
R apply(T t);
}
方法设计;
public static int testLambda(String str, Function<String, Integer> fun) {
return fun.apply(str);
}
方法实现
public static void main(String[] args) {
String str = "开封有个包青天";
int i = testLambda(str, s -> s.length());
System.out.println(i);
}
输出结果:
7
java8 api添加了一个新的抽象成为Stream流,可以让编程者用一种声明的方式处理数据。
Stream极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
数据源:可以是集合,数组,I/O channel,生产器generator等。
根据集合来获取:
根据Collection获取流:
Collection接口中有一个stream()方法,可以获取流
default Stream<E> stream()
1.根据List获取流
List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();
2.根据Set获取流
Set<String> set = new HashSet<>();
Stream<String> stream2 = set.stream();
3.根据Map获取流
3.1根据Map集合的键来获取流
Map<Integer,String> map = new HashMap<>();
Set<Integer> map1 = map.keySet();
Stream<Integer> stream3 = map1.stream();
3.2根据Map集合的值获取流
Map<Integer,String> map = new HashMap<>();
Collection<String> map2 = map.values();
Stream<String> stream4 = map2.stream();
3.3根据Map集合的键值对对象获取流
Map<Integer,String> map = new HashMap<>();
Set<Map.Entry<Integer, String>> map3 = map.entrySet();
Stream<Map.Entry<Integer, String>> stream5 = map3.stream();
4.根据数组获取
String[] arr = {"张颜宇","张三","李四","赵五","刘六","王七"};
Stream<String> stream6 = Stream.of(arr);
Stream 处理数据的【中间方法】:skip、limit、sorted、sorted、filter、distinct、map
Stream 处理数据的【最终方法/终止方法】:
终止方法,Stream 流自动关闭。对应 Stream 占用的资源空间会被 JVM 收回。count、forEach、collect、toArray()
Stream提供了新的方法’forEach’来迭代流中的每个数据。例如随机输出10个随机数:
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);
map:方法用于映射每个元素对应的结果,以下代码片段使用 map 输出了元素对应的平方数:
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
// 获取对应的平方数
List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
filter 方法用于通过设置的条件过滤出元素。以下代码片段使用 filter 方法过滤出空字符串:
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// 获取空字符串的数量
long count = strings.stream().filter(string -> string.isEmpty()).count();
limit 方法用于获取指定数量的流。 以下代码片段使用 limit 方法打印出 10 条数据:
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);
sorted 方法用于对流进行排序。以下代码片段使用 sorted 方法对输出的 10 个随机数进行排序:
Random random = new Random();
random.ints().limit(10).sorted().forEach(System.out::println);
parallelStream 是流并行处理程序的代替方法。以下实例我们使用 parallelStream 来输出空字符串的数量:
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// 获取空字符串的数量
long count = strings.parallelStream().filter(string -> string.isEmpty()).count();
Collectors 类实现了很多归约操作,例如将流转换成集合和聚合元素。Collectors 可用于返回列表或字符串:
Collectors.toList() 目标存储集合类型为 List 集合
Collectors.toSet() 目标存储集合类型为 Set 集合