1.Lambda表达式
Lambda表达式:是一种特殊的匿名内部类,其语法更简洁。
Lambda表达式允许把一个函数作为参数,传入另一个函数中。
Lambda表达式的语法: <函数式接口名> <变量名>=(参数)->{方法体}
Lambda表达式引入了一个新的操作符:->,可以将这个箭头操作符理解成一个分隔符,它将表达式分为:左侧:(参数列表),右侧:{方法体}
以创建线程对象为例:
public static void main(String[] args) {
Runnable task01 = ()->{
System.out.println("Lambda表达式创建线程对象");
};
Thread thread = new Thread(task01);
thread.start();
}
注意事项:
1.在使用含参的lambda表达式时,可以省略参数类型,因为lambda表达式会根据上下文推测出参数所对应的参数类型
2.如果参数列表为空,则需要保留(),但是如果参数有且仅有一个时,则可以省略(),只写参数名即可。
3.如果方法体中无返回值,并且只有一条语句时,可以省略{},但是当方法体中有返回值,并且只有一条语句时,需要将return一并省略,而方法体中存在多条语句时,则不可以省略{}
4.Lambda表达式不会生成一个单独的内部类文件
2.函数式接口
上面说到的Lambda表达式,是基于函数式接口而实现的,那么什么是函数式接口呢?
函数式接口:如果一个接口中有且只有一个抽象方法,那么该接口就被称为函数式接口,在使用Lambda表达式时,Lambda表达式会自动对应到该抽象方法上。
可以使用@Functionalterface 注解来检测接口是否为函数式接口。
常见的函数式接口:
使用示例:
Consumer<T>
public class Test04 {
public static void main(String[] args) {
/*常见函数式接口
* 有参无返回值 Consumer<T>
* */
fun((age)->System.out.println("张三今年"+age+"岁"),22);
}
public static void fun(Consumer<Integer> consumer,Integer age){
consumer.accept(age);
}
}
Supplier<T>
public class Test05 {
public static void main(String[] args) {
/*无参有返回值*/
fun(()->new Random().nextInt(100));
}
public static void fun(Supplier<Integer> supplier){
Integer integer = supplier.get();
System.out.println("随机数结果为:"+integer);
}
}
Function<T,R>
public class Test06 {
public static void main(String[] args) {
/*有参有返回值*/
fun((s)->s.toLowerCase(),"HELLO");
}
public static void fun(Function<String,String> function,String msg){
String apply = function.apply(msg);
System.out.println("转化结果为:"+apply);
}
}
Predicate<T>
public class Test07 {
public static void main(String[] args) {
fun((age)->age-18>0?true:false,22);
}
public static void fun(Predicate<Integer> predicate,Integer age){
boolean test = predicate.test(age);
System.out.println("是否成年:"+test);
}
}
3.方法引用
作用:降低Java代码的冗余,在Lambda表达式的方法体中,如果所实现的功能与已存在的功能代码相同,则可以使用方法引用,来简化Lambda表达式的写法,同时降低代码的冗余;
方法引用的分类:
[1]静态方法引用: 类名::静态方法 (参数)->类名.静态方法(参数)
[2]实例方法引用: 对象::实例方法 (参数)->对象.实例方法(参数)
[3]对象方法引用: 类名::实例方法. (参数1,参数2)->参数1.实例方法(参数2)
[4]构造方法引用: 类名::new (参数)->new 类名(参数)
例如:
public class Test08 {
public static void main(String[] args) {
/*方法引用*/
fun(Test08::printMoney,2323);
/*对象方法引用*/
Function<String,String> function = String::toLowerCase;
String hello = function.apply("HELLO");
System.out.println(hello);
/*构造方法引用*/
Function<String,String> function1 = String::new;
String aaa = function1.apply("aaa");
System.out.println(aaa);
Function<String,Student> function2 = Student::new;
Student xiaoJiXiangCaoWang = function2.apply("小吉祥草王");
System.out.println(xiaoJiXiangCaoWang);
}
public static void fun(Consumer<Integer> consumer,int money){
consumer.accept(money);
}
public static void printMoney(int money){
System.out.println(money);
}
}
class Student{
private String name;
public Student(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
'}';
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
4.Stream流
Stream流是java8新增处理集合的抽象概念,它能够实现对集合进行复杂的查找、过滤、筛选等操作,极大的简化了我们对集合内数据的操作。
Stream流可以优化我们原有的集合遍历的操作,避免了我们每次需要使用集合内部元素时都需要从头开始遍历的操作。
使用例子:
public class Test09 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("张三");
list.add("张三丰");
list.add("张麻子");
list.add("李二牛");
list.add("神里凌华");
list.add("智慧草神");
list.stream()
//.filter(item->item.startsWith("张"))
.filter(item->item.length()==4)
.forEach(item-> System.out.println(item));
LongStream longStream =LongStream.rangeClosed(1,10);
longStream.forEach(System.out::println);
}
}
4.1Stream流的工作原理
我们所使用的产品 ,一般都是由工厂,将原材料通过一系列的工序,一步一步加工成我们使用的产品,而Stream流就是类似与工厂的模式,其中的原料就是用于转化为Stream流的集合,而Stream流中的各个API操作就是一道道工序,最终获得我们所需要的数据。
4.2获取Stream流对象
【1】通过Collection对象的stream()方法或parallelStream()方法
【2】通过Arrays类的stream()方法
【3】通过Stream接口的of()、iterate()、generate()方法
(以上三种方式所创建的流都是串行流,第四种方式所创建的流是并行流,能够有效的处理大批量的数据)
【4】通过IntStream、LongStream、DoubleStream接口中的of、range、rangeClosed方法
4.3Stream流中常见的API
常见API可以分为中间操作和终止操作
中间操作并不会结束Stream流,中间操作的返回值仍是Stream流
终止操作会结束Stream流,有些操作会返回其他数据类型,有些则不会有返回值,但是都会结束原有的Stream流
常见的中间操作有:
【1】filter:筛选操作:可以根据用户需求对数据进行筛选,得到所需数据
【2】map:转化元素或提取元素,并将其放入流中,例如:将Student对象中的姓名提取出来,形成一个只包含姓名的流
【3】sorted:排序,将流中元素按照指定排序规则进行排序
【4】distinct:去重
常见的终止操作有:
【1】foreach:遍历
【2】match(包括三种noneMatch、anyMatch、allMatch):用来判断是否含有符合条件的元素,其返回值都是布尔值
【3】find(包括findFirst、findAll):获取符合条件的元素。
【4】reduce:规约,将一个流中的多个值缩减成一个值,能够实现对集合的求和求积等操作
【5】max、min、count:取最大、取最小、计数
综合例子:
交易员实体类:
public class Trader {
private final String name;
private final String city;
public Trader(String name, String city) {
this.name = name;
this.city = city;
}
public String getName() {
return name;
}
public String getCity() {
return city;
}
@Override
public String toString() {
return "Trader{" +
"name='" + name + '\'' +
", city='" + city + '\'' +
'}';
}
}
交易类:
public class Transaction {
private final Trader trader;
private final int year;
private final int value;
public Transaction(Trader trader, int year, int value){
this.trader = trader;
this.year = year;
this.value = value;
}
public Trader getTrader(){
return this.trader;
}
public int getYear(){
return this.year;
}
public int getValue(){
return this.value;
}
@Override
public String toString(){
return "{" + this.trader + ", " +
"year: "+this.year+", " +
"value:" + this.value +"}";
}
}
实现类:
public class Action {
public static void main(String[] args) {
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)
);
// (1) 找出2011年发生的所有交易,并按交易额排序(从低到高)[filter\sorted\foreach]。
System.out.println("(1) 找出2011年发生的所有交易,并按交易额排序(从低到高):");
transactions.stream()
.filter(transaction->transaction.getYear()==2011)
.sorted(Comparator.comparingInt(t->t.getValue()))
.forEach(System.out::println);
// (2) 交易员都在哪些不同的城市工作过?[map\distinct(去重)\collect]
System.out.println("(2) 交易员都在哪些不同的城市工作过:");
List<String> collect = transactions.stream()
.map(transaction -> transaction.getTrader().getCity())
.distinct()
.collect(Collectors.toList());
System.out.println(collect);
// (3) 查找所有来自于剑桥的交易员,并按姓名排序[filter\map\distinct\sorted]。
System.out.println("(3) 查找所有来自于剑桥的交易员,并按姓名排序。");
transactions.stream()
.filter(transaction->transaction.getTrader().getCity()=="Cambridge")
.map(transaction -> transaction.getTrader().getName())
.distinct()
.sorted(String::compareTo)
.forEach(System.out::println);
// (4) 返回所有交易员的姓名字符串,按字母顺序排序。[map\distinct\sorted]
System.out.println("(4) 返回所有交易员的姓名字符串,按字母顺序排序。");
transactions.stream()
.map(transaction -> transaction.getTrader().getName())
.distinct()
.sorted(String::compareTo)
.forEach(System.out::println);
// (5) 有没有交易员是在米兰工作的?[anyMatch]
System.out.println("(5) 有没有交易员是在米兰工作的?");
boolean b = transactions.stream()
.anyMatch(transaction -> transaction.getTrader().getCity() == "Milan");
System.out.println(b);
// (6) 打印生活在剑桥的交易员的所有交易额。[map]
System.out.println("(6) 打印生活在剑桥的交易员的所有交易额。");
transactions.stream()
.filter(transaction->transaction.getTrader().getCity()=="Cambridge")
.map(transaction -> transaction.getValue())
.forEach(System.out::println);
// (7) 所有交易中,最高的交易额是多少?[max]
System.out.println("(7) 所有交易中,最高的交易额是多少?");
Optional<Transaction> max = transactions.stream().max(Comparator.comparingInt(t1 -> t1.getValue()));
System.out.println(max.get().getValue());
// (8) 找到交易额最小的交易。[min]
System.out.println("(8) 找到交易额最小的交易。");
Optional<Transaction> min = transactions.stream().min(Comparator.comparingInt(t1 -> t1.getValue()));
System.out.println(min.get().getValue());
}
}
5.新增的时间日期类
LocalDate: 表示日期类。yyyy-MM-dd
LocalTime: 表示时间类。 HH:mm:ss
LocalDateTime: 表示日期时间类 yyyy-MM-dd t HH:mm:ss sss
DatetimeFormatter:日期时间格式转换类。
Instant: 时间戳类。
Duration: 用于计算两个日期类
public class Test02 {
public static void main(String[] args) {
/*当前的日期,只包含年月日,且默认格式为yyyy-MM-dd*/
LocalDate now = LocalDate.now();
System.out.println(now);
/*当前的时间,包含时分秒 纳秒*/
LocalTime now1 = LocalTime.now();
System.out.println(now1);
/*当前日期时间,包含年月日时分秒纳秒*/
LocalDateTime now2 = LocalDateTime.now();
System.out.println(now2);
/*指定日期格式*/
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
/*将字符串转化为指定日期格式*/
LocalDate parse = LocalDate.parse("1999-07-19", dateTimeFormatter);
System.out.println(parse);
}
}