Java8新特性

  1. Lambda表达式:也可以成为闭包,是java8最重要的特性,允许把一个函数作为一个方法的参数,使用它可以使代码变得更加简洁紧凑。

  2. Lambda表达式语法

    1. (parameters) -> expression
    2. (parameters) -> {expressions;}
  3. Lambda表达式特征:

    1. 可选类型生命:不需要生命参数类型,编译器可以统一识别参数值
    2. 可选的参数圆括号:一个参数无需定义圆括号,但多个参数的时候需要定义圆括号
    3. 可选的大括号:如果主题包含一个语句,就不需要使用大括号
    4. 可选的返回值类型:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定表明表达式返回了一个数值
  4. Lambda表达式演示代码

    public class LambdaTest {
    
        public static void main(String[] args) {
            MathOperation mathOperation = () -> 6;
            System.out.println(mathOperation.print());
    
            MathOperationAdd mathOperationAdd1 = (a, b) -> a + b;
            MathOperationAdd mathOperationAdd2 = (a, b) -> a * b;
            System.out.println(mathOperationAdd1.add(2,6));
            System.out.println(mathOperationAdd2.add(2,6));
    
            Stringfun stringfun = msg -> System.out.println("msg: "+msg);
            stringfun.fun("杀猪饭店");
        }
    
        interface MathOperation{
            int print();
        }
    
        interface MathOperationAdd{
            int add(int a, int b);
        }
    
        interface Stringfun{
            void fun(String s);
        }
    
    }
    
  5. Lambda表达式变量作用域:只能引用标记了final的外层局部变量,就是说不能在Lambda表达式内部修改定义在域外的局部变量,否则会编译错误,类似于下面的情况

    public class LambdaTest2 {
        public static void main(String[] args) {
            int num = 1;
            Convert<Integer, String> s = (param) -> System.out.println(param + num);
            //num = 1;   会编译报错
            s.convert(2);
            //num = 1;   会编译报错
        }
    
        public interface Convert<T1, T2>{
            void convert(int i);
        }
    }
    
  6. Lambda表达式的局部变量可以不声明为final,但必须不可被后面的代码修改(即隐形的具有final的语义)

  7. Lambda表达式中不允许声明一个于局部变量同名的参数或者局部变量

    import java.util.Comparator;
    
    public class LambdaTest3 {
        public static void main(String[] args) {
            String first = "";
           // Comparator<String> comparator = (first, second) ->  会报错,与上面的first重名
            //        Integer.compare(first.length(), second.length());
        }
    }
    
  8. 方法引用:可以使语言的构造更紧凑、减少冗余代码

  9. 方法引用使用一堆冒号:: ;

  10. 方法引用的使用

    1. 构造器引用:它的语法是Class::new,或者更一般的Class::new,示例如下

      final Car car = Car.create(Car::new);
      final List<Car> cars = Arrays.asList(car);
      
    2. 静态方法的引用:它的语法是Class::static_method示例如下

      cars.forEach(Car::collid);
      
    3. 特定类的任意对象的方法引用:它的语法是Class::method示例如下

      cars.forEach(Car::repair):
      
    4. 特定对象的方法引用:它的语法是instance::method示例如下

      final Car police = Car.create(Car::new);
      cars.forEach(police::follow);
      
  11. 方法引用代码示例

    import java.util.function.Supplier;
    
    public class Car {
    
        private String name;
        private int year;
    
        public static Car create(final Supplier<Car> supplier, String name, int year){
            name = name;
            year = year;
            System.out.println("构造器");
            return supplier.get();
        }
    
        public static void collide(final Car car){
            System.out.println("collide被调用了: "+car.toString());
        }
    
        public void follow(final Car another){
            System.out.println("follow the "+another.toString());
        }
    
        public void repair(){
            System.out.println("repaired "+this.toString());
        }
    
        @Override
        public String toString() {
            return "Car{" +
                    "name='" + name + '\'' +
                    ", year=" + year +
                    '}';
        }
    }
    
    import java.util.Arrays;
    import java.util.List;
    
    public class methodTest {
    
        public static void main(String[] args) {
            //构造器引用
            Car car = Car.create(Car::new, "BMW", 2);
    
            //静态方法引用,语法为 Class::static_method
            List<Car> cars = Arrays.asList(car);
            cars.forEach(Car::collide);
    
            //特定类任意对象,语法为 Class::method
            cars.forEach(Car::repair);
    
            //特定对象的方法引用,语法为instance::method
            Car car1 = Car.create(Car::new, "BC", 3);
            cars.forEach(car1::follow);
    
        }
    }
    
  12. 函数式接口:有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。

  13. 函数式接口可以被阴式转为lambda表达式

  14. 函数式接口代码示例:

    @FunctionalInterface
    public interface CreateFunction {
    
        void sayMessage(String message);
    }
    
    
    public class FunctionTest {
        public static void main(String[] args) {
            CreateFunction createFunction = msg -> System.out.println(msg);
            createFunction.sayMessage("123123");
        }
    }
    
  15. JDK8新增的函数式接口 java.util.function

    序号接口 & 描述
    1**BiConsumer<T,U>**代表了一个接受两个输入参数的操作,并且不返回任何结果
    2**BiFunction<T,U,R>**代表了一个接受两个输入参数的方法,并且返回一个结果
    3**BinaryOperator**代表了一个作用于于两个同类型操作符的操作,并且返回了操作符同类型的结果
    4**BiPredicate<T,U>**代表了一个两个参数的boolean值方法
    5BooleanSupplier代表了boolean值结果的提供方
    6**Consumer**代表了接受一个输入参数并且无返回的操作
    7DoubleBinaryOperator代表了作用于两个double值操作符的操作,并且返回了一个double值的结果。
    8DoubleConsumer代表一个接受double值参数的操作,并且不返回结果。
    9**DoubleFunction**代表接受一个double值参数的方法,并且返回结果
    10DoublePredicate代表一个拥有double值参数的boolean值方法
    11DoubleSupplier代表一个double值结构的提供方
    12DoubleToIntFunction接受一个double类型输入,返回一个int类型结果。
    13DoubleToLongFunction接受一个double类型输入,返回一个long类型结果
    14DoubleUnaryOperator接受一个参数同为类型double,返回值类型也为double 。
    15**Function<T,R>**接受一个输入参数,返回一个结果。
    16IntBinaryOperator接受两个参数同为类型int,返回值类型也为int 。
    17IntConsumer接受一个int类型的输入参数,无返回值 。
    18**IntFunction**接受一个int类型输入参数,返回一个结果 。
    19IntPredicate:接受一个int输入参数,返回一个布尔值的结果。
    20IntSupplier无参数,返回一个int类型结果。
    21IntToDoubleFunction接受一个int类型输入,返回一个double类型结果 。
    22IntToLongFunction接受一个int类型输入,返回一个long类型结果。
    23IntUnaryOperator接受一个参数同为类型int,返回值类型也为int 。
    24LongBinaryOperator接受两个参数同为类型long,返回值类型也为long。
    25LongConsumer接受一个long类型的输入参数,无返回值。
    26**LongFunction**接受一个long类型输入参数,返回一个结果。
    27LongPredicateR接受一个long输入参数,返回一个布尔值类型结果。
    28LongSupplier无参数,返回一个结果long类型的值。
    29LongToDoubleFunction接受一个long类型输入,返回一个double类型结果。
    30LongToIntFunction接受一个long类型输入,返回一个int类型结果。
    31LongUnaryOperator接受一个参数同为类型long,返回值类型也为long。
    32**ObjDoubleConsumer**接受一个object类型和一个double类型的输入参数,无返回值。
    33**ObjIntConsumer**接受一个object类型和一个int类型的输入参数,无返回值。
    34**ObjLongConsumer**接受一个object类型和一个long类型的输入参数,无返回值。
    35**Predicate**接受一个输入参数,返回一个布尔值结果。
    36**Supplier**无参数,返回一个结果。
    37**ToDoubleBiFunction<T,U>**接受两个输入参数,返回一个double类型结果
    38**ToDoubleFunction**接受一个输入参数,返回一个double类型结果
    39**ToIntBiFunction<T,U>**接受两个输入参数,返回一个int类型结果。
    40**ToIntFunction**接受一个输入参数,返回一个int类型结果。
    41**ToLongBiFunction<T,U>**接受两个输入参数,返回一个long类型结果。
    42**ToLongFunction**接受一个输入参数,返回一个long类型结果。
    43**UnaryOperator**接受一个参数为类型T,返回值类型也为T。

  16. 函数式接口实例:

  17. Predicate: 接口是一个函数式接口,它接受一个输入参数T,返回一个布尔值。改接口包含多种默认方法来将Predicate组合成其他复杂的逻辑。

    该接口用于测试的对象是true或false

  18. import java.util.Arrays;
    import java.util.List;
    import java.util.function.Predicate;
    
    public class PredicateTest {
        public static void main(String[] args) {
            /*Predicate<Integer> predicate = n -> n == 2;
            boolean test = predicate.test(3);
            System.out.println(test);*/
    
            List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9);
            Predicate<Integer> predicate = n -> n % 2 == 0;
            System.out.println("打印偶数");
            compare(list, predicate);
    
            System.out.println();
            System.out.println();
            
            System.out.println("打印大于3的数字");
            Predicate<Integer> predicate1 = n -> n > 3;
            compare(list, predicate1);
        }
    
        private static void compare(List<Integer> list, Predicate<Integer> predicate){
            for(Integer i : list){
                if(predicate.test(i)){
                    System.out.println(i + " ");
                }
            }
        }
    }
    
  19. Function<T, R>,接受一个参数,返回一个结果

    import java.util.function.Function;
    
    public class FunctionTest {
        public static void main(String[] args) {
            Function<String, Boolean> function = s -> null != s;
    
            Boolean apply = function.apply(null);
            System.out.println(apply);
    
            Function<Boolean, Integer> functionl2 = s -> s ? 1 : 0;
            //function的结果作为functionl2的参数
            Function<String, Integer> stringIntegerFunction = function.andThen(functionl2);
            Integer apply1 = stringIntegerFunction.apply(null);
            System.out.println(apply1);
    
            Function<String, Integer> compose = functionl2.compose(function);
            Integer abs = compose.apply("abs");
            System.out.println(abs);
        }
    }
    
  20. Consumer接受一个参数,没有返回结果

    import java.util.function.Consumer;
    import static java.lang.System.out;
    
    public class ConsumerTest {
        public static void main(String[] args) {
            //Consumer<String> consumer = s -> System.out.println(s);
            Consumer<String> consumer = out::println;
                    consumer.accept("werwer");
        }
    }
    
  21. Supplier接口,不接受参数,只返回一个结果

    import java.util.function.Supplier;
    
    public class SupplierTest {
        public static void main(String[] args) {
            Supplier<String> stringSupplier = () -> "无参数的";
            String s = stringSupplier.get();
            System.out.println(s);
        }
    }
    
  22. 默认方法:接口可以有时限方法,而且不需要实现类去实现其方法,只需要在方法名前加一个default关键字,即可实现默认方法

    public interface DefaultMethodTest {
    
        default void add(int a, int b){
            System.out.println(a + b);
        }
    
    }
    
  23. 静态默认方法

    public interface DefaultMethodTest {
    
        static void out(){
            System.out.println("吹牛");
        }
    
    }
    
  24. Optional类:是一个可以为null的容器对象,如果值存在则isPresent()方法返回true,调用get()方法会返回该对象,

  25. Optional是个容器,它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显示的进行空值检测。

  26. Optional类的引入很好的解决空指针异常。

  27. Optional实例:

    import java.util.Optional;
    
    public class OptionalTest {
        public static void main(String[] args) {
            Integer value = 11;
    
            //ofNullable允许参数为null
            Optional<Integer> optional = Optional.ofNullable(value);
    
            //of的参数不允许为null
            //Optional<Integer> optional1 = Optional.of(value);
    
            //判断存放的对象是否存在值,是,反回true,不存在则返回false
            System.out.println(optional.isPresent());
    
        }
    }
    
  28. Stream:Java8新添加了一个抽象成为Stream,可以让你以一种声明的方式处理数据。

  29. Stream使用一种类似用SQL语句从数据库查询数据的直观方式来提供一种对Java集合运算和表达的高阶抽象。

  30. Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。这种风格将要处理的元素集合看作一种流,流在管道中传输,并且可以在管道的节点上进行处理,比如筛选、排序、聚合等。

  31. 元素在管道中经过中间操作的处理,最后由最终操作得到前面处理的结果。

  32. Stream使用示例

    import java.util.Arrays;
    import java.util.List;
    import java.util.stream.Collectors;
    
    public class StreamTest {
    
        public static void main(String[] args) {
            List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl");
    
            //利用Stream统计strings中空字符串的个数
            long count = strings.stream().filter(s -> s.isEmpty()).count();
            System.out.println("count: "+count);
    
            //统计Stream中字符串长度为3的个数
            long count1 = strings.stream().filter(s -> s.length() == 3).count();
            System.out.println("count1: "+count1);
    
            //过滤掉空字符串,得到新的列表
            List<String> collect = strings.stream().filter(s -> !s.isEmpty())
                    .collect(Collectors.toList());
            System.out.println(collect);
    
            //合并字符串,将strings的非空字符串合并为一个新的字符串,中间以逗号隔开
            String collect1 = strings.stream().filter(s -> !s.isEmpty())
                    .collect(Collectors.joining(","));
            System.out.println(collect1);
        }
    }
    
  33. Stream对数字的操作

    import java.util.Arrays;
    import java.util.IntSummaryStatistics;
    import java.util.List;
    import java.util.Random;
    import java.util.stream.Collectors;
    
    public class NumberList {
        public static void main(String[] args) {
            List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
    
            //获得一个list中各元素平方的新集合
            List<Integer> collect = list.stream().map(i -> i * i)
                    .distinct().collect(Collectors.toList());
            System.out.println(collect);
    
            IntSummaryStatistics intSummaryStatistics = collect.stream()
                    .mapToInt((x) -> x).summaryStatistics();
    
            //获得collect中的最大值
            System.out.println(intSummaryStatistics.getMax());
            //获得collect中的最小值
            System.out.println(intSummaryStatistics.getMin());
            //获得collect中的总和
            System.out.println(intSummaryStatistics.getSum());
            //获得collect中的平均值
            System.out.println(intSummaryStatistics.getAverage());
    
            //获取10个随机数
            Random random = new Random();
            random.ints().limit(10).sorted().forEach(System.out::println);
    
        }
    }
    
  34. 日期API

  35. 旧版的Date的问题

    1. 是非线程安全的,所有的日期类都是可变的,这是Java日期类最大的问题之一。
    2. 涉及很差,Java的日期/时间类的定义不一致,在java.util和java.sql的包中都有日期,将其纳入到java.sql的包中并不合理。另外这两个类都有相同的名字,这本身就是一个非常糟糕的设计。
    3. 时区处理麻烦,日期类并不提供国际化,没有时区支持,因此java引入了java.util.Calendar和java.util.timeZone类,但它们同样存在上述的所有问题。
  36. Java8在java.time包下提供了很多新的API,

    1. Local(本地) – 简化了日期时间的处理,没有时区的问题。
    2. Zoned(时区) – 通过指定的时区处理日期时间
  37. 新的java.time包涵盖了所有处理日期、时间、日期/时间、时区、时刻(intstants),过程(during)与时钟的(cloak)操作。

  38. 日期的使用示例

    import java.time.LocalDate;
    import java.time.LocalDateTime;
    import java.time.ZoneId;
    import java.time.ZonedDateTime;
    import java.time.format.DateTimeFormatter;
    import java.time.temporal.ChronoUnit;
    
    //LocalDate 用于表示当天日期,它只有日期,不包含时间
    public class LocalDateTest {
        public static void main(String[] args) {
    
            //获取当前时间
            LocalDate now = LocalDate.now();
            System.out.println(now);
    
            //获取指定日期的日期对象
            LocalDate date = LocalDate.of(2000, 1, 1);
            System.out.println(date);
    
            //获取日期对象的年月日数据
            int year = now.getYear();
            int monthValue = now.getMonthValue();
        int dayOfMonth = now.getDayOfMonth();
            System.out.println("year: "+year);
            System.out.println("monthValue: "+monthValue);
            System.out.println("dayOfMonth: "+dayOfMonth);
    
            //比较两个日期是否相等
            LocalDate localDate = LocalDate.of(2019, 8, 14);
            System.out.println(now.equals(localDate));
    
            //日期计算
            LocalDate localDate1 = now.plus(1, ChronoUnit.WEEKS);
            System.out.println(localDate1);
    
            //日期的比较
            LocalDate localDate2 = LocalDate.of(2000, 1, 1);
            System.out.println(now.isAfter(localDate2));
            LocalDate localDate3 = LocalDate.of(2020, 1, 1);
            System.out.println(now.isAfter(localDate3));
    
            //时区
            ZoneId shanghaiZoneId = ZoneId.of("Asia/Shanghai");
            ZonedDateTime now1 = ZonedDateTime.now(shanghaiZoneId);
    
            ZoneId tokyoZoneId = ZoneId.of("Asia/Tokyo");
            ZonedDateTime now2 = ZonedDateTime.now(tokyoZoneId);
    
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            System.out.println("上海时间为: " + now1.format(formatter));
            System.out.println("东京时间为: " + now2.format(formatter));
    
            //解析日期
            String dateText = "20190813";
            LocalDate date2 = LocalDate.parse(dateText, DateTimeFormatter.BASIC_ISO_DATE);
            System.out.println(date2);
    
            //格式化日期
            String format = now.format(DateTimeFormatter.ISO_DATE);
            System.out.println(format);
    
            //日期转换字符串
            LocalDateTime localDateTime = LocalDateTime.now();
            DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            String format1 = localDateTime.format(formatter1);
            System.out.println(format1);
    
            //字符串转时间
            String dateTimeText = "2018-08-14 10:25:26";
            LocalDateTime dateTime = LocalDateTime.parse(dateTimeText, formatter1);
            System.out.println(dateTime);
        }
    }
    
  39. 时间的使用示例

    import java.time.LocalTime;
    
    //LocalTime 用于表示当天时间, 它只有时间,不包含日期。
    public class LocalTimeTest {
        public static void main(String[] args) {
            LocalTime now = LocalTime.now();
            System.out.println(now);
    
            LocalTime localTime = now.plusHours(2);
            System.out.println(localTime);
        }
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值