Java函数式编程
概述
学习函数式编程可以是我们的代码更加优雅,开发快速,它跟面向对象不同,面向对象考虑用什么对象完成什么事情,函数式编程更加类似于数学的函数,主要关注的是对数据进行了什么样的操作
Lamda表达式
使用的前提是,它是一个接口,而且只有一个抽象方法。是对匿名内部类写法的简化,也是函数式编程的重要体现。写法是(参数列表)->{方法体}
例子1
Runnable接口
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
匿名内部类写法
package gdut.edu.test01;
public class Lamda01 {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("新线程run方法执行了");
}
}).start();
}
}
Lamda表达式写法
package gdut.edu.test01;
public class Lamda02 {
public static void main(String[] args) {
new Thread(() -> System.out.println("新线程run方法执行了")).start();
}
}
例子2
接口
- Count接口
package gdut.test02;
public interface Count {
int add(int num1, int num2);
}
- PrintStr接口
package gdut.test02;
public interface PrintStr {
void handle(String s);
}
LamdaUtils
package gdut.test02;
public class LamdaUtils {
public static int add(Count count){
int num1 = 2;
int num2 = 3;
int add = count.add(num1, num2);
return add;
}
public static void printStr(PrintStr printStr){
String str = "hello world";
printStr.handle(str);
}
}
Test
package gdut.test02;
public class Lamda01 {
public static void main(String[] args) {
// Count匿名内部类写法
int res = LamdaUtils.add(new Count() {
@Override
public int add(int num1, int num2) {
return num1 + num2;
}
});
System.out.println(res);
// 没有简化的lamda表达式写法
res = LamdaUtils.add((int num1, int num2) -> {
return num1 + num2;
});
System.out.println(res);
// 简化lamda表达式,参数类型可以不写,代码只有一句时,大括号、return、该句代码的分号可以省略
res = LamdaUtils.add((num1, num2) -> num1 + num2);
System.out.println(res);
// PrintStr匿名内部类写法
LamdaUtils.printStr(new PrintStr() {
@Override
public void handle(String s) {
System.out.println(s);
}
});
// lamda表达式写法
LamdaUtils.printStr((String s) -> {
System.out.println(s);
});
// lamda表达式简写,参数类型可以不写,只有一个参数时,小括号可以省略,
// 代码只有一句时,大括号、return、该句代码的分号可以省略
LamdaUtils.printStr(s -> System.out.println(s));
}
}
Stream流
概述
Java的Stream流使用的是函数式编程模式,可以用来对集合、数组进行链状流式操作,方便我们对集合、数组操作
常用操作
创建流=>中间操作=>最终操作(一定要有最终操作,否则前面的中间操作无效)
创建stream流
- 单列集合创建stream流:(集合对象).stream()
- 数组创建stream流:Arrays.stream(数组)或者Stream.of()
- 双列集合创建stream流:先转换成单列集合,然后使用(集合对象).stream()创建
package gdut.stream;
import gdut.stream.middle.MapTest;import java.util.*;
import java.util.stream.Stream;
public class BuildStream {
public static void main(String[] args) {
// 创建stream流
// 单列集合创建stream流,使用(集合对象).stream()
ArrayList<Integer> integersList = new ArrayList<>();
Stream<Integer> integerStream = integersList.stream();
// 数组创建Stream流,使用Arrays.stream(数组)或者Stream.of()
Integer[] arr = {1, 2, 3, 4, 5};
Stream<Integer> arrStream1 = Arrays.stream(arr);
Stream<Integer> arrStream2 = Stream.of(arr);
// 双列集合创建stream流,先转换成单列集合再创建
HashMap<String, Integer> stringIntegerHashMap = new HashMap<>();
stringIntegerHashMap.put("key1", 1);
stringIntegerHashMap.put("key2", 2);
stringIntegerHashMap.put("key3", 3);
Set<MapTest.Entry<String, Integer>> entrySet = stringIntegerHashMap.entrySet();
Stream<MapTest.Entry<String, Integer>> entryStream = entrySet.stream();
Set<String> keySet = stringIntegerHashMap.keySet();
Stream<String> keyStream = keySet.stream();
}
}
中间操作
filter
对流中的元素进行过滤,符合条件的留在流中
- 匿名内部类写法
package gdut.stream;
import java.util.Arrays;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
public class Filter {
public static void main(String[] args) {
// 筛选出数组中大于2的值
Integer[] arr = {1, 2, 3, 4, 5};
Stream<Integer> integerStream = Arrays.stream(arr);
integerStream
.filter(new Predicate<Integer>() {
@Override
public boolean test(Integer integer) {
return integer > 2;
}
})
.forEach(new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
System.out.println(integer);
}
});
}
}
- lamda表达式写法
package gdut.stream;
import java.util.Arrays;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
public class FilterLamda {
public static void main(String[] args) {
// 筛选出数组中大于2的值
Integer[] arr = {1, 2, 3, 4, 5};
Stream<Integer> integerStream = Arrays.stream(arr);
integerStream
.filter(integer -> integer > 2)
.forEach(integer -> System.out.println(integer));
}
}
map
map操作对流中元素进行计算或者转换类型
- 匿名内部类写法
package gdut.stream;
import java.util.Arrays;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;
public class MapTest {
public static void main(String[] args) {
Integer[] arr = {1, 2, 3, 4, 5};
// map操作可以对流中的元素进行计算或者转换类型
Stream<Integer> integerStream = Arrays.stream(arr);
integerStream
.map(new Function<Integer, Integer>() {
@Override
public Integer apply(Integer integer) {
// 对元素加100
return integer + 100;
}
})
.map(new Function<Integer, String>() {
@Override
public String apply(Integer integer) {
return integer.toString()+"变成字符串";
}
})
.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
}
}
- lamda表达式写法
package gdut.stream;
import java.util.Arrays;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;
public class MapLamda {
public static void main(String[] args) {
Integer[] arr = {1, 2, 3, 4, 5};
// map操作可以对流中的元素进行计算或者转换类型
Stream<Integer> integerStream = Arrays.stream(arr);
integerStream
.map(integer -> integer + 100)
.map(integer -> integer.toString() + "变成字符串")
.forEach(s -> System.out.println(s));
}
}
distinct
distinct依赖Object的equals方法来判断是否是相同对象,从而去重流中相同的元素
package gdut.stream;
import gdut.stream.middle.Student;import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class DistinctTest {
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
for (int i = 0; i < 5; i++) {
Student student = new Student(i, "student" + i);
students.add(student);
}
students.add(new Student(0, "student0"));//添加一个相同的学生
Stream<Student> studentStream = students.stream();
// distinct依赖Object的equals方法来判断是否是相同对象,从而去重流中的元素
studentStream
.distinct()
.forEach(student -> System.out.println(student));
}
}
sorted
对流中的元素进行排序操作,如果调用空参sorted()方法,要求流中的元素实现Comparable接口
- 匿名内部类写法
package gdut.stream;
import gdut.stream.middle.Student;import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Stream;
public class SortedTest {
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
for (int i = 0; i < 5; i++) {
Student student = new Student(i, "student" + i);
students.add(student);
}
Stream<Student> studentStream = students.stream();
studentStream
.sorted(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o2.getAge() - o1.getAge();
}
})
.forEach(student -> System.out.println(student));
}
}
- lamda表达式写法
package gdut.stream;
import gdut.stream.middle.Student;import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
public class SortedTest {
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
for (int i = 0; i < 5; i++) {
Student student = new Student(i, "student" + i);
students.add(student);
}
Stream<Student> studentStream = students.stream();
studentStream
.sorted((o1, o2) -> o2.getAge() - o1.getAge())
.forEach(student -> System.out.println(student));
}
}
limit
设置流的最大长度,超出部分会被抛弃
package gdut.stream;
import gdut.stream.middle.Student;import java.util.ArrayList;
import java.util.List;
public class LimitTest {
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
for (int i = 0; i < 5; i++) {
Student student = new Student(i, "student" + i);
students.add(student);
}
students.stream()
.sorted((student1, student2) -> student2.getAge() - student1.getAge())
.limit(2)
.forEach(student -> System.out.println(student));
}
}
skip
跳过流中前n个元素,返回剩余元素
package gdut.stream;
import gdut.stream.middle.Student;import java.util.ArrayList;
import java.util.List;
public class SkipTest {
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
for (int i = 0; i < 5; i++) {
Student student = new Student(i, "student" + i);
students.add(student);
}
// skip跳过流中前n个元素,返回剩余元素
students.stream()
.sorted((student1, student2) -> student2.getAge() - student1.getAge())
.skip(2)
.forEach(student -> System.out.println(student));
}
}
flatMap
map只能把一个对象转换成另一个对象作为流中的元素,flatMap可以把一个对象转换成多个对象作为流中的元素
- map转换和flatMap转换对比,匿名内部类写法
package gdut.stream;
import gdut.stream.middle.Student;import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Stream;
public class FlatMapTest {
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
ArrayList<String> books = new ArrayList<>();
books.add("数学");
books.add("英语");
books.add("语文");
for (int i = 0; i < 5; i++) {
Student student = new Student(i, "student" + i, books);
students.add(student);
}
Stream<Student> studentStream1 = students.stream();
Stream<Student> studentStream2 = students.stream();
// 使用map
studentStream1
.map(new Function<Student, List<String>>() {
@Override
public List<String> apply(Student student) {
return student.getBooks();
}
})
.forEach(new Consumer<List<String>>() {
@Override
public void accept(List<String> strings) {
System.out.println(strings);
}
});
// 使用flatMap
studentStream2
.flatMap(new Function<Student, Stream<String>>() {
@Override
public Stream<String> apply(Student student) {
return student.getBooks().stream();
}
})
.distinct()
.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
}
}
- map和flatMap对比,lamda表达式写法
package gdut.stream;
import gdut.stream.middle.Student;import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Stream;
public class FlatMapLamda {
public static void main(String[] args) {
List<Student> students = new ArrayList<>();
ArrayList<String> books = new ArrayList<>();
books.add("数学");
books.add("英语");
books.add("语文");
for (int i = 0; i < 5; i++) {
Student student = new Student(i, "student" + i, books);
students.add(student);
}
Stream<Student> studentStream1 = students.stream();
Stream<Student> studentStream2 = students.stream();
// 使用map
studentStream1
.map(student -> student.getBooks())
.forEach(stringsList -> System.out.println(stringsList));
// 使用flatMap
studentStream2
.flatMap((Function<Student, Stream<String>>) student -> student.getBooks().stream())
.distinct()
.forEach(s -> System.out.println(s));
}
}
终结操作
forEach
对流中的元素进行遍历操作
package gdut.stream.last;
import java.util.ArrayList;
public class ForEachTest {
public static void main(String[] args) {
ArrayList<Integer> integers = new ArrayList<>();
integers.add(1);
integers.add(2);
integers.add(3);
integers.stream()
.forEach(item -> System.out.println(item + 100));
}
}
count
获取当前流中元素的个数
package gdut.stream.last;
import java.util.ArrayList;
public class CountTest {
public static void main(String[] args) {
ArrayList<String> strings = new ArrayList<>();
for (int i = 0; i < 10; i++) {
strings.add("string" + i);
}
long count = strings.stream()
.count();
System.out.println(count);
}
}
max&min
用来获取流中的最值
- 匿名内部类写法
package gdut.stream.last;
import gdut.stream.middle.Student;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Optional;
public class MinMaxTest {
public static void main(String[] args) {
ArrayList<Student> students = new ArrayList<>();
for (int i = 18; i < 100; i++) {
Student student = new Student(i, "name" + i);
students.add(student);
}
// 获取年龄最大或最小的student
Optional<Student> max = students.stream()
.max(new Comparator<Student>() {
@Override
public int compare(Student stu1, Student stu2) {
return stu1.getAge() - stu2.getAge();
}
});
Optional<Student> min = students.stream()
.min(new Comparator<Student>() {
@Override
public int compare(Student stu1, Student stu2) {
return stu1.getAge() - stu2.getAge();
}
});
System.out.println(max.get());
System.out.println(min.get());
}
}
- lamda表达式写法
package gdut.stream.last;
import gdut.stream.middle.Student;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Optional;
public class MinMaxLamda {
public static void main(String[] args) {
ArrayList<Student> students = new ArrayList<>();
for (int i = 18; i < 100; i++) {
Student student = new Student(i, "name" + i);
students.add(student);
}
// 获取年龄最大或最小的student
Optional<Student> max = students.stream()
.max((stu1, stu2) -> stu1.getAge() - stu2.getAge());
Optional<Student> min = students.stream()
.min((stu1, stu2) -> stu1.getAge() - stu2.getAge());
System.out.println(max.get());
System.out.println(min.get());
}
}
collect
将流中的元素保存为list、set、map
package gdut.stream.last;
import gdut.stream.middle.Student;
import java.util.*;
import java.util.stream.Collectors;
public class CollectTest {
public static void main(String[] args) {
ArrayList<Student> students = new ArrayList<>();
ArrayList<String> books = new ArrayList<>();
for (int i = 0; i < 5; i++) {
books.add("book" + i);
}
for (int i = 0; i < 5; i++) {
Student student = new Student(10 + i, "name" + i, books);
students.add(student);
}
students.add(new Student(10, "name0", books));
// 获取一个存放所有作者名的list集合
List<String> nameList = students.stream()
.map(student -> student.getName())
.collect(Collectors.toList());
System.out.println(nameList);
// 获取一个存放所有书名的set集合
Set<String> bookSet = students.stream()
.flatMap(student -> student.getBooks().stream())
.collect(Collectors.toSet());
System.out.println(bookSet);
// 获取一个有作者名和作者的书籍的map(key,value),注意要去重,key不能重复
Map<String, List<String>> resultMap = students.stream()
.distinct()
.collect(Collectors.toMap(student -> student.getName(),student->student.getBooks()));
Set<Map.Entry<String, List<String>>> entrySet = resultMap.entrySet();
Iterator<Map.Entry<String, List<String>>> iterator = entrySet.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
查找与匹配
anyMatch
只要流中有元素符合某个条件就返回true,如果全部不符合就返回false
- 匿名内部类写法
package gdut.stream.last;
import java.util.ArrayList;
import java.util.function.Predicate;
public class AnyMatchTest {
public static void main(String[] args) {
ArrayList<Integer> integers = new ArrayList<>();
for (int i = 0; i < 100; i++) {
integers.add(i);
}
// 只要流中有一个元素符合某个条件就返回true,如果全部不符合就返回false
boolean resFlag = integers.stream()
.anyMatch(new Predicate<Integer>() {
@Override
public boolean test(Integer integer) {
return integer > 77;
}
});
System.out.println(resFlag);
}
}
- lamda表达式写法
package gdut.stream.last;
import java.util.ArrayList;
import java.util.function.Predicate;
public class AnyMatchLamda {
public static void main(String[] args) {
ArrayList<Integer> integers = new ArrayList<>();
for (int i = 0; i < 100; i++) {
integers.add(i);
}
// 只要流中有一个元素符合某个条件就返回true,如果全部不符合就返回false
boolean resFlag = integers.stream()
.anyMatch(integer -> integer > 77);
System.out.println(resFlag);
}
}
allMatch
判断流中是否所有元素都符合某个条件,全部符合返回true,有一个不符合都返回false
package gdut.stream.last;
import java.util.ArrayList;
public class AllMatchTest {
public static void main(String[] args) {
ArrayList<Integer> integers = new ArrayList<>();
for (int i = 10; i <100 ; i++) {
integers.add(i);
}
// allMatch判断是否所有元素符合某个条件,全部符合返回true,有一个不符合就返回false
boolean flag = integers.stream()
.allMatch(integer -> integer > 10);
System.out.println(flag);
}
}
noneMatch
都不符合某个条件返回true,只要有一个符合某个条件就返回false
package gdut.stream.last;
import java.util.ArrayList;
public class NoneMatchTest {
public static void main(String[] args) {
ArrayList<Integer> integers = new ArrayList<>();
for (int i = 0; i < 100; i++) {
integers.add(i);
}
// noneMatch都不符合某个条件,返回true,有一个符合某个条件返回false
boolean flag = integers.stream()
.noneMatch(integer -> integer > 100);
System.out.println(flag);
}
}
findAny
获取流中的任意一个元素,但是没有办法保证获取到的一定是流中的第一个元素
package gdut.stream.last;
import java.util.ArrayList;
import java.util.Optional;
public class FindAnyTest {
public static void main(String[] args) {
ArrayList<Integer> integers = new ArrayList<>();
for (int i = 0; i < 100; i++) {
integers.add(i);
}
// findAny查找出integers中大于18的任意一个数字,没办法保证获取的一定是流中的第一个元素
Optional<Integer> any = integers.stream()
.filter(integer -> integer > 18)
.findAny();
any.ifPresent(integer -> System.out.println(integer));
}
}
findFirst
获取流中的第一个元素
package gdut.stream.last;
import java.util.ArrayList;
import java.util.Optional;
public class FindFirstTest {
public static void main(String[] args) {
ArrayList<Integer> integers = new ArrayList<>();
for (int i = 0; i < 100; i++) {
integers.add(i);
}
// findFirst获取流中的第一个元素
Optional<Integer> first = integers.stream()
.findFirst();
first.ifPresent(integer -> System.out.println(integer));
}
}
reduce归并
对流中的数据进行操作,最终返回一个值
- 匿名内部类方式
package gdut.stream.last;
import java.util.ArrayList;
import java.util.Optional;
import java.util.function.BinaryOperator;
public class ReduceTest {
public static void main(String[] args) {
ArrayList<Integer> integers = new ArrayList<>();
for (int i = 0; i < 100; i++) {
integers.add(i);
}
// reduce操作,获取流中的最大值,设置初始值为最小值
// System.out.println(Integer.MIN_VALUE);
Integer result = integers.stream()
.reduce(Integer.MIN_VALUE, new BinaryOperator<Integer>() {
@Override
public Integer apply(Integer result, Integer element) {
return result > element ? result : element;
}
});
System.out.println(result);
// reduce操作,获取流中的最小值,不设置默认值,利用重载方法,底层设置默认值为流中的第一个值
Optional<Integer> result2 = integers.stream()
.reduce(new BinaryOperator<Integer>() {
@Override
public Integer apply(Integer result, Integer element) {
return result > element ? element : result;
}
});
result2.ifPresent(res -> System.out.println(res));
}
}
- lamda表达式写法
package gdut.stream.last;
import java.util.ArrayList;
import java.util.Optional;
import java.util.function.BinaryOperator;
public class ReduceLamda {
public static void main(String[] args) {
ArrayList<Integer> integers = new ArrayList<>();
for (int i = 0; i < 100; i++) {
integers.add(i);
}
// reduce操作,获取流中的最大值,设置初始值为最小值
// System.out.println(Integer.MIN_VALUE);
Integer result = integers.stream()
.reduce(Integer.MIN_VALUE, (result1, element) -> result1 > element ? result1 : element);
System.out.println(result);
// reduce操作,获取流中的最小值,不设置默认值,利用重载方法,底层设置默认值为流中的第一个值
Optional<Integer> result2 = integers.stream()
.reduce((result12, element) -> result12 > element ? element : result12);
result2.ifPresent(res -> System.out.println(res));
}
}
注意事项
- 没有终结操作,中间操作不会执行(惰性求值)
- 流是一次性的(一旦一个流对象经过终结操作之后,这个流不能再使用)
- 在流中对数据进行处理,不触碰数据的set方法一般不会影响原数据
Optional
概述
我们在编写代码的时候经常出现空指针异常,使用optional可以写出更加优雅的代码避免出现空指针异常
创建optional对象
- 创建一个获取Optional的工具类
package gdut.stream.optional;
import gdut.stream.middle.Student;
import java.util.Optional;
public class GetStudentUtils {
public static Optional<Student> getStudent() {
Student student = new Student(22, "name");
return Optional.ofNullable(student);
}
}
- 安全消费
package gdut.stream.optional;
import gdut.stream.middle.Student;
import java.util.Optional;
import java.util.function.Consumer;
public class OptionalTest {
public static void main(String[] args) {
Optional<Student> student = GetStudentUtils.getStudent();
student.ifPresent(new Consumer<Student>() {
@Override
public void accept(Student student) {
System.out.println("student = " + student);
}
});
}
}
optional的一些操作
package gdut.stream.optional;
import gdut.stream.middle.Student;
import java.util.Optional;
public class OptionalTest {
public static void main(String[] args) {
Optional<Student> student = GetStudentUtils.getStudent();
// 安全消费
student.ifPresent(student1 -> System.out.println("student = " + student1));
// Student student1 = student.get();//这种获取方法不推荐,如果student为null会报java.util.NoSuchElementException: No value present
// optional也可以像stream流一样过滤
student.filter(stu -> stu.getAge() > 10).ifPresent(stu -> System.out.println(stu));
// optional也可以有map操作
Optional<String> nameStr = student.map(stu -> stu.getName());
nameStr.ifPresent(str -> System.out.println(str));
}
}
函数式接口
概述
- 函数式接口只有一个抽象方法,JDK的函数式接口都加上了@FunctionalInterface注解,无论是否有该注解,只要接口中只有一个抽象方法,都是函数式接口
常见函数式接口
- Consumer消费接口
@FunctionalInterface
public interface Consumer<T> {
/**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);
}
- Function计算转换接口
@FunctionalInterface
public interface Function<T, R> {
/**
* Applies this function to the given argument.
*
* @param t the function argument
* @return the function result
*/
R apply(T t);
}
- Predicate判断接口
@FunctionalInterface
public interface Predicate<T> {
/**
* Evaluates this predicate on the given argument.
*
* @param t the input argument
* @return {@code true} if the input argument matches the predicate,
* otherwise {@code false}
*/
boolean test(T t);
}
- Supplier生产型接口
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
Stream并行流
当流中有大量的元素时,可以使用并行流去提高操作效率,并行流就是把任务分配给多个线程,最总在终结操作将结果汇总
package gdut.stream.last;
import java.util.ArrayList;
import java.util.Optional;
import java.util.function.Consumer;
public class ParallelStreamTest {
public static void main(String[] args) {
ArrayList<Integer> integers = new ArrayList<>();
for (int i = 0; i < 100; i++) {
integers.add(i);
}
Optional<Integer> res = integers.stream().parallel()
.peek(new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
System.out.println(integer + Thread.currentThread().getName());
}
})
.filter(num -> num < 10)
.reduce((result, element) -> result + element);
res.ifPresent(System.out::println);
}
}
方法引用
我们在使用lamda表达式时,如果方法体只有一个方法的调用的时候我们可以使用方法引用来简化代码
推荐用法
我们在使用lamda表达式的时候,方法体只有一个方法的调用,我们不需要考虑如何去写方法引用,用哪种方法引用,方法引用的格式是什么。在写完lamda表达式后,我们只需要根据快捷键(这里我使用的是idea的alt
+enter
)来尝试其是否可以转换成方法引用的写法。
基本格式
类名或者对象名::方法名
语法了解
引用类的静态方法
- 格式 类名::方法名
- 使用前提 在重写方法的时候,方法体只有一行代码,并且这行代码调用了某个类的静态方法,并且我们把重写的抽象方法的所有参数都按照顺序传入了这个静态方法中,这个时候我们就可以引用类的静态方法
- Cat接口
package gdut.stream.quote;
public interface Cat<T, E> {
E myCat(T t);
}
- CatUtils
package gdut.stream.quote;
public class CatUtils {
public static <T, E> E getCatAge(T t, Cat<T, E> cat) {
E e = cat.myCat(t);
return e;
}
public <T, E> E get(T t, Cat<T, E> cat) {
E e = cat.myCat(t);
return e;
}
}
- CatTest
package gdut.stream.quote;
public class CatTest {
public static void main(String[] args) {
Integer age = 10;
String strAge = CatUtils.getCatAge(age, new Cat<Integer, String>() {
@Override
public String myCat(Integer integer) {
return String.valueOf(integer);
}
});
System.out.println(strAge);
String strAge2 = CatUtils.getCatAge(age, integer -> String.valueOf(integer));
System.out.println(strAge2);
String strAge3 = CatUtils.getCatAge(age, String::valueOf);
System.out.println(strAge2);
}
}
引用对象的实例方法
- 格式 对象名::方法名
- 使用前提 重写方法时,方法体只有一行代码,并且这行代码调用了某个对象的成员方法,并且我们把要重写的抽象方法所有参数都按照顺序传入了这个成员方法中,这个时候我们就可以引用对象的实例方法
package gdut.stream.quote;
public class CatTest02 {
public static void main(String[] args) {
Integer age = 22;
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("hello+tomcat+");
StringBuffer catAge = CatUtils.getCatAge(age, new Cat<Integer, StringBuffer>() {
@Override
public StringBuffer myCat(Integer integer) {
return stringBuffer.append(integer);
}
});
System.out.println(catAge.toString());
StringBuffer catAge2 = CatUtils.getCatAge(age, integer -> stringBuffer.append(integer));
System.out.println(catAge2.toString());
StringBuffer catAge3 = CatUtils.getCatAge(age, stringBuffer::append);
System.out.println(catAge3.toString());
}
}
引用类的实例方法
- 格式 类名::方法名
- 使用前提 重写方法时,方法体只有一行代码,并且这行代码调用了第一个参数的成员方法,并且把我们重写的抽象方法中剩余参数都按照顺序传入这个成员方法中,这时我们可以使用引用类的实例方法
- Dog实体类
package gdut.stream.quote;
public class Dog {
private String name;
public Dog() {
}
public Dog(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
'}';
}
}
- DogInterface接口
package gdut.stream.quote;
public interface DogInterface<T,N> {
N aDog(T t);
}
- DogUtils
package gdut.stream.quote;
public class DogUtils {
public static <T,N> N getDog(T t,DogInterface<T,N> dog){
return dog.aDog(t);
}
}
- DogTest
package gdut.stream.quote;
public class DogTest {
public static void main(String[] args) {
Dog dog = new Dog("hotDog");
String dogName = DogUtils.getDog(dog, new DogInterface<Dog, String>() {
@Override
public String aDog(Dog dog) {
return dog.getName();
}
});
System.out.println(dogName);
String dogName1 = DogUtils.getDog(dog, dog1 -> dog1.getName());
System.out.println(dogName1);
String dogName2 = DogUtils.getDog(dog, Dog::getName);
System.out.println(dogName2);
}
}