jdk8新特性

本文详细介绍了Java8中的新特性,包括接口中的默认方法、Lambda表达式的使用,以及函数式接口的概念。Lambda表达式提供了更简洁的代码写法,函数式接口允许只有一个抽象方法的接口。文章还深入探讨了Stream流的用法,如转换集合、计算求和、查找最大值和最小值、过滤和分页排序等,展示了Stream流在处理集合操作时的强大功能。此外,还提到了Optional类在避免空指针异常方面的应用以及方法引入的几种形式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

jdk8新特性

接口中生命的默认方法为普通方法

接口中不仅可以定义静态方法、抽象方法,还可以使用default关键字来定义普通方法也叫默认方法(可以有方法实现)

Lambda表达式

为什么使用lambda表达式

为了能够更精简的使用匿名内部类,实例:

package tengfei.lambdaTest;

public interface OrderService {
    void get();
}
package tengfei.lambdaTest;

public class MainTest {
    public static void main(String[] args) {
        /*
        * 我们知道接口是不能通过new创建实例对象的
        * 1、使用接口的实现类(子类)
        * 2、使用匿名内部类
        * */
        OrderService orderService = new OrderService() {
            @Override
            public void get() {
                System.out.println("--_--");
            }
        };
        orderService.get();

        new OrderService() {
            @Override
            public void get() {
                System.out.println("匿名内部类,相当于OrderService接口的实现类,也就是子类");
            }
        }.get();

        //上面两种写法一样
    }
}

函数式接口

函数式接口特性:

  • 使用@FunctionalInterface注解修饰
  • 接口中只定义一个抽象方法,但是可以定义多个默认方法(default)
  • 可以重写Object类中的方法
package tengfei.functionalInterfaceTest;
@FunctionalInterface
public interface MyFunctionalInterface {
    void add();
    
    default void get(){
        System.out.println("可以定义默认方法");
    }
    
    //可以重写Object中的方法
    String toString();
}

lambda基础语法

() -> {}

参数列表 -> 方法实现体

精简写法

package tengfei.functionalInterfaceTest;

public class MainTest {
    public static void main(String[] args) {
        /*
        * lambda简化写法(无参)
        * 第一步、第二步、第三步
        * */
        MyFunctionalInterface myFunctionalInterface = ()->{
            System.out.println("精简第一步");
        };
        myFunctionalInterface.add();
        //当方法体只有一条语句时
        MyFunctionalInterface myFunctionalInterface1 = ()-> System.out.println("精简第二步");
        myFunctionalInterface1.add();

        ((MyFunctionalInterface)()-> System.out.println("精简第三步")).add();

        /*
        * lambda简化语法(有参)
        * */
        //第一步
        MyFunctionalInterfaceReturn myFunctionalInterfaceReturn = (i,j)->{return i+"--"+j;};
        myFunctionalInterfaceReturn.get(1,2);

        //第二步
        MyFunctionalInterfaceReturn myFunctionalInterfaceReturn1 = (i, j) -> i+"--"+j;
        myFunctionalInterfaceReturn1.get(1,2);

        //第三步
        ((MyFunctionalInterfaceReturn)(i,j)->i+"--"+j).get(1,2);

    }
}

使用lambda操作集合

以下三个案例,均是在开发过程中出现lambda表达式用法的常见场景,这里目的是理解lambda的写法

遍历集合
package tengfei.operateListByLambda;

import java.util.ArrayList;

public class MainTest {
    public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<>();
        arrayList.add("ma");
        arrayList.add("teng");
        arrayList.add("fei");

        arrayList.forEach(str->{
            System.out.println(str);
        });

        arrayList.forEach(s -> System.out.println(s));
    }
}
集合排序
package tengfei.operateListByLambda;

import tengfei.entity.User;

import java.util.ArrayList;
import java.util.Comparator;

public class MainTest01 {
    public static void main(String[] args) {
        ArrayList<User> users = new ArrayList<>();
        users.add(new User("小虎",12));
        users.add(new User("小狗",8));
        users.add(new User("小王",24));

        users.sort(new Comparator<User>() {
            @Override
            public int compare(User o1, User o2) {
                return o1.getAge().compareTo(o2.getAge());
            }
        });

        users.sort(((o1, o2) -> o1.getAge().compareTo(o2.getAge())));

        users.forEach((user -> System.out.println(user.toString())));
    }
}
线程调用
package tengfei.operateListByLambda;

public class MainTest02 {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName());
            }
        }).start();

        //精简
        new Thread(()-> System.out.println(Thread.currentThread().getName())).start();
    }
}

Stream流

为什么要使用Stream流

  • stream流能够简洁的实现集合的遍历、过滤、排序等
  • 分类:串行流stream() 、并行流parallelStream()

Stream流将list集合转为set集合

package tengfei.Stream;

import tengfei.entity.User;

import java.util.ArrayList;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamTest {
    public static void main(String[] args) {
        ArrayList<User> users = new ArrayList<>();
        users.add(new User("李华",18));
        users.add(new User("小明",21));
        users.add(new User("张三",24));
        users.add(new User("张三",24));

        Stream<User> stream = users.stream();
        Set<User> set = stream.collect(Collectors.toSet());

        set.forEach(user -> System.out.println(user.toString()));
    }
}

//执行结果
User{name='张三', age=24}
User{name='小明', age=21}
User{name='李华', age=18}
User{name='张三', age=24}

产生疑问:

  • 为什么list转为set集合,集合中的数据没有去重?
  • Set集合底层去重的原理–》双等号和equals的区别

答:因为这里定义的User实体类没有重写equals方法,此时User实体类对象仍然使用的是Object类中的equals方法,查看源码可知,Object类中的equals方法里面使用的也是双等号,而对应引用对象User,两个具有相同的属性值通过new关键字创建的两个对象地址值不同当然equlas返回的就是true

Stream流将list集合转为map集合

package tengfei.Stream;

import tengfei.entity.User;

import java.util.ArrayList;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamTest01 {
    public static void main(String[] args) {
        ArrayList<User> users = new ArrayList<>();
        users.add(new User("李华",18));
        users.add(new User("小明",21));
        users.add(new User("张三",24));

        /*
        * 单列集合只有元素,也就是双列集合的value
        * 转为双列集合前提要指定key
        * */
        Stream<User> stream = users.stream();
        //Collectors.toMap(key,value)
        Map<String, User> map = stream.collect(Collectors.toMap(new Function<User, String>() {
            @Override
            public String apply(User user) {
                return user.getName();
            }
        }, new Function<User, User>() {
            @Override
            public User apply(User user) {
                return user;
            }
        }));

        //简化写法
        Map<String, User> userMap = stream.collect(Collectors.toMap(user -> user.getName(), user -> user));
        
    }
}

Stream流计算求和

package tengfei.Stream;

import tengfei.entity.User;

import java.util.ArrayList;
import java.util.Optional;
import java.util.function.BinaryOperator;
import java.util.stream.Stream;

public class StreamTest02 {
    public static void main(String[] args) {
        Stream<Integer> stream = Stream.of(10, 10, 20, 10);
        Optional<Integer> sum = stream.reduce(new BinaryOperator<Integer>() {
            @Override
            public Integer apply(Integer integer, Integer integer2) {
                return integer + integer2;
            }
        });
        System.out.println(sum.get());

        //计算下面三人的年龄之和
        ArrayList<User> users = new ArrayList<>();
        users.add(new User("李华",18));
        users.add(new User("小明",21));
        users.add(new User("张三",24));

        Stream<User> stream1 = users.stream();
        Optional<User> ageSum = stream1.reduce(new BinaryOperator<User>() {
            @Override
            public User apply(User user, User user2) {
                return new User("年龄之和", user.getAge() + user2.getAge());
            }
        });
        System.out.println(ageSum.get());

    }
}

Stream查找最大值和最小值

package tengfei.Stream;

import tengfei.entity.User;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Optional;
import java.util.stream.Stream;

public class StreamTest03 {
    public static void main(String[] args) {
        ArrayList<User> users = new ArrayList<>();
        users.add(new User("李华",18));
        users.add(new User("小明",21));
        users.add(new User("张三",24));

        Stream<User> stream = users.stream();
        Optional<User> max = stream.max(new Comparator<User>() {
            @Override
            public int compare(User o1, User o2) {
                return o1.getAge() - o2.getAge();
            }
        });
        System.out.println(max.get());
    }
}

Stream的Match用法

package tengfei.Stream;

import tengfei.entity.User;

import java.util.ArrayList;
import java.util.function.Predicate;
import java.util.stream.Stream;

public class MainTest04 {
    public static void main(String[] args) {
        ArrayList<User> users = new ArrayList<>();
        users.add(new User("李华",18));
        users.add(new User("小明",21));
        users.add(new User("张三",24));

        Stream<User> stream = users.stream();
        boolean b = stream.anyMatch(new Predicate<User>() {
            @Override
            public boolean test(User user) {
                return user.getAge() > 18;
            }
        });
        System.out.println(b);
    }
}

Stream的过滤器用法

package tengfei.Stream;

import tengfei.entity.User;

import java.util.ArrayList;
import java.util.function.Predicate;
import java.util.stream.Stream;

public class StreamTest05 {
    public static void main(String[] args) {
        ArrayList<User> users = new ArrayList<>();
        users.add(new User("李华",18));
        users.add(new User("李华",24));
        users.add(new User("小明",21));
        users.add(new User("张三",24));

        Stream<User> stream = users.stream();
        stream.filter(new Predicate<User>() {
            @Override
            public boolean test(User user) {
                return "李华".equals(user.getName())&&user.getAge()>18;
            }
        }).forEach(user -> System.out.println(user.toString()));
    }
}

Stream实现分页limit

package tengfei.Stream;

import tengfei.entity.User;

import java.util.ArrayList;
import java.util.stream.Stream;

public class StreamTest06 {
    public static void main(String[] args) {
        ArrayList<User> users = new ArrayList<>();
        users.add(new User("李华",18));
        users.add(new User("李华",24));
        users.add(new User("小明",21));
        users.add(new User("张三",24));

        Stream<User> stream = users.stream();
        stream.skip(1).limit(2).forEach(user -> System.out.println(user.toString()));
    }
}

Stream实现排序

package tengfei.Stream;

import tengfei.entity.User;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.stream.Stream;

public class StreamTest07 {
    public static void main(String[] args) {
        ArrayList<User> users = new ArrayList<>();
        users.add(new User("李华",18));
        users.add(new User("李华",24));
        users.add(new User("小明",21));
        users.add(new User("张三",24));

        Stream<User> stream = users.stream();
        stream.sorted(new Comparator<User>() {
            @Override
            public int compare(User o1, User o2) {
                return o1.getAge()-o2.getAge();
            }
        }).forEach(user -> System.out.println(user.toString()));
    }
}

综合案例

package tengfei.Stream;

import tengfei.entity.User;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.function.Predicate;
import java.util.stream.Stream;

public class StreamTest08 {
    public static void main(String[] args) {
        ArrayList<User> users = new ArrayList<>();
        users.add(new User("李华一",18));
        users.add(new User("李华",24));
        users.add(new User("李华明",34));
        users.add(new User("小明",21));
        users.add(new User("张三",24));

        /*
        * 年龄降序,名称包含“李华”,获取前两位
        * */
        Stream<User> stream = users.stream();
        stream.filter(new Predicate<User>() {
            @Override
            public boolean test(User user) {
                return user.getName().contains("李华");
            }
        }).sorted(new Comparator<User>() {
            @Override
            public int compare(User o1, User o2) {
                return -(o1.getAge()-o2.getAge());
            }
        }).limit(2).forEach(user -> System.out.println(user.toString()));
        //简写
        stream.filter(user -> user.getName().contains("李华"))
                .sorted((o1, o2) -> o2.getAge()-o1.getAge())
                .limit(2)
                .forEach(user -> System.out.println(user.toString()));
    }
}

方法引入

什么是方法引入

需要结合lambda表达式能够使代码更加简洁,lambda表达式的作用是为了匿名内部类更加简洁

规范:

  • 能够使用方法引入的前提:被引入的方法它的参数列表方法返回值类型 要与函数式接口定义的方法参数列表和方法返回值类型一致

方法引入之静态方法

类名::静态方法名
package tengfei.方法引入;
@FunctionalInterface
public interface MyTest {
    void get(int a);
}
package tengfei.方法引入;

public class StaticTest {
    public static void main(String[] args) {
        MyTest test = new MyTest() {
            @Override
            public void get(int a) {
                System.out.println("匿名内部类"+a);
            }
        };
        test.get(1);

        MyTest test1 = (a) -> System.out.println("lambda表达式"+a);
        test1.get(1);

        MyTest test2 = (a)-> StaticTest.staticGet(a);
        test2.get(1);

        //方法引入
        MyTest test3 = StaticTest::staticGet;
        test3.get(1);

    }
    //定义一个静态方法
    public static void staticGet(Integer a){
        System.out.println("这是一个静态方法"+a);
    }
}

方法引入之实例方法引入

new 实例对象
对象实例::实例方法
package tengfei.方法引入;

public class Test02 {
    public static void main(String[] args) {
        Test02 obj = new Test02();
        MyTest test = (a) -> obj.testGet(a);

        MyTest test1 = obj::testGet;
        test1.get(1);

    }

    //定义一个类实例方法
    public void testGet(Integer a){
        System.out.println("这是一个实例方法!"+a);
    }
}

方法引入之构造函数引入


package tengfei.方法引入;

import tengfei.entity.User;

public class Test03 {
    public static void main(String[] args) {
        MyTest test = (a)-> new User();
        test.get(1);

        MyTest test1 = User::new;
        test1.get(1);
    }
}

方法引入之对象方法引入

package tengfei.方法引入;
@FunctionalInterface
public interface MyDefaultInterface {
    void get(Test04 test04);
}
package tengfei.方法引入;

public class Test04 {
    public static void main(String[] args) {
        MyDefaultInterface myDefaultInterface = new MyDefaultInterface() {
            @Override
            public void get(Test04 test04) {
                test04.defaultMethod();
            }
        };
        myDefaultInterface.get(new Test04());

        //lambda表达式
        MyDefaultInterface myDefaultInterface1 = Test04::defaultMethod;
        myDefaultInterface1.get(new Test04());

    }

    //定义一个普通方法
    public void defaultMethod(){
        System.out.println("这是一个类的实例方法");
    }
}

Optional

Optional类是一个可以为null的容器对象。如果值存在则 isPresent()方法会返回true,调用get(方法会返回该对象;

Optional是个容器,它可以保存类型T的值,或者仅仅保存null;

Optional提供很多有用的方法,这样我们就不用显式进行空值检测

判断对象是否为空

package tengfei.optionalTest;

import java.util.Optional;

public class Test01 {
    public static void main(String[] args) {
        String username = null;
        //ofNullable(arg),该方法参数可以为空
        Optional<String> optional = Optional.ofNullable(username);
        //username为空返回值false,不为空返回为true
        boolean present = optional.isPresent();
        System.out.println(optional.get());
    }
}

过滤和设置默认值

package tengfei.optionalTest;

import java.util.Optional;
import java.util.function.Predicate;

public class Test02 {
    public static void main(String[] args) {
        String username = null;
        //设置默认值
//        String s = Optional.ofNullable(username).orElse("default");
//        System.out.println(s);

        //过滤
        boolean present = Optional.ofNullable(username).filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return "default".equals(s);
            }
        }).isPresent();
        System.out.println(present);
    }
}

代码优化

package tengfei.optionalTest;

import java.util.Optional;
import java.util.function.Consumer;

public class Test03 {
    public static void main(String[] args) {
        String username = null;
        Optional<String> optional = Optional.ofNullable(username);
        boolean b = optional.isPresent();
        if (b){
            System.out.println("username不为空再进行具体的操作");
        }


        //优化
        Optional<String> optional1 = Optional.ofNullable(username);
        optional1.ifPresent(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println("如果username不为空,就执行这个方法");
            }
        });

        //简化
        optional1.ifPresent(s -> System.out.println(s));
        optional1.ifPresent(System.out::println);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凉水不好喝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值