java.lang.Runnable
java.util.concurrent.Callable
java.security.PrivilegedAction
java.util.Comparator
java.io.FileFilter
java.nio.file.PathMatcher
java.lang.reflect.InvocationHandler
java.beans.PropertyChangeListener
java.awt.event.ActionListener
javax.swing.event.ChangeListener
/**
* Function:apply方法,输入参数并返回结果,
* Funcation第一个参数是apply的入参,第二个参数是apply的返回值
*/
Function<Integer, String> function = new Function<>() {
@Override
public String apply(Integer integer) {
return "数字是:"+integer;
}
};
String apply = function.apply(2);
System.out.println(apply);//数字是:2
/**
* Supplier:get方法,不输入参数并返回结果
* Supplier的参数是get方法的返回值
*/
Supplier<String> supplier = new Supplier<>() {
@Override
public String get() {
return "hahaha";
}
};
System.out.println(supplier.get());//hahaha
/**
* Consumer:accept方法,输入一个参数,没有返回值
* Consumer的参数是accept方法的参数
*/
Consumer<String> consumer = new Consumer<>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
consumer.accept("哈哈哈");//哈哈哈
/**
* Predicate:test方法,输出一个参数,返回值是布尔类型
* Predicate的参数是test方法的参数,用户做断言,判读的
*/
Predicate<String> predicate = new Predicate<>() {
@Override
public boolean test(String s) {
if(s != null && !s.trim().equals("")) {
return true;
}
return false;
}
};
System.out.println(predicate.test(null));//false
======一般写法
public class MyRunnable implements Runnable {
public void run() {
System.out.println("This is a named inner class running in a thread.");
}
}
Thread thread = new Thread(new MyRunnable());
thread.start();
======匿名内部类写法
new Thread(new Runnable() {
public void run() {
System.out.println("This is an anonymous inner class running in a thread.");
}
}).start();
<函数式接口> <变量名> = (参数1,参数2…) -> {
//方法体
}
(参数1,参数2…)表示参数列表;->表示连接符;{}内部是方法体
1、=右边的类型会根据左边的函数式接口类型自动推断;
2、如果形参列表为空,只需保留();
3、如果形参只有1个,()可以省略,只需要参数的名称即可;
4、如果执行语句只有1句,且无返回值,{}可以省略,若有返回值,则若想省去{},则必须同时省略return,且执行语句也保证只有1句;
5、形参列表的数据类型会自动推断;
6、lambda不会生成一个单独的内部类文件;
7、lambda表达式若访问了局部变量,则局部变量必须是final的,若是局部变量没有加final关键字,系统会自动添加,此后在修改该局部变量,会报错;
public interface MyInterface{
int sum(int num1,int num2);
}
public class MyInterfaceImpl implements MyInterface{
@Override
public int sum(int num1, int num2) {
return num1+num2;
}
}
public static void main(String[] args) {
MyInterfaceImpl mf = new MyInterfaceImpl();
System.out.println(mf.sum(10, 20));
}
public static void main(String[] args) {
//这部分可以简写成Lambda表达式
MyInterface mf = new MyInterface() {
@Override
public int sum(int num1, int num2) {
return num1+num2;
}
};
System.out.println(mf.sum(10, 20));
}
MyInterface mf = (int num1, int num2)->{
return num1+num2;
};
MyInterface mf = num1->num1+10;
MyInterface mf = (num1, num2)->num1+num2;
public interface MyInterface{
void print(String str);
}
/*匿名内部类写法*/
MyInterface mi = new MyInterface{
@Override
void print(String str){
System.out.println(str);
};
}
/*Lambda常规写法*/
MyInterface mi = (String str)->{
System.out.println(str);
};
/*Lambda简写*/
MyInterface mi2 = str->System.out.println(str);
public interface MyInterface{
void test();
}
/*匿名内部类写法*/
MyInterface mi = new MyInterface{
@Override
void test(){
System.out.println("123456");
};
}
//Lambda常规写法
MyInterface mi = ()->{
System.out.println("123456");
};
//简写
MyInterface mi2 = ()-> System.out.println("123456");
public class Test {
public static void main(String[] args) {
final int i = 9;
MyInterface mf = (num1,num2)->{
System.out.println(i);
return num1+num2;
};
}
}
类名::new
,是对构造方法的引用//Person类
public class Person {
private int id;
private String name;
public Person(int id, String name) {
this.id = id;
this.name = name;
}
public Person() {
}
}
//创建Person对象的函数式接口
public interface PersonFactory{
Person creatPerson(int id,String name);
}
//使用匿名内部类创建
public static void main(String[] args) {
PersonFactory factory = new PersonFactory() {
@Override
public Person creatPerson(int id, String name) {
return new Person(id,name);
}
};
}
//Lambda简写
PersonFactory factory = (id,name)->new Person(id,name);
//Lambda简写2
PersonFactory factory = Person::new;
类名::静态方法名
,相当于是函数式接口调了一个别人已经写好的静态方法,就是一个中介//函数式接口
public interface PersonFactory{
int parse(String str);
}
//匿名内部类的写法
PersonFactory pf = new PersonFactory() {
@Override
public int parse(String str) {
return Integer.parseInt(str);
}
};
//Lambda常规写法
PersonFactory factory = str->Integer.parseInt(str);
//Lambda静态方法引用
PersonFactory fp = Integer::parseInt;
对象::实例方法名
,函数式接口调用了一个别人写好的实例方法,和静态方法引用不同的是,调用的方法一个是静态方法,一个是实例方法//Java8的函数式接口Function
@FunctionalInterface
public interface Function<T,R>{
R apply(T t);
}
//匿名内部类的方式
public static void main(String[] args) {
String str = "hello,world";
Function<String,Boolean> func1 = new Function<String, Boolean>() {
@Override
public Boolean apply(String t) {
return t.endsWith("world");
}
};
boolean test = test(func1,str);
System.out.println(test);
}
public static boolean test(Function<String,Boolean> f,String str){
return f.apply(str);
}
//Lambda表达式
public static void main(String[] args) {
String str = "hello,world";
Function<String,Boolean> func1 = t->str.endsWith("world");
boolean test = test(func1,str);
System.out.println(test);
}
public static boolean test(Function<String,Boolean> f,String str){
return f.apply(str);
}
//Lambda表达式简写
public static void main(String[] args) {
String str = "hello,world";
Function<String,Boolean> func1 = str::endsWith;
boolean test = test(func1,str);
System.out.println(test);
}
public static boolean test(Function<String,Boolean> f,String str){
return f.apply(str);
}
类名::实例方法名
,函数式接口中形参的第一个参数是实例方法的调用方public Class Student{
private String name;
public Student(){
}
public Student(String name){
this.name = name;
}
public String getName(){
return this.name;
}
public String setName(String name){
this.name = name;
}
}
public class Test{
public static void main(String[] args) {
//匿名内部类写法
Function<Student,String> fu = new Function<>(){
@Override
public String apply(Student student){
return stduent.getName();
}
}
//Lambda表达式写法
Function<Student,String> fu = student -> stduent.getName();
//Lambda表达式简写
Function<Student,String> fu = Student::getName();
}
}
//方式1,用Stream.of(),参数是可变参数,他的底层是Arrays.stream(可变参数)
Stream<Integer> integerStream = Stream.of(1,2,3);
//方式2,Arrays.stream(int数组)
IntStream stream = Arrays.stream(new int[]{1, 2, 3});
//Stream和IntStream是同级的,都是BaseStream的子类,IntStream有更多的方法,他的参数只能是int类型的,Stream任意类型
//集合对象.stream(),list和set就直接用对象.stream(),
List<String> list = Arrays.asList("你", "好", "吗");//将可变参数转为集合
Stream<String> stream1 = list.stream();
//map只能将entrySet转为stream,Entry的第一个参数是key,第二个参数是value
Map<String, Integer> map = new HashMap<>();
map.put("apple", 1);
map.put("banana", 2);
map.put("orange", 3);
// 将Map转换为Stream
Stream<Map.Entry<String, Integer>> stream2 = map.entrySet().stream();
先准备一个简单的员工类
public class Employee {
private String name;//姓名
private Integer age;//年龄
private BigDecimal salary;//工资
public String getName() {
return name;
}
//因为要链式编程,所以将默认的void改成了对象
public Employee setName(String name) {
this.name = name;
return this;
}
public Integer getAge() {
return age;
}
public Employee setAge(Integer age) {
this.age = age;
return this;
}
public BigDecimal getSalary() {
return salary;
}
public Employee setSalary(BigDecimal salary) {
this.salary = salary;
return this;
}
public Employee() {}
public Employee(String name, int age, BigDecimal salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
@Override
public String toString() {
return "姓名:" + name + " 年龄:" + age + " 工资:" + salary;
}
}
List<Employee> list = Arrays.asList(
new Employee("哈哈哈",19,new BigDecimal("8000")),
new Employee("嘻嘻嘻",20,new BigDecimal("9000")),
new Employee("呵呵呵",19,new BigDecimal("12000")),
new Employee("嘿嘿嘿",24,new BigDecimal("10000")));
//找出集合中,年龄大于20,工资大于10000的人(传统写法)
for (Employee employee : list) {
if(employee.getAge() > 20 && employee.getSalary().compareTo(new BigDecimal("10000")) > 0){
System.out.println(employee);
}
}
//过滤出年龄大于20并且工资大于10000的员工的信息(filter写法)
Stream<Employee> es = list.stream().filter(new Predicate<Employee>() {
@Override
//test的结果为true表示满足,反之不满足
public boolean test(Employee employee) {
//这个打印语句是不会执行的,因为filter是一个中间操作,只有遇到终端操作时才会执行
System.out.println(employee);
return employee.getAge() >= 20 && employee.getSalary().compareTo(BigDecimal.valueOf(10000)) > 0;
}
});
//要想打印出过滤后的结果,得执行终端操作,使用forEach遍历打印。
es.forEach(System.out::println);
//取前两个
Stream<Employee> limit = list.stream().limit(2);
//limit同样是一个中间操作,所以要使用终端操作才能显示结果
limit.forEach(System.out::println);
//需求就是只返回员工的姓名
Stream<String> map = list.stream().map(new Function<Employee, String>() {//第一个是传进来的参数是方法的形参,第二个传进来的参数是返回值类型
@Override
public String apply(Employee employee) {
//返回的结果就是你想要得到的结果
return employee.getName();
}
});
//map同样是一个中间操作
map.forEach(System.out::println);
//按照年龄降序排列
list.stream().sorted(new Comparator<Employee>() {
@Override
public int compare(Employee o1, Employee o2) {
return o2.getAge()-o1.getAge();
}
}).forEach(System.out::println);
//转List
List<Employee> collect = list.stream().collect(Collectors.toList());
//转Set
Set<Employee> collect1 = list.stream().collect(Collectors.toSet());
//转Map,匿名内部类写法,键是姓名,值是Employee对象
Map<String, Object> collect2 = list.stream().collect(Collectors.toMap(new Function<Employee, String>() {
@Override
public String apply(Employee employee) {
return employee.getName();
}
}, new Function<Employee, Object>() {
@Override
public Object apply(Employee employee) {
return employee;
}
}));
//转Map简单lambda写法,e ->e 的变量任意,两边相同就可,其实就是传什么参数进来,返回了什么参数
Map<String, Object> collect2 = list.stream().collect(Collectors.toMap(Employee::getName,e ->e));
//转LinkedList,没有直接提供方法的Collection接口下的集合都可以用toCollection
LinkedList<Employee> collect3 = list.stream().collect(Collectors.toCollection(new Supplier<LinkedList<Employee>>() {
@Override
public LinkedList<Employee> get() {
return new LinkedList<>(); //转什么就返回一个什么
}
}));
//求个数
Long collect4 = list.stream().collect(Collectors.counting());
//按照年龄分组
Map<Integer, List<Employee>> collect5 = list.stream().collect(Collectors.groupingBy(new Function<Employee, Integer>() {
@Override
public Integer apply(Employee employee) {
return employee.getAge();
}
}));
//求年龄的平均值:averagingInt、averagingDouble、averagingLong
Double collect6 = list.stream().collect(Collectors.averagingInt(new ToIntFunction<Employee3>() {
@Override
public int applyAsInt(Employee3 employee3) {
return employee3.getAge();
}
}));
//用的不多,(这个例子就是所有员工的年龄相加)
Integer collect8 = list.stream().collect(Collectors.reducing(0, new Function<Employee3, Integer>() {
@Override
public Integer apply(Employee3 employee3) {
return employee3.getAge();
}
},
new BinaryOperator<Integer>() {
@Override
public Integer apply(Integer integer, Integer integer2) {
return integer + integer2;
}
}));
System.out.println(collect8);
//字符串拼接,只能用于实现了CharSequence的泛型
List<String> list = Arrays.asList("A", "B", "C", "D");
//无参,就是将所有内容连接起来
String result = list.stream().collect(Collectors.joining());
System.out.println(result); // 输出:ABCD
//一个参数:连接符
String result1 = list.stream().collect(Collectors.joining("-"));
System.out.println(result1); // 输出:A-B-C-D
//三个参数:连接符,前缀,后缀
String result2 = list.stream().collect(Collectors.joining("-", "[", "]"));
System.out.println(result2); // 输出:[A-B-C-D]
String s = "123";
//把对象装进Optional容器,如果对象是null,则直接抛出空指针异常
Optional<String> s2 = Optional.of(s);
//把对象装进Optional容器,如果对象是null也不报错
Optional<String> s1 = Optional.ofNullable(s);
//从Optional中获取对象,如果对象为空,抛出NoSuchElementException异常
System.out.println(s1.get());
//判断optional中存放的对象是否为null,不是空就返回true,是空就返回false
System.out.println(s1.isPresent());
//先判断,再取
if(s1.isPresent()){
System.out.println(s1.get());
}
//获取optional中的对象,如果是null,可以设置默认值
System.out.println(s1.orElse("对象是null"));
//获取optional中的对象,也可以设置默认值,但是可以做更多的是,可以优化lambda表达式
s1.orElseGet(new Supplier<String>() {
@Override
public String get() {
//此处还能写其他的业务代码
System.out.println("hahahah");
//如果是null,可以返回默认值
return "对象是null";
}
});
//创建一个空的Optional实例
Optional<Object> empty = Optional.empty();
System.out.println(empty);//Optional.empty
//map:改变把Optional对象的值,如果原对象值为null,改变不了
Optional<Object> o = s2.map(new Function<String, Object>() {
@Override
public Object apply(String s) {
return "456";
}
});
System.out.println(o.get());//456
//flatMap:和map一样,但是返回值必须是Optional
Optional<Object> o = s2.flatMap(new Function<String, Optional<?>>() {
@Override
public Optional<?> apply(String s) {
return Optional.of(s);
}
});
//获取当前的日期
LocalDate now= LocalDate.now();
//获取当前日期+时间
LocalDateTime now1 = LocalDateTime.now();
//获取时间
LocalTime now2 = LocalTime.now();
System.out.println(now);//2024-02-04
System.out.println(now1);//2024-02-04T01:04:12.585509300
System.out.println(now2);//01:04:12.585509300
//localdate日期转换
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-DD HH:mm:ss");
System.out.println(df.format(now1));//2024-02-35 01:04:12只能对now1,只有now1中包含年月日时分秒
//时区类,获取所有的ZoneId
ZoneId.getAvailableZoneIds().forEach(System.out::println);
//通过字符串时区获取ZoneId
ZoneId id = ZoneId.of("Asia/Chongqing");
//获取指定时区的时间
LocalDateTime now3 = LocalDateTime.now(id);
System.out.println(now3);//2024-02-04T01:04:12.597477100