Java8新特性
〇内部类(*)
外部链接链接
〇函数接口
外部链接链接
Function<Integer , Integer> f = Math::abs;
Consumer<String> c = System.out::println;
Supplier<Integer> s = "Hello"::length;
Predicate<String> p = "Hello"::equals;
c.accept(s.get().toString());
c.accept(p.test("Hello") && true ? "A":"B");
c.accept(f.apply(-1000).toString());
①Lambda表达式介绍
- 在JDK8之前,Java是不支持函数式编程的,所谓的函数编程,即可理解是将一个函数(也称为“行为”)作为一个参数进行传递。
- 通常我们提及得更多的是面向对象编程,面向对象编程是对数据的抽象(各种各样的POJO类),而函数式编程则是对行为的抽象(将行为/方法作为一个参数进行传递)。
- 在JavaScript中这是很常见的一个语法特性,但在Java中将一个函数作为参数传递这却行不通,好在JDK8的出现打破了Java的这一限制。
②基本的语法规则
**能够接收Lambda表达式的参数类型,是一个只包含一个方法的接口。**只包含一个方法的接口称之为“函数接口”。
1. 无参数,无返回值
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Hello World!");
}
});
//使用Lambda表达式则只需要使用一句话就可代替上面使用匿名类的方式
new Thread(() -> System.out.println("Hello World!"));
2. 有参数,无返回值
Lambda表达式“(x) -> Sysout.out.println(“Hello World” + x)”,左边传递的是参数,此处并没有指明参数类型,因为它可以通过上下文进行类型推导,但在有些情况下不能推导出参数类型(参数是范型的时候),此时则需要指明参数类型 。
public interface FunctionInterface {
void test(int param);
}
//接口测试
public class FunctionInterfaceTest {
@Test
public void testLambda() {
//使用Lambda表达式代替匿名内部类
func((x) -> System.out.println("Hello World" + x));
}
private void func(FunctionInterface functionInterface) {
int x = 1;
functionInterface.test(x);
}
}
3. 有参数,有返回值
public interface FunctionInterface<T> {
boolean test(T param);
}
//接口测试
public class FunctionInterfaceTest {
@Test
public void testLambda() {
//使用Lambda表达式代替匿名内部类
func((Integer x) -> true);
}
private void func(FunctionInterface<Integer> functionInterface{
int x = 1;
functionInterface.test(x);
}
}
此时的Lambda表达式“(Integer x) -> true”,右边是表达式的主体,直接返回true,如果有多行代码,则可以直接使用花括号表示,例如:
func((Integer x) -> {
System.out.println("Hello World" + x);
return true;
});
4.小结
这三种基本情况已经大致清楚了,特别是需要弄清,什么时候可以使用Lambda表达式代替匿名内部类,也就是Lambda表达式的应用场景是函数接口。Lambda表达式这一新特性在JDK8中的引入,更大的好处则是集合API的更新,新增的Stream类库,使得我们在遍历使用集合时不再像以往那样不断地使用for循环。
2.Stream流遍历集合
①流介绍
-
流是 JDK8 新增的成员,允许以声明性方式处理数据集合,可以把 Stream 流看作是遍历数据集合的一个高级迭代器 。
-
stream的操作可以分为两类,中间操作(intermediate operations)和结束操作(terminal operations):
-
- 中间操作总是会惰式执行,调用中间操作只会生成一个标记了该操作的新stream。
- 结束操作会触发实际计算,计算发生时会把所有中间操作积攒的操作以pipeline的方式执行,这样可以减少迭代次数。计算完成之后stream就会失效。
-
虽然大部分情况下stream是容器调用Collection.stream()方法得到的,但stream和collections有以下不同:
-
- 无存储。stream不是一种数据结构,它只是某种数据源的一个视图,数据源可以是一个数组,Java容器或I/O channel等。
- 为函数式编程而生。对stream的任何修改都不会修改背后的数据源,比如对stream执行过滤操作并不会删除被过滤的元素,而是会产生一个不包含被过滤元素的新stream。
- 惰式执行。stream上的操作并不会立即执行,只有等到用户真正需要结果的时候才会执行。
- 可消费性。stream只能被“消费”一次,一旦遍历过就会失效,就像容器的迭代器那样,想要再次遍历必须重新生成。
②获取stream
// 1、数组
String[] arr = new String[]{"ab", "cd", "ef"};
Stream<String> arrStream = Arrays.stream(arr);
// 2、集合
List<String> list = Arrays.asList("ab", "cd", "ef");
Stream<String> colStream = list.stream();
// 3、值
Stream<String> stream = Stream.of("ab", "cd", "ef");
③stream方法使用
测试数据:
List<User> list = Arrays.asList(
// name,age
new User("张三", 11),
new User("王五", 20),
new User("王五", 91),
new User("张三", 8),
new User("李四", 44),
new User("李四", 44),
new User("李四", 44)
);
1.forEach()
使用该方法迭代流中的每个数据
/**
* forEach 迭代输出每条数据.
*/
@Test
public void testForEach(){
// java 8 前
System.out.println("java 8 前");
for(User user: list){
System.out.println(user);
}
// java 8 lambda
System.out.println("java 8 lambda");
list.forEach(user -> System.out.println(user));
// java 8 stream lambda
System.out.println("java 8 stream lambda");
list.stream().forEach(user -> System.out.println(user));
}
2.sorted()
使用该方法排序数据
/**
* sort 排序.
*/
@Test
public void testSort() {
System.out.println("-----排序前-----");
list.forEach(user -> System.out.println(user));
System.out.println("-----排序后-----");
// java 8 前
System.out.println("java 8 前");
Collections.sort(list, new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
return o1.getAge().compareTo(o2.getAge());
}
});
for (User user : list) {
System.out.println(user);
}
// java 8 stream 方法引用
System.out.println("java 8 stream 方法引用");
list.stream().sorted(Comparator.comparing(User::getAge)).forEach(user -> System.out.println(user));
}
3.filter()
使用该方法过滤
/**
* filter 过滤.
*/
@Test
public void testFilter(List<User> list) {
// 输出年龄大于50的人
System.out.println("-----过滤前-----");
list.forEach(user -> System.out.println(user));
System.out.println("-----过滤后-----");
// java 8 前
System.out.println("java 8 前");
for(User user: list){
if (user.getAge() > 50) {
System.out.println(user);
}
}
// java 8 stream
System.out.println("java 8 stream");
list.stream().filter((User user) -> user.getAge() > 50).forEach(user -> System.out.println(user));
}
4.limit()
使用方法截断
/**
* limit 截断.
*/
@Test
public void testLimit() {
// 从第三个开始截断,只输出前三个
System.out.println("-----截断前-----");
list.forEach(user -> System.out.println(user));
System.out.println("-----截断后-----");
// java 8 前
System.out.println("java 8 前");
for (int i = 0; i < 3; i++) {
System.out.println(list.get(i));
}
// java 8 stream
System.out.println("java 8 stream");
list.stream().limit(3).forEach(user -> System.out.println(user));
}
5.map()
//将指定方法应用到每个元素上
.map(Transaction::getYear)
6.distinct()
去重
7.collect()
//收集成集合
.collect(toList())
3.应用测试
①Trader类
package Lambda;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* @author mingxian.wen@hand-china.com
* @description:
* @create 2019-09-03 14:14
*/
@Data
@AllArgsConstructor
public class Trader {
private String name;
private String city;
}
②Transaction类
package Lambda;
import lombok.AllArgsConstructor;
import lombok.Data;
/**
* @author mingxian.wen@hand-china.com
* @description:
* @create 2019-09-03 14:15
*/
@Data
@AllArgsConstructor
public class Transaction {
private Trader trader;
private int year;
private int value;
}
③主函数
package Lambda;
import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.toList;
import java.util.*;
/**
* @author mingxian.wen@hand-china.com
* @description:
* @create 2019-09-03 14:15
*/
public class LambdaMain {
Trader raoul = new Trader("Raoul", "Cambridge");
Trader mario = new Trader("Mario", "Milan");
Trader alan = new Trader("Alan", "Cambridge");
Trader brian = new Trader("Brian", "Cambridge");
List<Transaction> transactions = Arrays.asList(
new Transaction(brian, 2011, 300),
new Transaction(raoul, 2012, 1000),
new Transaction(raoul, 2011, 400),
new Transaction(mario, 2012, 710),
new Transaction(mario, 2012, 700),
new Transaction(alan, 2012, 950)
);
/*找出2011年发生的所有交易,并按交易额排序*/
public void T1() {
List<Transaction> list = transactions.stream()
//.map(Transaction::getYear)
.filter((t) -> t.getYear() == 2011)
.sorted(comparing(Transaction::getValue))
.collect(toList());
/*.forEach(System.out::println);*/
list.forEach(System.out::println);
}
/*交易员在哪些不同的城市工作过*/
public void T2() {
List<String> list = transactions.stream()
//.map(Transaction::getTrader)
//.map(Trader::getCity)
.map((t) -> t.getTrader().getCity())
.distinct()
.collect(toList());
list.forEach(System.out::println);
}
/*查找所有来自剑桥的交易员,并按姓名排序*/
public void T3() {
List<Trader> list = transactions.stream()
.map(Transaction::getTrader)
.distinct()
.filter((t) -> "Cambridge".equals(t.getCity()))
.sorted(comparing(Trader::getName))
.collect(toList());
list.forEach(System.out::println);
}
/*返回所有交易员的姓名字符串,并按字母顺序排序*/
public void T4() {
String str = transactions.stream()
.map((t) -> t.getTrader().getName())
.distinct()
.sorted()
.reduce("", (s1, s2) -> s1 + s2 + " ")
.trim();
System.out.println(str);
}
/*有没有交易员在米兰工作的?*/
public void T5() {
List<String> list = transactions.stream()
.map(Transaction::getTrader)
.distinct()
.filter((t) -> "Milan".equals(t.getCity()))
.map(Trader::getName)
.collect(toList());
list.forEach(System.out::println);
boolean anyMatch = transactions.stream()
.anyMatch((t) -> "Milan".equals(t.getTrader().getCity()));
System.out.println(anyMatch);
}
/*打印生活在剑桥的交易员的所有交易额*/
public void T6() {
List<Integer> list = transactions.parallelStream()
.filter((t) -> "Cambridge".equals(t.getTrader().getCity()))
.map(Transaction::getValue)
.collect(toList());
list.forEach(System.out::println);
}
/*所有交易中,最高的交易额是多少*/
public void T7() {
Integer value = transactions.stream()
//.max(Comparator.comparing(Transaction::getValue))
.map(Transaction::getValue)
.reduce(0,Integer::max);
System.out.println(value);
}
/*找到交易额最小的交易*/
public void T8() {
Transaction transaction = transactions.stream()
.min(Comparator.comparing(Transaction::getValue))
.orElse(null);
System.out.println(transaction);
}
public static void main(String[] args) {
LambdaMain lambdaMain = new LambdaMain();
lambdaMain.T8();
}
}