Java8新特性

Java8(又称JDK1.8)是Java语言开发的一个主要版本

Oracle公司于2014年3月18日发布Java8

一、Lambda表达式

1.1 概念

  • 特殊的匿名内部类,语法更简洁

  • Lambda表达式允许把函数作为一个方法的参数(函数作为方法参数传递),将代码想数据一样传递

语法

  • 操作符:->
    • ->(箭头操作符)将表达式分成两部分
  • 左侧:(参数1,参数2…)表示参数列表
  • 右侧:{}内部式方法体
<函数式接口><变量名> = (参数1,参数2...)->{
    //方法体
};

注意事项

  • 形参列表的数据类型会自动推断
  • 如果形参列表为空,只需保留()
  • 如果形参只有1个,()可以省略,只需要参数的名称即可。
  • 如果执行语句只有一句,且无返回值,{}可以省略,若有返回值,则想省去{},则必须同时省略return,且执行语句也保证只有一句
  • Lambda不会生成一个单独的内部类文件

1.2 案例

Lambda转化过程

 		//1匿名内部类:创建Runnable对象
        Runnable runnable=new Runnable() {
            @Override
            public void run() {
                System.out.println("子线程开始执行了...");
            }
        };
        new Thread(runnable).start();
		//2使用Lambda表达式优化
        Runnable runnable2= ()->System.out.println("子线程开始执行了...");
        new Thread(runnable2).start();

        //Comparator
        Comparator<Integer> comparator=new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return Integer.compare(o1, o2);
            }
        };
        //使用Lambda表达式优化
        Comparator<Integer> comparator2= (o1,  o2)->Integer.compare(o1, o2);
        TreeSet<Integer> treeSet=new TreeSet<>(comparator2);

二、函数式接口

2.1 概念

  • 如果一个接口只有一个抽象方法,则该接口称之为函数式接口,函数式接口可以使用Lambda表达式,Lambda表达式会被匹配到这个抽象方法上
  • @FunctionalInterface 注解检测接口是否符合函数式接口

2.2 常见函数式接口


示例代码

  • Consumer 消费型接口
    //省略了主函数
	//匿名内部类形式
	System.out.println("------Consumer消费型-----");
    happpy(122, new Consumer<Double>() {
        @Override
        public void accept(Double aDouble) {
            System.out.println(aDouble);
        }
    });
	//Lambda表达式形式
    happpy(1000,money ->System.out.println("聚餐,花费:"+money));

	//Consumer:消费型接口  有参无返回值
    public static void happpy(double money, Consumer<Double> con){
        con.accept(money);
    }
  • Supplier 供给型接口
        System.out.println("------Supplier供给型-----");
        int[] arr=getNums(3,() ->new Random().nextInt(900)+100);
        for (int i : arr) {
            System.out.println(i);
        }

        //Supplier:供给型接口  无参有返回值
        public static int[] getNums(int count, Supplier<Integer> sup){
            int[] nums=new int[count];
            for(int i=0;i<count;i++){
                nums[i]=sup.get();
            }
            return nums;
        }
  • Function<T,R> 函数型接口
    System.out.println("------Function函数型-----");
	String r=handler("hello",s-> s.toUpperCase());
    System.out.println(r);

    //Function:函数型接口,有参有返回值
    public static String handler(String str, Function<String,String> fun){
        return fun.apply(str);
    }
  • Predicate 断言型接口
    System.out.println("------Predicate断言型-----");
    List<String> names=new ArrayList<>();
    names.add("zhangsan");
    names.add("lisi");
    names.add("zhangsanfeng");
    names.add("zhangwuji");
    names.add("cancan");
    List<String> names2=filter(names,s-> s.startsWith("li"));
    for (String s : names2) {
        System.out.println(s);
    }

    //Predicate:断言型接口,有参有返回值 返回值boolean类型
    public static List<String> filter(List<String> names, Predicate<String> p){
        List<String> list=new ArrayList<>();
        for (String name : names) {
            if(p.test(name)){
                list.add(name);
            }
        }
        return list;
    }

三、方法引用

3.1 概念

方法引用是Lambda表达式的一种简写形式。如果Lambda表达式方法体中只是调用一个特定的已经存在的方法,则可以使用方法的引用

3.2 常见形式

3.2.1 第一种形式
  • 对象::实例方法
    • Lambda表达式方法体中只是调用一个特定的已经存在的方法
    • 方法的参数,返回值和接口中的方法参数一致

示例代码

   	//Consumer<T> : void accept(T t) 有参数,无返回
	//println():有参,无返回
	Consumer<String> consumer= s -> System.out.println(s);
    Consumer<String> consumer2=  System.out::println;
    consumer2.accept("hello");
    consumer2.accept("你好");
3.2.2 第二种形式
  • 类::静态方法
    • Lambda表达式方法体中只是调用一个特定的已经存在的方法
    • 方法的参数,返回值和接口中的方法的参数一致
	Comparator<Integer> comparator=(o1,o2)->Integer.compare(o1,o2);
    Comparator<Integer> comparator2=Integer::compare;
//源码分析
Comparator<T> //有两个参数,并且有返回值 
int compare(T o1, T o2);

Integer//静态方法,有两个参数,有返回值
public static int compare(int x, int y) {
    return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
3.2.3 第三种形式
  • 类::实例方法
    • Lambda表达式方法体中只是调用一个特定的已经存在的方法
    • 有一个参数作为方法的调用者,其他的参数,返回值和接口中的方法一致
    Comparator<String> comparator3=(o1,o2)->o1.compareTo(o2);
    Comparator<String> comparator4=String::compareTo;
3.2.4 第四种形式
  • 类::new
    • Lambda表达式方法体中只是调用构造方法创建对象
    • 构造方法参数和接口中方法参数一致
    Supplier<Employee> sup=()->new Employee();
    Supplier<Employee> sup2=Employee::new;
    System.out.println(sup2.get());
    MySupplier<Employee> sup3=Employee::new;
    Employee e = sup3.get("张三", 20, 20000);
    System.out.println(e.toString());
interface Suplier<T>{//无参,有返回值
    T get();
}

public Employ(){//无参,需创建对象
    
}
----------------------------------
interface MyInterface<T>{//有参,有返回值
    T demo(String name,int age)
}

public Empoyee(String name,int age){//有参,创建对象
    this.name = name;
    this.age = age;
}
3.2.5 第五种形式
  • 元素类型[]::new
    • Lambda表达式方法体中创建数组
    • 参数作为数组的长度
    Function<Integer,String[]> function=n->new String[n];
    Function<Integer,String[]> function2=String[]::new;
    String[] arr = function2.apply(5);
    System.out.println(arr.length);
interface Funtion<T,R>{
    R apply(T t);
}

四、Stream

4.1 概念

流(Stream)与集合类似,但集合中保存的是数据,而Stream中保存对集合或数组数据的操作

特点

  • Stream自己不会存储元素
  • Stream不会改变源对象。相反,他们会返回一个持有结果的新Stream
  • Stream操作是延迟执行的,会等到需要结果的时候才执行

4.2 Stream使用步骤

4.2.1 创建流
  • 通过Collection集合的stream()或parallelStream()方法
  • 通过Arrays类的stream()方法
  • 通过Stream接口的of(),iterate(),generate()方法
  • 通过IntStream,LongStream,DoubleStream接口中的of,range,rangeClosed方法

示例代码

    //创建流
    //(1)通过Collection集合的stream()或parallelStream()方法。
    ArrayList<String> arrayList=new ArrayList<>();
    arrayList.add("beijing");
    arrayList.add("shanghai");
    arrayList.add("hangzhou");
    arrayList.add("guangzhou");
    arrayList.add("dongguan");
    Stream<String> stream = arrayList.stream();
    stream.filter(s->s.length()>=8)
        .forEach(s-> System.out.println(s));
    //(2)通过Arrays类的stream()方法。
    IntStream stream1 = Arrays.stream(new int[]{10, 20, 30, 40, 50});
    stream1.forEach(n-> System.out.println(n));
    //(3)Stream的方法:of() 指定元素  iterate()无限迭代流  generate()无限生成流
    Stream<String> stringStream = Stream.of(new String[]{"苹果", "橘子", "葡萄"});
    stringStream.forEach(s-> System.out.println(s));
    Stream<Integer> iterate = Stream.iterate(1, n -> n * 2);
    iterate.limit(5).forEach(s-> System.out.println(s));
    Stream<Integer> generate = Stream.generate(() -> new Random().nextInt(100));
    generate.limit(5).forEach(s-> System.out.println(s));
    //(4)使用IntStream LongStream DoubleStream  of() 指定元素  range()产生指定范围的数字 不包含结束 rangeClosed() 产生指定范围的数字 包含结束
    IntStream intStream = IntStream.of(100, 200, 300);
    intStream.forEach(s-> System.out.println(s));
    IntStream.rangeClosed(0, 100).forEach(s-> System.out.println(s));

4.2.2 中间操作
  • filter,limit,skip,distinct,sorted
  • map
  • parallel
    //中间操作:
    //filter、limit、skip、distinct、sorted
    //map
    //parallel
    //(1)filter、limit、skip、distinct、sorted
    List<Employee> list = new ArrayList<>();
    Employee e1 = new Employee("灿灿", 18, 28000);
    Employee e2 = new Employee("龙哥", 16, 25000);
    Employee e3 = new Employee("华哥", 28, 50000);
    Employee e4 = new Employee("赵吉", 20, 35000);
    Employee e5 = new Employee("子旭", 19, 30000);
    Employee e6 = new Employee("子旭", 19, 30000);
    list.add(e1);
    list.add(e2);
    list.add(e3);
    list.add(e4);
    list.add(e5);
    list.add(e6);
    //filter 过滤
    System.out.println("-----filter------");
    list.stream()
        .filter(e->e.getAge()>=20)
        .forEach(System.out::println);
    //limit 限制
    System.out.println("-----limit------");
    list.stream()
        .limit(2)
        .forEach(System.out::println);
    //skip 跳过
    System.out.println("------skip-----");
    list.stream()
        .skip(2)
        .limit(2)
        .forEach(System.out::println);
    //distinct 去掉重复 (重复依据 hashcode和equals)
    System.out.println("----distinct 去掉重复-----");
    list.stream()
        .distinct()
        .forEach(System.out::println);
    //sorted 排序(实现Comparable接口,重写compareTo方法/创建比较器)
    System.out.println("-----sorted() 排序------");
    list.stream()
        .sorted()
        .forEach(System.out::println);

    //map 映射
    //打印所有员工的姓名
    System.out.println("------map-------");
    list.stream()
        .map(e->e.getSalary())
        .forEach(System.out::println);

    //parallel 并行流
    System.out.println("-----并行流-----");
    //        list.stream()
    //                .parallel()
    //                .forEach(System.out::println);
    list.parallelStream()
        .forEach(System.out::println);
public class Employee implements Comparable<Employee> {
    private String name;
    private int age;
    private double salary;

    public Employee(String name, int age, double salary) {
        this.name = name;
        this.age = age;
        this.salary = salary;
        System.out.println("带参构造方法");
    }

    public Employee() {
        System.out.println("默认构造方法");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", salary=" + salary +
                '}';
    }



    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Employee employee = (Employee) o;
        return age == employee.age &&
                Double.compare(employee.salary, salary) == 0 &&
                Objects.equals(name, employee.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age, salary);
    }

    @Override
    public int compareTo(Employee o) {
        int n1=this.getAge()-o.getAge();
        int n2=Double.compare(this.getSalary(), o.getSalary());
        return n1==0?n2:n1;
    }
}
4.2.3 终止操作
  • forEach,min,max,count
  • reduce,collect
    //终止操作
    //forEach、min、max、count
    //reduce、collect
    List<Employee> list = new ArrayList<>();
    Employee e1 = new Employee("灿灿", 18, 28000);
    Employee e2 = new Employee("龙哥", 16, 25000);
    Employee e3 = new Employee("华哥", 28, 50000);
    Employee e4 = new Employee("赵吉", 20, 35000);
    Employee e5 = new Employee("子旭", 19, 30000);
    Employee e6 = new Employee("子旭", 19, 30000);
    list.add(e1);
    list.add(e2);
    list.add(e3);
    list.add(e4);
    list.add(e5);
    list.add(e6);
    //forEach 遍历 min 最小元素 max最大元素 count元素个数
    //查找工资最低的员工
    //Optional:防止空指针异常,返回的数据封装Optional对象。
    Optional<Employee> min = list.stream()
        .min((o1, o2) -> Double.compare(o1.getSalary(), o2.getSalary()));
    System.out.println(min.get().toString());

    Optional<Employee> max= list.stream()
        .max((o1, o2) -> Double.compare(o1.getSalary(), o2.getSalary()));
    System.out.println(max.get().toString());

    long count = list.stream().count();
    System.out.println("元素个数:"+count);

    //reduce:归约,统计
    //统计所有人的工资和
    Optional<Double> sum = list.stream()
        .map(e -> e.getSalary())
        .reduce((s1, s2) -> s1 + s2);

    System.out.println("所有工资和:"+sum.get());
    System.out.println("平均工资:"+sum.get()/count);

    //collect:收集
    //获取所有人的姓名转成list集合
    List<String> names = list.stream()
        .map(e -> e.getName())
        .collect(Collectors.toList());

    for (String name : names) {
        System.out.println(name);
    }

    //延迟操作 :添加所有的中间操作都不会立即执行。
    System.out.println("--------延迟操作 ------------");
    long c= list.stream()
        .filter(e->{
            System.out.println("执行过了"+e.toString());
            return e.getAge()>=20;
        }).count();
    System.out.println(c);

五、时间

5.1 本地化日期API

  • LocalDate
  • LocalTime
  • LocalDateTime : 类似于Calendar
public class LocalDateTimeDemo {
    public static void main(String[] args) {
        //本地日期时间类
        LocalDateTime localDateTime=LocalDateTime.now();
        System.out.println(localDateTime.toString());

        //昨天
        LocalDateTime yesterday = localDateTime.minusDays(1);
        System.out.println(yesterday);

        //明天
        LocalDateTime tomorrow = localDateTime.plusDays(1);
        System.out.println(tomorrow);

        //指定日期和时间的对象
        LocalDateTime date = LocalDateTime.of(1997, 7, 1, 10, 10, 15);
        System.out.println(date.toString());

        //获取日期和时间信息
        System.out.println(localDateTime.getYear());
        System.out.println(localDateTime.getMonthValue());
        System.out.println(localDateTime.getDayOfMonth());
        System.out.println(localDateTime.getHour());
        System.out.println(localDateTime.getMinute());
        System.out.println(localDateTime.getSecond());

        System.out.println("---------不可变---------");
        //设置日期和时间(不可变)
        LocalDateTime localDateTime1 = localDateTime.withMonth(2);
        System.out.println(localDateTime);
        System.out.println(localDateTime1);

        Date d=new Date();//(可变)
        d.setTime(System.currentTimeMillis()-60*60*24*1000);
        System.out.println(d);
    }
}

5.2 Instant 时间戳

​ 类似于Date

public class InstantDemo {
    public static void main(String[] args) throws InterruptedException {
        //创建Instant
        Instant instant=Instant.now();
        System.out.println(instant);
        System.out.println("秒:"+instant.getEpochSecond());
        System.out.println("毫秒:"+instant.toEpochMilli());
        //昨天
        Instant yesterday=instant.minusMillis(60*60*24*1000);
        System.out.println(yesterday);

        //明天
        Instant tomorrow=instant.plusMillis(60*60*24*1000);
        System.out.println(tomorrow);


        //计时
        Instant start=Instant.now();

        Thread.sleep(3000);

        Instant end=Instant.now();

        long t = Duration.between(start, end).toMillis();
        System.out.println("用时:"+t);

    }
}

5.3 时区

public class ZoneIdDemo {
    public static void main(String[] args) {
        //ZoneId时区类
        Set<String> set = ZoneId.getAvailableZoneIds();
        for (String s : set) {
            System.out.println(s);
        }
        //获取默认时区
        System.out.println("--------默认时区-------");
        System.out.println(ZoneId.systemDefault());
    }
}

5.4 案例

public class InstantDemo2 {
    public static void main(String[] args) {
        //演示转换
        //(1)LocalDateTime-->Instant-->Date
        System.out.println("---------LocalDateTime-->Instant-->Date-------");
        LocalDateTime now=LocalDateTime.now();
        Instant instant = now.atZone(ZoneId.systemDefault()).toInstant();
        Date from = Date.from(instant);

        System.out.println(from);
        //(2)Date-->Instant-->LocalDateTime
        System.out.println("---------Date-->Instant-->LocalDateTime-------");
        Instant instant1 = from.toInstant();
        LocalDateTime localDateTime = instant1.atZone(ZoneId.systemDefault()).toLocalDateTime();
        System.out.println(localDateTime);
    }
}

5.5 格式化类

DateTimeFormatter

public class DateTimeFormaterDemo {
    public static void main(String[] args) {
        //时间格式化类DateTimeFormatter
        DateTimeFormatter dtf= DateTimeFormatter.ofPattern("yyyy/M.dd HH:mm:ss");
        //(1) 日期---》字符串
        LocalDateTime localDateTime=LocalDateTime.now();
        String format = dtf.format(localDateTime);
        System.out.println(format);

        //(2)字符串--->日期
        LocalDateTime parse = LocalDateTime.parse("1998/10.10 10:20:30",dtf);
        System.out.println(parse);

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值