Lambda表达式是一种特殊的匿名内部类,语法更简洁。它允许把函数作为一个方法的参数,将代码像数据一样传递。但是Lambda不会生成单独的内部类文件。
Lambda表达式的基本语法:
<函数式接口> <变量名> = (参数1, 参数2)-> {
// 方法体
};
如果形参列表为空,只用保留();
如果形参个数只有一个,()可以省略,只需要参数的名称;
形参列表的数据类型会自动推断;
如果执行语句只有一条,当没有返回值时,{}可以省略;当有返回值时,若是想省去{},则必须同时省略return。
demo展示:
package test1;
public class Demo1 {
public static void main(String[] args) {
// 匿名内部类
Runnable runnable1 = new Runnable() {
@Override
public void run() {
System.out.println("匿名内部类");
}
};
new Thread(runnable1).start();
// Lambda
Runnable runnable2 = ()-> System.out.println("Lambda ...");
new Thread(runnable2).start();
// Lambda
new Thread(()-> System.out.println("Lambda ...")).start();
}
}
demo2:
package test2;
import java.util.Comparator;
import java.util.TreeSet;
public class demo {
public static void main(String[] args) {
// 匿名内部类
Comparator<String> com = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.length() - o2.length();
}
};
TreeSet<String> treeSet = new TreeSet<>(com);
// Lambda
Comparator<String> com1 = (String o1, String o2)-> {
return o1.length() - o2.length();
};
TreeSet<String> treeSet1 = new TreeSet<>(com1);
// Lambda
Comparator<String> com2 = (o1, o2)-> o1.length() - o2.length();
TreeSet<String> treeSet2 = new TreeSet<>(com2);
}
}
函数式接口:如果一个接口只有一个抽象方法,则该接口称为函数式接口,可使用Lambda表达式。
demo如下:
函数式接口:
package test1;
/**
* 函数式接口
* 可通过FunctionalInterface注解验证是否是函数式接口
*
*/
@FunctionalInterface
public interface Usb {
void service();
}
主方法:
package test1;
public class test {
public static void main(String[] args) {
Usb mouse = new Usb() {
@Override
public void service() {
System.out.println("mouse...");
}
};
run(mouse);
// Lambda
Usb fan = ()-> System.out.println("fan...");
run(fan);
}
public static void run(Usb usb) {
usb.service();
}
}
demo1 消费型接口:
package test2;
import java.util.function.Consumer;
public class ConsumerTest {
public static void main(String[] args) {
// 匿名内部类
java.util.function.Consumer<Double> consumer = new java.util.function.Consumer<Double>() {
@Override
public void accept(Double aDouble) {
System.out.println("消费:" + aDouble);
}
};
// Lambda
java.util.function.Consumer<Double> consumer1 = aDouble-> System.out.println("消费:" + aDouble);
happy(consumer1, 100.0);
// 更进一步
happy(aDouble-> System.out.println("消费:" + aDouble), 1000.0);
}
// 消费型接口
public static void happy(java.util.function.Consumer<Double> consumer, Double money) {
consumer.accept(money);
}
}
demo2供给型接口:
package test2;
import java.util.Random;
import java.util.function.Supplier;
public class SupplierTest {
public static void main(String[] args) {
// 匿名内部类
Supplier<Integer> supplier = new Supplier<Integer>() {
@Override
public Integer get() {
return new Random().nextInt();
}
};
// Lambda
Supplier<Integer> supplier1 = ()-> new Random().nextInt();
getNums(supplier1, 100);
// 进一步简化
getNums(()-> new Random().nextInt(), 100);
}
public static int[] getNums(Supplier<Integer> supplier, int count) {
int[] arrays = new int[count];
for (int i = 0; i < count; i++) {
arrays[i] = supplier.get();
}
return arrays;
}
}
demo3函数式接口:
package test2;
import java.util.function.Function;
public class FunctionTest {
public static void main(String[] args) {
Function<String ,String> function = new Function<String, String>() {
@Override
public String apply(String s) {
return s.substring(0, s.length() - 2);
}
};
// Lambda
Function<String ,String> function1 = s->s.substring(0, s.length() - 2);
handleFunction(function1, "1234567890");
// 更进一步
handleFunction(s->s.substring(0, s.length() - 2), "1234567890");
}
public static String handleFunction(Function<String, String> function, String str) {
return function.apply(str);
}
}
demo4断言式接口:
package test2;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
public class PredicateTest {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
Predicate<String> predicate = new Predicate<String>() {
@Override
public boolean test(String s) {
if (s.length() < 10) {
return true;
}
return false;
}
};
// Lambda
Predicate<String> predicate1 = s-> {
if (s.length() < 10) {
return true;
}
return false;
};
// Lambda
Predicate<String> predicate2 = s->(s.length() < 10);
fileNames(predicate, list);
// 更进一步
fileNames(s->(s.length() < 8), list);
}
public static List<String> fileNames(Predicate<String> predicate, List<String> list) {
List<String> resultList = new ArrayList<>();
for (String s : list) {
if (predicate.test(s)) {
resultList.add(s);
}
}
return resultList;
}
}
方法引用:是Lambda表达式的一种简写形式,如果Lambd表达式方法体中只式调用一个特定的已经存在的方法,则可以使用方法引用。
常见形式:
对象::实例方法
类::静态方法
类::实例方法
类::new
demo1:
package test3;
import java.util.Comparator;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
public class demo {
public static void main(String[] args) {
// 对象::实例方法
Consumer<String> consumer = s->System.out.println(s);
consumer.accept("haha");
// 上述操作中,后面的方法类型与前面一致,都是有参数无返回值,因此可简写成如下方式:
Consumer<String> consumer2 = System.out::println;
consumer2.accept("xixi");
// 类::静态方法
Comparator<Integer> comparator = (t1, t2)->Integer.compare(t1, t2);
//可写成如下方式:
Comparator<Integer> comparator1 = Integer::compare;
// 类::实例方法
Function<String, String> function = e->e.toString();
// 可写成如下方式:
Function<String, String> function1 = String::toString;
//类::new
Supplier<Employee> supplier = ()->new Employee();
Supplier<Employee> supplier1 = Employee::new;
}
}
Stream中保存对集合或者数组数据的操作,和集合类似,但是集合中保存的是数据。类似于工厂的流水线。
特点:
1. 自己不存储元素,只保存操作。
2. 不会改变源对象,相反,会返回一个持有结果的新Stream。
3. Stream的操作是延迟执行的,会等到需要结果的时候才执行。
使用步骤:
1. 创建流的方法
通过Collection对象的stream()或者parallelStream()方法
通过Arrays类的stream()方法
通过Stream接口的of(),iterate(),generate()方法
通过IntStream,LongStream,DoubleStream接口中的if,range,rangeColsed方法。
demo:
package test4;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
import java.util.stream.IntStream;
import java.util.stream.Stream;
public class Demo {
public static void main(String[] args) {
// 1. 通过Collection对象的stream()或者parallelStream()方法。
ArrayList<String> arrayList = new ArrayList<>();
arrayList.add("xixi");
arrayList.add("haha");
arrayList.add("lala");
// 串行流
Stream<String> stringStream = arrayList.stream();
// 遍历
//stringStream.forEach(s->System.out.println(s));
stringStream.forEach(System.out::println);
System.out.println("***********************************");
// 并行流
Stream<String> stringStream1 = arrayList.parallelStream();
//stringStream1.forEach(s->System.out.println(s));
stringStream1.forEach(System.out::println);
System.out.println("***********************************");
// 2. 通过Arrays类的stream()方法。
String[] array = {"111", "222", "333"};
Stream<String> streamArrays = Arrays.stream(array);
streamArrays.forEach(System.out::println);
System.out.println("***********************************");
// 3. 通过Stream接口的of(),iterate(),generate()方法。
// 将数组变成流
Stream<Integer> streamOf = Stream.of(1,2,3,4,5,6,7,8,9,10);
streamOf.forEach(System.out::println);
System.out.println("***********************************");
// 迭代流
Stream<Integer> streamIterate = Stream.iterate(0, x->x + 2); // 返回从0开始,每次递增2的数组
streamIterate.limit(10).forEach(System.out::println); // 取出其中的10个数据
System.out.println("***********************************");
// 生成流
Stream<Integer> streamGenerate = Stream.generate(()->new Random().nextInt(100)); // 返回100以内的随机数组成的数组
streamGenerate.limit(10).forEach(System.out::println);
// 4. 通过IntStream, LongStream,DoubleStream接口中的of,range,rangeColsed方法。
System.out.println("***********************************");
IntStream intStream = IntStream.of(10, 50, 90);
intStream.forEach(System.out::println);
System.out.println("***********************************");
// range与rangeColsed的区别是range是非闭合,一rangeColsed是闭合
IntStream.range(0,10).forEach(System.out::println);
System.out.println("***********************************");
IntStream.rangeClosed(0, 10).forEach(System.out::println);
}
}
2. 中间操作
在一个或者多个步骤中,将初始的Stream转化到另一个Stream的中间操作。
常用操作有:filter, limit,skip,distinct,sorted,map,parallel。
demo:
package test5;
import java.util.ArrayList;
public class Demo {
public static void main(String[] args) {
ArrayList<Employee> arrayList = new ArrayList<>();
arrayList.add(new Employee("wangwang1", 15000));
arrayList.add(new Employee("wangwang2", 11000));
arrayList.add(new Employee("wangwang3", 19000));
// arrayList.add(new Employee("wangwang3", 19000));
arrayList.add(new Employee("wangwang4", 14000));
// 中间操作 filter(过滤), limit(限制),skip(跳过),distinct(去重),sorted(排序),map,parallel。
// filter过滤
System.out.println("********************filter******************");
arrayList.stream().filter(e->e.getMoney() > 16000).forEach(System.out::println);
System.out.println("********************limit******************");
arrayList.stream().limit(2).forEach(System.out::println);
System.out.println("********************skip******************");
arrayList.stream().skip(1).forEach(System.out::println);
System.out.println("********************distinct******************"); // 去重的依据是hashcode与euqal,因此Employee要重写这两个方法
arrayList.stream().distinct().forEach(System.out::println);
System.out.println("********************sorted******************");
// 从小到大排列
arrayList.stream().sorted((o1, o2)->Integer.compare(o1.getMoney(), o2.getMoney())).forEach(System.out::println);
System.out.println("********************map******************");
System.out.println("********************parallel******************");
}
}
3.终止操作
使用一个终止操作来产生一个结果,该操作会强制它之前的操作立即执行,在这之后,Stream就不能用了。终止操作有forEach,min,max,count,reduce,collect。
package test6;
import test5.Employee;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
public class Demo {
public static void main(String[] args) {
ArrayList<Employee> arrayList = new ArrayList<>();
arrayList.add(new Employee("wangwang1", 15000));
arrayList.add(new Employee("wangwang2", 11000));
arrayList.add(new Employee("wangwang3", 19000));
arrayList.add(new Employee("wangwang4", 14000));
System.out.println("*************for Each**************");
arrayList.stream()
.filter(e->e.getMoney()>11000).forEach(System.out::println);
System.out.println("*************min**************");
System.out.println(arrayList.stream()
.min((e1, e2)->Double.compare(e1.getMoney(), e2.getMoney())).get());
System.out.println("*************max**************");
System.out.println(arrayList.stream()
.max((e1, e2)->Double.compare(e1.getMoney(), e2.getMoney())).get());
System.out.println("*************count**************");
System.out.println(arrayList.stream()
.count());
System.out.println("*************reduce**************");
Optional<Integer> sum = arrayList.stream()
.map(e->e.getMoney())
.reduce((x, y)->x+y);
System.out.println(sum.get());
System.out.println("*************collect**************");
List<String> list = arrayList.stream()
.map(e->e.getName())
.collect(Collectors.toList());
for (String l : list) {
System.out.println(l);
}
}
}
新时间API(java 8开始)与修旧时间api转换:
package test7;
import javafx.util.converter.LocalDateStringConverter;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.Set;
public class demo {
public static void main(String[] args) {
System.out.println("**********LocalDateTime**************");
LocalDateTime localDateTime0 = LocalDateTime.now();
LocalDateTime localDateTime1 = LocalDateTime.of(2021,8,27,8,14,39);
System.out.println(localDateTime0);
System.out.println(localDateTime0.getYear());
System.out.println(localDateTime1);
// 添加天数
LocalDateTime localDateTime2 = localDateTime0.plusDays(10);
System.out.println(localDateTime2);
// 减少天数
LocalDateTime localDateTime3 = localDateTime0.minusDays(5);
System.out.println(localDateTime3);
System.out.println("**********Instant:时间戳**************");
Instant instant = Instant.now();
System.out.println(instant.toString());
// 从1970年到现在的时间
System.out.println(instant.toEpochMilli());
System.out.println(System.currentTimeMillis());
// 添加or减少时间
Instant instant1 = instant.plusSeconds(5);
System.out.println(Duration.between(instant, instant1).toString());
System.out.println("**********ZoneId:时区**************");
Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
for (String s : availableZoneIds) { // 打印所有时区
System.out.println(s);
}
// 当前的时区
System.out.println(ZoneId.systemDefault().toString());
System.out.println("**********新旧时间转换**************");
System.out.println("Date-->Instant-->LocalDateTime");
Date date = new Date();
System.out.println(date);
Instant instant2 = date.toInstant();
System.out.println(instant2);
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant2, ZoneId.systemDefault());
System.out.println(localDateTime);
System.out.println("LocalDateTime-->Instant-->Date");
Instant instant3 = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
System.out.println(instant3);
Date date1 = Date.from(instant3);
System.out.println(date1);
}
}
时间格式化:
package test7;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class demo2 {
public static void main(String[] args) {
// 创建
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 时间转为字符串
String format = dateTimeFormatter.format(LocalDateTime.now());
System.out.println(format);
// 字符串转为时间
LocalDateTime localDateTime = LocalDateTime.parse("2019-07-15 07:08:09", dateTimeFormatter);
System.out.println(localDateTime);
}
}