jdk8基本用法

该文章主要是描述了jdk8函数式接口编程的基本用法,主要包括内置四大函数式接口、函数式接口应用案例及Stream集合流式操作。以下内容都是jdk8常用的语法demo,针对每一个点都有一个小case测试。

内置四大函数式接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/**
* @desc Java四大内置函数式接口
* Consumer<T>:消费型接口
* void accept(T t);
* Suppler<T>:供给型接口
* T get();
* Function<T, R>:函数型接口
* R apply(T t);
* Predicate<T>:断言型接口
* boolean test(T t);
* @Author xw
* @Date 2019/9/9
*/
public class JDKFuncInterfaceDemo {
public static void main(String[] args) {
// Consumer<T>:消费型接口
printConsumer("abcd", (x) -> System.out.println(x));
// Suppler<T>:供给型接口;
// 案例:产生指定个数的整数,并放入集合中
int num = 5;
getNumList(num, () -> new Random().nextInt(100)).stream().forEach(System.out::println);
// Function<T, R>:函数型接口;
// 案例:字符串处理(转大小写、截取等)
System.out.println(strHandler("abcdefg", str -> str.toUpperCase()));
System.out.println(strHandler("abcdefg", str -> str.substring(0,3)));
// Predicate<T>:断言型接口(见MyFuncInterfaceDemo)
}
private static void printConsumer(String str, Consumer<String> func) {
func.accept(str);
}
private static String strHandler(String str, Function<String, String> func) {
return func.apply(str);
}
private static List<Integer> getNumList(int num, Supplier<Integer> sup) {
List<Integer> list = new ArrayList<>(num);
for (int i = 0; i < num; i++) {
list.add(sup.get());
}
return list;
}
}

函数式接口案例

案例需要的初始化数据

1
2
3
4
5
6
7
List<Employee> list = Arrays.asList(
new Employee("zhangsan", 20, 2500),
new Employee("lisi", 25, 4000),
new Employee("wangwu", 35, 8000),
new Employee("maliu", 45, 9000),
new Employee("tianqi", 50, 8000),
new Employee("smis", 26, 3000));

接口引用

常规操作

1
2
3
4
5
6
7
8
9
@Test
private static void test_normal(List<Employee> list) {
List<Employee> newList = filterEmpByAge(list);
System.out.println("----------大于25岁的-----------");
newList.stream().forEach(System.out::println);
newList = filterEmpBySalary(newList);
System.out.println("----------薪资大于5K的-----------");
newList.stream().forEach(System.out::println);
}

使用策略模式

1
2
3
4
5
6
7
8
9
@Test
private static void test_strategy(List<Employee> list) {
List<Employee> newList = filterEmployee(list, new AgePredicateStrategy());
System.out.println("----------年龄大于25岁的-----------");
newList.stream().forEach(System.out::println);
newList = filterEmployee(newList, new SalaryPredicateStrategy());
System.out.println("----------薪资大于5K的-----------");
newList.stream().forEach(System.out::println);
}

使用内部类

1
2
3
4
5
6
7
8
9
10
11
@Test
private static void test_inner_class(List<Employee> list) {
List<Employee> newList = filterEmployee(list, new MyPredicate<Employee>() {
@Override
public boolean test(Employee e) {
return e.getAge() > 25 && e.getSalary() > 5000;
}
});
System.out.println("----------年龄大于25岁 && 薪资大于5K的-----------");
newList.stream().forEach(System.out::println);
}

使用Lambda表达式

1
2
3
4
5
6
7
8
@Test
private static void test_lambda(List<Employee> list) {
/*filterEmployee(list, (Employee e) -> {return e.getAge() > 25 && e.getSalary() > 5000;});
filterEmployee(list, (Employee e) -> e.getAge() > 25 && e.getSalary() > 5000);*/
List<Employee> newList = filterEmployee(list, (e) -> e.getAge() > 25 && e.getSalary() > 5000);
System.out.println("----------年龄大于25岁 && 薪资大于5K的-----------");
newList.stream().forEach(System.out::println);
}

使用Stream

1
2
3
4
5
6
7
8
9
10
11
12
13
@Test
private static void test_stream01(List<Employee> list) {
System.out.println("----------年龄大于25岁 && 薪资大于5K的-----------");
filterEmployee(list, (e) -> e.getAge() > 25 && e.getSalary() > 5000).stream()
.forEach(System.out::println);
}
@Test
private static void test_stream02(List<Employee> list) {
System.out.println("----------年龄大于25岁 && 薪资大于5K的-----------");
filterEmployee(list, (e) -> e.getAge() > 25 && e.getSalary() > 5000).stream()
.map(Employee::getName)
.forEach(System.out::println);
}

方法引用

对象::实例方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Test
private static void test_instance_method() {
PrintStream ps1 = System.out;
Consumer<String> str1 = (x) -> ps1.println(x);
str1.accept("abc1");
PrintStream ps2 = System.out;
Consumer<String> str2 = ps2::println;
str2.accept("abc2");
Consumer<String> str3 = System.out::println;
str3.accept("abc3");
Employee emp = new Employee();
Supplier<String> funcName = () -> emp.getName();
System.out.println(funcName.get());
Supplier<Integer> funcAge = emp::getAge;
System.out.println(funcAge.get());
}

类::静态方法名

1
2
3
4
5
6
7
@Test
private static void test_static_method() {
Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
System.out.println(com.compare(1, 2));
Comparator<Integer> com2 = Integer::compareTo;
System.out.println(com2.compare(1, 2));
}

类::实例方法名

1
2
3
4
5
@Test
private static void test_normal_method() {
BiPredicate<String, String> bp = (x, y) -> x.equals(y);
System.out.println(bp.test("a", "b"));
}

构造器引用(实例名::new)

1
2
3
4
5
6
7
8
9
10
11
12
@Test
private static void test_constructor_method() {
Supplier<Employee> funcEmp = () -> new Employee();
System.out.println(funcEmp.get());
Supplier<Employee> funcEmp2 = Employee::new;
System.out.println(funcEmp2.get());
// 指定调用构造方法
Function<Integer, Employee> funcEmpAge = (x) -> new Employee(x);
System.out.println(funcEmpAge.apply(101));
Function<Integer, Employee> funcEmpAge2 = Employee::new;
System.out.println(funcEmpAge2.apply(102));
}

数组引用

1
2
3
4
5
6
7
8
private static void test_array_method() {
Function<Integer, String[]> funcArray = (x) -> new String[x];
String[] strs = funcArray.apply(10);
System.out.println(strs.length);
Function<Integer, String[]> funcArray2 = String[]::new;
String[] strs2 = funcArray.apply(20);
System.out.println(strs2.length);
}

Stream常规操作

创建Stream的几种方式

1
2
3
4
5
6
7
8
9
10
private static void test_create_stream() {
Stream<String> stream1 = new ArrayList<String>().stream();
Stream<String> stream2 = Arrays.stream(new String[]{"a", "b", "c"});
Stream<String> stream3 = Stream.of("a", "b", "c");
Stream<Integer> stream4 = Stream.iterate(0, (x) -> x + 2); // 无限流
stream4.limit(10).forEach(System.out::println);
Stream.generate(() -> Math.random())
.limit(5).forEach(System.out::println);
System.out.println("----------------------------------------");
}

流转集合的几种方式

1
2
3
4
5
6
7
8
9
10
private static void test_to_collect() {
List<String> list = employees.stream().map(Employee::getName).collect(Collectors.toList());
list.forEach(System.out::println);
System.out.println("----------------------------------------");
Set<String> set = employees.stream().map(Employee::getName).collect(Collectors.toSet());
set.forEach(System.out::println);
System.out.println("----------------------------------------");
HashSet<String> hashSet = employees.stream().map(Employee::getName).collect(Collectors.toCollection(HashSet::new));
hashSet.forEach(System.out::println);
}

统计

总数、平均值、最小值

1
2
3
4
5
6
7
8
9
10
11
12
private static void test_to_count1() {
System.out.println("总数:" + employees.stream().collect(Collectors.counting()));
System.out.println("平均值:" + employees.stream().collect(Collectors.averagingDouble(Employee::getSalary)));
System.out.println("最小值:" + employees.stream().collect(Collectors.minBy((x, y) -> Double.compare(x.getSalary(), y.getSalary()))).get()); // 已过时
System.out.println("最小值:" + employees.stream().min(Comparator.comparing(Employee::getSalary)).get());
System.out.println("最小值:" + employees.stream().min(Comparator.comparing(Employee::getSalary).thenComparing(Employee::getAge)).get());
System.out.println("------------另一种方式-----------");
DoubleSummaryStatistics collect = employees.stream().collect(Collectors.summarizingDouble(Employee::getSalary));
System.out.println("总数:" + collect.getCount());
System.out.println("平均值:" + collect.getAverage());
System.out.println("最小值:" + collect.getMin());
}

归约

1
2
3
4
5
6
7
8
9
10
private static void test_to_count2() {
// 归约
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Integer sum = list.stream().reduce(0, (x, y) -> x + y);
System.out.println(sum);
Integer amount1 = employees.stream().map(Employee::getSalary).reduce(0, (x, y) -> x + y);
System.out.println(amount1);
Integer amount2 = employees.stream().map(Employee::getSalary).reduce(Integer::sum).get();
System.out.println(amount2);
}

字符串拼接

1
2
3
4
private static void test_append_str() {
String str = employees.stream().map(Employee::getName).collect(Collectors.joining(",","(",")"));
System.out.println("str=" + str);
}

分组、分区

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private static void test_groupby_partitioningBy() {
// 按员工类型分组
Map<Employee.EmployeeType, Long> map1 = employees.stream().collect(Collectors.groupingBy(Employee::getEmployeeType, Collectors.counting()));
System.out.println(map1);
// 按员工类型 + 薪资分组
Map<Employee.EmployeeType, Map<String, List<Employee>>> map2 = employees.stream().collect(Collectors.groupingBy(Employee::getEmployeeType, Collectors.groupingBy((e) -> {
if (e.getSalary() >= 8000) {
return "高收入";
} else if (e.getSalary() >= 4000) {
return "中收入";
} else {
return "解决温饱";
}
})));
System.out.println(map2);
// 按薪资分区,>=8000 一个区,另外一个区
Map<Boolean, List<Employee>> map3 = employees.stream().collect(Collectors.partitioningBy(e -> e.getSalary() >= 8000));
System.out.println(map3);
}