jdk8_jdk8- - CSDN
  • Java8开发工具包(Java Development Kit) windows 64位标准版, 2019年4月更新版 Java8开发工具包(Java Development Kit) linux 64位标准版, 2019年4月更新版 链接: https://pan.baidu.com/s/1pTr-9-FbMme8Pc1Q2MhKjA ...

    Java8开发工具包(Java Development Kit) windows 64位标准版, 2019年4月更新版
    Java8开发工具包(Java Development Kit) linux 64位标准版, 2019年4月更新版

    链接: https://pan.baidu.com/s/1pTr-9-FbMme8Pc1Q2MhKjA
    提取码: e6ih

    链接: https://pan.baidu.com/s/1tJVUDqc3YpwygtPM6QxD1w 提取码: 36s2 复制这段内容后打开百度网盘手机App,操作更方便哦

    展开全文
  • javaJDK8javaJDK8

    2020-07-30 23:33:33
    javaJDK8 欢迎下载javaJDK8 欢迎下载javaJDK8 欢迎下载javaJDK8 欢迎下载
  • JDK8最新版

    2020-07-17 17:51:11
    包含了几款jdk7和最新的jdk8以及环境变量配置文件,帮助初学者更好更快的入门!
  • JDK8新特性

    2018-07-06 18:22:50
    1. 函数式编程 1.1 面向对象编程与函数式编程 1.2 JDK8对FP的支持2. 接口的默认方法(default)和静态方法(Static Methods) 2.1 接口的默认(实例)方法 2.2 接口静态(类)方法 2.3 接口的实例方法 2.4 ...

    原文链接:JDK 8 New Feature

        JDK8是一个重大的升级版本!引入新的语法(Lambda表达式)支持函数式编程;改造了现在类库(特别是集合框架);增加了新的类库和特性。

        JDK8带来了三个重要的特性:

    1. Lambda表达式
    2. Stream API
    3. Date/Time API(java.time)

    1. 函数式编程

    1.1 面向对象编程与函数式编程

    参考

        1、面向对象编程与函数式编程 https://www.codenewbie.org/blogs/object-oriented-programming-vs-functional-programming

        面向对象编程(Object-Oriented Programming,OOP)是一种编程方式,它基于对象(Object)的概念,由数据(以字段或属性的形式)和代码(以过程或方法的形式)构成。

        函数式编程(Functional programming,FP)是一种编程方式,是一种构建程序元素和结构的风格,它将计算机的运算作为数学上的函数运算,并且避免使用程序状态和易变对象。

        在程序中,有两种主要的组件,即数据和行为(或代码)。在OOP看来,将数据和与之关联的行为结合在一起到一个对象中会使程序如何运行变得更易理解。而FP则认为数据和行为是不同的,并且应该清晰的区别开来。

    举例

    让我们通过一个例子来说明这两种编程风格的不同吧。例如你正在运营一家公司,并准备给你的员工涨薪。

    OOP的示例

    使用OOP时,我们将创建一个Empoyee类,并将数据(name/salary)和行为(raiseSalary())放在类里,如下:

    1
    public class Employee {
    2
       // Data
    3
       private String name;
    4
       private int salary;
    5
    6
       // Constructor
    7
       public Empolyee(String name, int salary) {
    8
          this.name = name;
    9
          this.salary = salary;
    10
       }
    11
    12
       // Behavior
    13
       public void raiseSalary(int amount) {
    14
          salary += amount;
    15
       }
    16
       public String toString() {
    17
          return "Employee[name=" + name + ",salary=" + salary + "]";
    18
       }
    19
    }

    我们需要创建员工的列表List:

    1
    List<Empolyee> empolyees = = List.of(new Employee("Peter", 1000), new Employee("Paul", 2000));

    然后在for循环中调用raiseSalary()方法

    1
    for (Employee employee : employees) {
    2
       employee.raiseSalary(100);
    3
       System.out.println(employee);  // debugging
    4
    }

    使用面向对象编程(OOP)时:

    1. 我们首先定义类(class)
    2. 然后创建类的实例(instance)
    3. 再调用实例的方法

    在创建实例的时候把数据提供给对象,我们运行对象上的方法,使与存储的数据相关作用。


    函数式编程(FP)示例

    使用函数式编程,数据和行为是分开的。数据经常放在简单的结构体中,比如数组中。数据是不可变的,而行为是由微小、独立和特写的函数实,如下:

    1
    // Data
    2
    Map<String, Integer> workers = Map.of("Peter", 1000, "Paul", 2000);
    3
    4
    // Behavior
    5
    [TODO] 
    6
    raiseSalary(): one
    7
    raiseSalaries(): delegate to raiseSalary()

    使用函数式编程时,数据被保存在简单的数据或者哈希结构中,而不是高级别的类对象中。数据和行为不会搀和在一起。数据是不可变的,状态共享被禁止。函数式编程特别依赖小而专业性的方法,这些方法是大的job的一部分,并且将细节委派给其他小方法。

    函数式编程将计算重点放在在一个纯函数上,一个纯函数(pure function)是下面这样的函数。

    1. 返回值依赖于输入,相同的输入总会产生相同的输出
    2. 没有负作用
    3. 不会改变入参的值

    在函数式编程中:

    1. 有一个完全独立的数据和行为(函数function)
    2. 数据(对象)是不可变的
    3. 状态共享被禁止(没有继承关系)

    很有代表性的一点是,函数编程中会使用更少的代码,因为我们没必要对定义一个复杂的类。

    比较

    1. 函数编程的一个优点是数据集是固定;并且随着你的应用程序的演进,你会添加新的函数处理已存在的数据,而当前的那些函数是相对独立的。
    2. 函数编程的另一个优点是在并发环境中。众所周知不可变的状态在并发环境中没有任何问题。
    3. 而面向对象编程的优点在于,类(数据和行为的集合)集是固定的;并且随着你应用程序的演进,你可以添加新类进去(利用组件或继承)。已存在的类是相对独立的。

    然而,当应用程序持续演进过程中,有可能会走错路,遇到下面这样的问题:

    1. 添加新数据时不得不对现有的函数进行改造
    2. 添加新的方法到OO程序时不得不对现有的类进行改造

    话又说回来了,你其实不用太纠结选OOP还是FP,你完全可以在面向对象的思想框架中使用函数编程。开发者可以在页面对象环境中写出短小,独立且特定功能一的函数。

    1.2 JDK8对FP的支持

    为了支持函数式编程,JDK8重新设计了接口interface,引进了lamba表达式,改造了集合框架,并入了流式API。

    在详细讲解函数式编程思想之前,我们先来看一下这些变化。

    2. 接口的默认方法(default)和静态方法(Static Methods)

    接口的主要目的是,让你“面向接口而不是面向实现编程”。

    在JDK8之前,接口包含了两类实体:

    1. public abstract描述的抽象方法:没有实现或方法体的方法,子类实现必须覆盖抽象方法并且提供实现的方法体
    2. public static final字段或常量。

    因此设计和维护接口非常困难,因为当我们在接口中添加一个方法时,所有的实现类不得不跟着实现这些方法。

    为了解决这个问题,从JDK8开始,接口可以包含一个public static 的方法和一个public default方法(JDK9未来会把private方法和private static方法引入到接口中)。

    1. public default方法和public static 方法都是非抽象(non-abstract)的方法,它们都有实现(方法体)。
    2. 添加一个public default方法或者public static 方法到接口中不用在子类中去实现。
    3. 接口的public default方法可以被子类继承(子类或子接口),子类实现或子接口不能覆盖public default方法,当然也没有必要。
    4. 接口的public static方法不能被子类继承。只能被超类调用;不能被子类或子类的实现所调用。
    5. (JDK9)private方法和private static方法就像接口的工具方法,不能被他们的子类所继承。

    总之,在JDK8或9中接口包含了:

    1. public static (class)final的字段或常量
    2. public static(instance)的没有实现的方法——必须被子类实现的
    3. public default(instance)自带实现的方法——可以被继承,也可以被覆盖只是没必要
    4. public static(class)自带实现的方法——不能被子类继承(不像超类的那种static方法)
    5. (JDK9)的private(intance)自带实现的方法——不可以被继承,不能被其他static方法调用
    6. (JDK9)的private static(class)自带实现的方法——不能被子类承继,可以被本接口的其他static方法调用

    2.1 接口的默认(实例)方法

    JDK8的接口可以通过default关键字来声明默认方法。默认方法是非抽象的,言下之义,必须有默认的实现,其子没有必要去覆盖这个方法,当然有需要时也可以。default的方法必须是public的。

    1
    public interface MyJ8InterfaceWithDefault {
    2
       void foo();   // JDK8之前的抽象方法
    3
    4
       // 通过default关键字标记的默认方法
    5
       default void bar() {    // JDK8之后的默认方法
    6
          System.out.println("MyJ8InterfaceWithDefault runs default bar()");
    7
       }
    8
       
    9
       //default void bar1();
    10
       // error: missing method body, or declare abstract
    11
    }

    如果忘了给默认方法写实现,会报错:error: missing method body, or declare abstract

    1
    public class MyImplClass1 implements MyJ8InterfaceWithDefault {
    2
       // Need to override all the abstract methods,
    3
       //   but not necessarily for the default methods.
    4
       @Override
    5
       public void foo() {
    6
          System.out.println("MyImplClass1 runs foo()");
    7
       }
    8
    9
       // Test Driver
    10
       public static void main(String[] args) {
    11
          MyImplClass1 c = new MyImplClass1();
    12
          c.foo();  // MyImplClass1 runs foo()
    13
          c.bar();  // MyJ8InterfaceWithDefault runs default bar()
    14
       }
    15
    }

    实现多个接口

    Java中的类可以实现多个接口(但只能实现一个父类)。在上面的例子中,如果另一个接口也提供了一个叫foo的默认方法,而一个类实现了这两个接口的话,问题就来了,此时类就不知道用哪个默认方法的实现了,为了解决这个问题,JDK8要求当实现的接口中有相同的默认方法声明时,就必须覆盖这个方法。如下:

    1
    public interface MyJ8InterfaceWithDefault1 {
    2
       // Same signature (but different implementation) as the default method in MyJ8InterfaceWithDefault
    3
       default void bar() {   // public (instance) (post-JDK 8)
    4
          System.out.println("MyJ8InterfaceWithDefault1 runs default bar() too!");
    5
       }
    6
    }
    1
    public class MyImplClass2 implements MyJ8InterfaceWithDefault, MyJ8InterfaceWithDefault1 {
    2
       @Override
    3
       public void foo() {
    4
          System.out.println("MyImplClass2 runs foo()");
    5
       }
    6
    7
       @Override
    8
       public void bar() {
    9
          System.out.println("MyImplClass2 runs overridden bar()");
    10
       }
    11
       // bar() exists in both interfaces.
    12
       // MUST override, or
    13
       //    error: class MyImplClass2 inherits unrelated defaults for bar()
    14
       //    from types MyJ8InterfaceWithDefault and MyJ8InterfaceWithDefault1
    15
    16
       public static void main(String[] args) {
    17
          MyImplClass2 c = new MyImplClass2();
    18
          c.foo();   // MyImplClass2 runs foo()
    19
          c.bar();   // MyImplClass2 runs overridden bar()
    20
       }
    21
    }

    这种情况下,如果没有正确覆盖默认方法的话,就会出现一个错误:error: class MyImplClass2 inherits unrelated defaults for bar() from types MyJ8InterfaceWithDefault and MyJ8InterfaceWithDefault1

    2.2 接口静态(类)方法

    static method和default method类似,只是它不能被子类继承。默认情况下是public的(JDK9支持private的静态方法)

    1
    public interface MyJ8InterfaceWithStatic {
    2
       void foo();   // abstract public (instance) (pre-JDK 8)
    3
    4
       static void bar() {  // public (class) (post-JDK 8)
    5
          System.out.println("MyJ8InterfaceWithStatic runs static bar()");
    6
       }
    7
    8
       //static void bar1();
    9
       // error: missing method body, or declare abstract   
    10
    }

    就是默认方法一样,静态方法也必须是有实体体的,否则会出现编译错误:error: missing method body, or declare abstract 

    1
    public class MyImplClass3 implements MyJ8InterfaceWithStatic {
    2
       @Override
    3
       public void foo() {
    4
          System.out.println("MyImplClass3 run foo()");
    5
       }
    6
    7
       // Test Driver
    8
       public static void main(String[] args) {
    9
          MyImplClass3 c = new MyImplClass3();
    10
          c.foo();  // MyImplClass3 run foo()
    11
          MyJ8InterfaceWithStatic.bar();  // MyJ8InterfaceWithStatic runs static bar()
    12
    13
          // Interface's static methods are NOT inherited (Unlike Superclass)!!!
    14
          // MyImplClass3.bar();
    15
          // c.bar();
    16
                // error: cannot find symbol bar()
    17
          // MyJ8InterfaceWithStatic c1 = new MyImplClass3();
    18
          // c1.bar();
    19
                // error: illegal static interface method call
    20
       }
    21
    }

    注意接口的静态方法不能被子类继承!!!不像超类的静态方法是可以被它的子类承继的。这可能是因为我们只能扩展一个超类,但能实现多个接口。

    1
    public class MyImplClass4 implements MyJ8InterfaceWithStatic {
    2
       @Override
    3
       public void foo() {
    4
          System.out.println("MyImplClass4 run foo()");
    5
       }
    6
    7
       // @Override  // error: static methods cannot be annotated with @Override
    8
       public static void bar() {
    9
          System.out.println("MyImplClass4 run bar()");
    10
       }
    11
    12
       // Test Driver
    13
       public static void main(String[] args) {
    14
          MyImplClass4 c = new MyImplClass4();
    15
          c.foo();  // MyImplClass3 run foo()
    16
    17
          MyJ8InterfaceWithStatic.bar();  // MyJ8InterfaceWithStatic runs static bar()
    18
          MyImplClass4.bar(); // MyImplClass4 run bar()
    19
          c.bar();            // MyImplClass4 run bar()
    20
       }
    21
    }

    由于接口中的静态方法不能被子类继承,所以你可以在子类中定义一个自己的相同名字的静态方法。

    Java中的超类的静态方法可以被子类继承吗?

    是的。可以参考这里

    Java接口的静态方法可以被子类继承吗?

    不可以。可能是因为子类能实现多个接口,但只能扩展一个超类。

    2.3 接口的实例方法

    在JDK8的接口中,可以包含3种方法:abstract/default/static。所有方法都是public的。

    JDK8的关于接口的文档中列出了实现方法,指的是非静态方法(即abstract和default的方法)

    最后列一个所有的方法种类:如静态方法(static methods),实例方法(instance methods),抽象方法(Abstract methods)和默认方法(default methods)。这些你都可以在接口java.util.stream.Stream.中看到。

    2.4 接口与抽象类

    1. 变量:接口只能包含常量(即public static final修饰的变量)
    2. 方法访问权限:所有的方法(abstract/static/default)都是public的。JDK9中支持private和private static 方法。

    3. Labmda表达式、函数式接口和集合

    参考:

    1. Lambda表达式教程:http://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html
    2. Lambda快速入门:http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/Lambda-QuickStart/index.html
    3. 集合教程:http://docs.oracle.com/javase/tutorial/collections/
    4. 聚合操作教程:http://docs.oracle.com/javase/tutorial/collections/streams/index.html

    JDK8中最显著的更新莫过于Lambda表达式了,它用更简单符合来构建一个“Single-Abstract-Method-Interface”。在JDK8中,“Single-Abstract-Method-Interface”也叫“Functional Interface”。

    JDK8也改造了集合框架,使用Lambda表达式、函数式接口和流式API,可以支持链式和聚合操作(或称filter-map-reduce)。

    3.1 函数式接口

    JDK有许多“Single-Abstract-Method Interfaces”,在JDK8中称为函数式接口(Functional Interface)。最常见的是java.awt.event.ActionListener 、java.lang.Runnable、 java.util.Comparator。这些方接口通常会在匿名类中构造匿名实例。

    注解@FunctionInterface 

    这个注解可以用来标记只有一个抽象方法的接口。可以有效的阻止向一个函数式接口中添加额外的方法。

    3.2 示例1:Swing中的监听Lambda

    略(译者不常用)

    3.3 Lambda表达式的语法和使用

    在JDK8之前,想要构造一个函数式接口的实例,需要多行代码才能完成。而Lambda表达式却可以用简单的符号完成。此外,还可以把Lambda表达式当成一个方法的参数来用。

    Lambda表达式定义了函数式接口的唯一方法。它有两部分组成:即参数和方法体,通过->符号隔开。参数之间用","隔开,通过()来包裹。当只有一个参数的时候,括号是可以省略的。方法体可能是一条语句,或者一段语句块。由于函数式接口只有一个方法,因此方法名是省略掉的。参数的类型和返回值值都是可选的,因为这些都可以通过方法签名推测出来。

    语法是这样的:

    1
    (arguments) -> (body)

    示例:

    1
    () -> statement    // 无参方法和只有一条语句的方法体
    2
    3
    arg -> statement   // 一个参数(注意括号省略了)和方法体
    4
    5
    (arg1, arg2, ...) -> { 
    6
       body-block 
    7
    }   // 参数可以通过逗号隔开
    8
    9
    (Type1 arg1, Type2 arg2, ...) -> { 
    10
       method-body-block;
    11
       return return-value; 
    12
    }   // 多个参数和多行语句的代码块

    在其他支持函数式变量和函数式对象的语句中,Lambda被用来定义一个匿名函数。然而,在JDK8中,Lambda表达式只能定义一个单抽象方法接口的实例。

    如果你像下面这样写:

    1
    int i = () -> 5;
    2
    // error: incompatible types: int is not a functional interface

    没错,报错了。可以换成下面的就可以。

    1
    // 使用Lambda表达式来构建一个 Runnable 实例
    2
    // 换句话说,Lambda表达式返回的是一个函数式接口的实例
    3
    Runnable r1 = () -> System.out.println("run run()");
    4
       // Runnable is a functional interface
    5
       // Lambda expression is used to define the implementation of the abstract method run()
    6
    7
    // Using Lambda expression to construct an ActionListener instance
    8
    ActionListener lis = e -> System.out.println("run actionPerformed()");

    Java是一门面向对象的语言,Java中的一切都是对象(除了基本数据类型)。函数在Java中不是对象(但是对象的一部分),所以函数不能独立的存在。不像其他语言(如C++,Python或JavaScript),函数可以独立的存在,你甚至可以把一个函数像一个参数一样传递,从一个函数中返回另一个函数等等。

    JDK8的函数式接口和Lambda表达式让我们可以用一行代码(或更少的代码)就可以构造一个“函数对象”。然而,只能是有一个方法的对象。

    3.4 示例2:Runnable接口的Lambda

    Runnable接口包含了单一的抽象方法,定义如下:

    1
    @FunctionalInterface
    2
    public interface Runnable {
    3
       void run();  // public abstract
    4
    }

    因此可以通过匿名内部类或Lamda表达式来创建一个Runnable对象

    1
    public class TestRunnableLambda {
    2
       public static void main(String[] args) {
    3
          // Using an anonymous inner class
    4
          Runnable r1 = new Runnable() {
    5
             public void run() {
    6
                System.out.println("Runnable 1");
    7
             }
    8
          };
    9
          // Using a one-liner Lambda Expression for One-Method Interface
    10
          Runnable r2 = () -> System.out.println("Runnable 2");
    11
    12
          r1.run();
    13
          r2.run();
    14
       }
    15
    }

    3.5 示例3:二元运算中的Lambda

    下面定义了一个函数式接口来表示二元运算操作(如加减法):

    1
    @FunctionalInterface
    2
    public interface MyIntBinaryOperator {
    3
       int applyAsInt(int left, int right);
    4
    }

    下面的类中,方法operate()持有两个int类型的参数,和一个MyIntBinaryOperator类型的参数,返回二元运算。

    1
    public class MyMathBinaryOperation {
    2
       // Define instances of IntBinaryOperator for add, subtract, multiply and divide
    3
       public MyIntBinaryOperator add = (a, b) -> a + b;
    4
       public MyIntBinaryOperator sub = (a, b) -> a - b;
    5
       public MyIntBinaryOperator mul = (a, b) -> a * b;
    6
       public MyIntBinaryOperator div = (a, b) -> a / b;
    7
    8
       // Carry out the binary operation
    9
       public int operate(int left, int right, MyIntBinaryOperator op) {
    10
          return op.applyAsInt(left, right);
    11
       }
    12
    13
       // Test Driver
    14
       public static void main(String args[]){
    15
          MyMathBinaryOperation op = new MyMathBinaryOperation();
    16
          // Use pre-defined IntBinaryOperator
    17
          System.out.println("8 + 9 = " + op.operate(8, 9, op.add));
    18
          System.out.println("8 - 9 = " + op.operate(8, 9, op.sub));
    19
          System.out.println("8 x 9 = " + op.operate(8, 9, op.mul));
    20
          System.out.println("8 / 9 = " + op.operate(8, 9, op.div));
    21
          // Use a custom IntBInaryOperator
    22
          System.out.println("2 ^ 5 = " + op.operate(2, 5, (a, b) -> (int)Math.pow(a, b)));
    23
       }
    24
    }

    java.util.function包

    JDK8的新包java.util.function提供了相似的函数式接口,如特定类型的二元操作IntBinaryOperatorLongBinaryOperatorDoubleBinaryOperator。也有通用类型的二元运算。后面会详细讨论。

    3.6 示例4:Comparator比较器中的Lambda

    我们可以使用Collections.sort()的静态方法,来给集合对象自定义的排序。静态方法签名如下:

    1
    public static <T> void sort(List<T> list, Comparator<? super T> c)

    或者使用函数式接口Comparator的两个参数的sort方法,其中包含用以比较两个集合对象大小的抽象方法,定义如下:

    1
    package java.util;
    2
    3
    @FunctionalInterface
    4
    public interface Comparator<T> {
    5
       // Compares its two arguments for order.
    6
       // Returns a negative integer, zero, or a positive integer
    7
       //   as the first argument is less than, equal to, or greater than the second.
    8
       int compare(T o1, T o2);  // public abstract
    9
    }

    假设现在有一个以Person为元素的List对象,我们需要执行一个自定义排序,在JDK8之前使用匿名内部类的方法实现Comparator接口,JDK8之后使用Lambda表达式。

    Person.java

    1
    public class Person {
    2
       private String name;
    3
       private int age;
    4
    5
       public Person(String name, int age) {  // Constructor
    6
          this.name = name; this.age = age;
    7
       }
    8
       public String getName() {
    9
          return name;
    10
       }
    11
       public int getAge() {
    12
          return age;
    13
       }
    14
       public String toString() {
    15
          return name + "(" + age + ")";
    16
       }
    17
       // To be used in testing Consumer
    18
       public void sayHello() {
    19
          System.out.println(name + " says hello");
    20
       }
    21
    }
    1
    import java.util.*;
    2
    public class TestComparatorLambda {
    3
       public static void main(String[] args) {
    4
          List<Person> pList = new ArrayList<>();
    5
          pList.add(new Person("Peter", 21));
    6
          pList.add(new Person("Paul", 18));
    7
          pList.add(new Person("Patrick", 22));
    8
          System.out.println(pList);
    9
             // Unsorted: [Peter(21), Paul(18), Patrick(22)]
    10
    11
          // In JDK 9, you can simply write:
    12
          List<Person> pList9 = List.of(new Person("Peter", 21), new Person("Paul", 18));
    13
          System.out.println(pList9);
    14
          
    15
          // Using an anonymous inner class to create a Comparator instance
    16
          Collections.sort(pList, new Comparator<Person>() {
    17
             @Override
    18
             public int compare(Person p1, Person p2){
    19
                return p1.getName().compareTo(p2.getName());  // String's compareTo()
    20
             }
    21
          });
    22
          System.out.println(pList);
    23
             // Sort by name: [Patrick(22), Paul(18), Peter(21)]
    24
    25
          // Using a Lambda Expression to create a Comparator instance
    26
          Collections.sort(pList, (p1, p2) -> p1.getAge() - p2.getAge());
    27
          System.out.println(pList);
    28
             // Sort by age: [Paul(18), Peter(21), Patrick(22)]
    29
       }
    30
    }

    上面代码是如何工作的?

    第一个sort方法使用了匿名内部类的形式构造了Comparator接口的实例对象,而第二个sort方法使用一行Lambda表达式来构造的Comparator实例对象。

    3.7 示例5:集合

    JDK8对集合框架做了重大的改进,集成了Lambda表达式和流式API来支持函数式编程。

    用例:Filter与Reduce

    假设我们有一个由Person对象组成的List,要实现下面的功能:

    1. 遍历这个list
    2. 根据几个条件来过滤(比如age>12)
    3. 在过滤出来的对象上都运行某一操作(比如调用sayHello()方法),就被称为归约操作(reduction operation)可以让我们计算一个结果。

    代码应该能用来处理过滤任何几种条件,并且运行任何几种归约操作。

    方法1:Roll Your Own

    PersonPredicate.java:定义了一个函数式接口,用以处理过滤操作,其中包含了一个返回类型为boolean的test()方法。

    1
    @FunctionalInterface
    2
    public interface PersonPredicate {
    3
       boolean test(Person p);  // Perform this boolean test on the given Person
    4
    }

    PersonConsumer.java:定义了一个函数式接口,用来运行Person对象上的某些方法。

    1
    @FunctionalInterface
    2
    public interface PersonConsumer {
    3
       void accept(Person p);  // Run these operations on the given Person
    4
    }

    PersonsFilterReduce.java

    1
    import java.util.List;
    2
    3
    public class PersonsFilterReduce {
    4
    }

    ProcessPersons.java:我们会定义一个静态处理方法process()来执行filter-reduce操作。通过循环List<Person>,我们可以在这个测试驱动类中测试几个过滤器和规约操作。

    1
    import java.util.*;
    2
    3
    public class ProcessPersons {
    4
       // Given a List<Person>, filter with predicate, and consume.
    5
       public static void process(List<Person> pList, PersonPredicate predicate, PersonConsumer consumer) {
    6
          for (Person p : pList) {
    7
             if (predicate.test(p)) {  // Filter
    8
                consumer.accept(p);    // Reduce
    9
             }
    10
          }
    11
       }
    12
    13
       public static void main(String[] args) {
    14
          // Create a List of Person objects
    15
          List<Person> pList = new ArrayList<>();
    16
          pList.add(new Person("Peter", 21));
    17
          pList.add(new Person("Paul", 60));
    18
          pList.add(new Person("Patrick", 15));
    19
          System.out.println(pList);  // [Peter(21), Paul(60), Patrick(15)]
    20
    21
          // Pre-JDK 8: Using anonymous inner classes
    22
          ProcessPersons.process(
    23
             pList,
    24
             new PersonPredicate() {
    25
                @Override
    26
                public boolean test(Person p) {
    27
                   return p.getAge() >= 21;  // Filtering criteria
    28
                }
    29
             },
    30
             new PersonConsumer() {
    31
                @Override
    32
                public void accept(Person p) {
    33
                   p.sayHello();   // Apply this operation
    34
                }
    35
             }
    36
          );
    37
    38
          // JDK 8: Using Lambda Expressions
    39
          ProcessPersons.process(pList, p -> p.getAge() >= 21, p -> p.sayHello());
    40
       }
    41
    }

    可以看到,在JDK8中只需要一行代码,就完成了JDK8之前必须15行代码完成的事情。

    方法2:使用JDK8预定义函数式接口

    JDK8中有一个新包java.util.function,包含了很多标准的函数式接口,包括Predicate和Consumer:

    java.util.function.Predicate:

    1
    package java.util.function;
    2
    3
    @FunctionalInterface
    4
    public interface Predicate<T> {
    5
       boolean test(T t);  // Evaluates this predicate on the given object.
    6
       ......
    7
    }

    java.util.function.Consumer:

    1
    package java.util.function;
    2
    3
    @FunctionalInterface
    4
    public interface Consumer<T> {
    5
       void accept(T t);  // Run this operation on the given object.
    6
       ......
    7
    }

    为了代替上面自己撸的函数式接口,这里我们用的是通用的。

    下面添加了一个process1()方法,这里用改用通用的函数式接口Predicate<Person>和Consumer<Person>方法:

    1
    ......
    2
    import java.util.function.*;
    3
    4
    public class ProcessPersons {
    5
       ......
    6
       public static void process1(List<Person> pList, Predicate<Person> predicate, Consumer<Person> consumer) {
    7
          for (Person p : pList) {
    8
             if (predicate.test(p)) {
    9
                consumer.accept(p);
    10
             }
    11
          }
    12
       }
    13
    14
       public static void main(String[] args) {
    15
          ......
    16
          // Using JDK 8 standard functional interfaces Predicate<T> and Consumer<T>
    17
          ProcessPersons.process1(pList, p -> p.getAge() >= 21, p -> p.sayHello());
    18
       }
    19
    }

    方法3:Filter-Map-Reduce

    假设不再去直接操作过滤出的Person对象,而是执行某个操作,对Person做一些映射或转换之后。下面使用通用的函数式接口java.util.function.Function作为映射器,定义如下:

    java.util.function.Function:

    1
    package java.util.function;
    2
    3
    @FunctionalInterface
    4
    public Function<T, R> {
    5
       R apply(T t);  // Apply this mapping to the given object.
    6
       ......
    7
    }

    ProcessPersons.java:添加一个方法process2(),用来测试新方法:

    1
    import java.util.*;
    2
    import java.util.function.*;
    3
    4
    public class ProcessPersons {
    5
       ......
    6
       // Given a List, filter with predicate, apply mapper, and reduce (filter-map-reduce)
    7
       public static void process2(List<Person> pList, 
    8
                                   Predicate<Person> predicate, 
    9
                                   Function<Person, String> mapper, 
    10
                                   Consumer<String> consumer) {
    11
          for (Person p:pList) {
    12
             if (predicate.test(p)) {
    13
                String s = mapper.apply(p);  // Apply mapper to transfom Person to String
    14
                consumer.accept(s);
    15
             }
    16
          }
    17
       }
    18
    19
       public static void main(String[] args) {
    20
          ......
    21
    22
          // Using Lambda Expression
    23
          ProcessPersons.process2(
    24
             pList, 
    25
             p -> p.getAge() >= 21, 
    26
             p -> p.getName(), 
    27
             name -> System.out.println(name)
    28
          );
    29
    30
          // Using method references
    31
          ProcessPersons.process2(pList, p -> p.getAge() >= 21, Person::getName, System.out::println);
    32
       }
    33
    }

    方法引用

    在Java中引入了一个新的操作符"::",用来引用方法,而不是调用它,称之为方法引用。例如

    1
    // Method References
    2
    System.out::println
    3
    Person::getName
    4
    Person::sayHello
    5
    "xyz"::length
    6
    7
    // Constructor References
    8
    Integer::new
    9
    int[]::new

    上面的示例中,可以使用ClassName::method代替p->p.method()表达式。

    方法4:使用JDK8的流式API和管道

    JDK8为集合框架增添了新的流式API,用以支持聚合操作(如函数式编程)。这可以简化filter-map-reduce操作为一行代码。另外再也不需要明确的写for循环了。

    1
    import java.util.*;
    2
    import java.util.function.*;
    3
    4
    public class ProcessPersons {
    5
       public static void main(String[] args) {
    6
          ......
    7
          
    8
          // Using JDK 8 Stream for filter-reduce
    9
          pList.stream().filter(p -> p.getAge() >= 21).forEach(p -> p.sayHello());
    10
          pList.stream().filter(p -> p.getAge() >= 21).forEach(Person::sayHello);  // Using method reference
    11
    12
          // Using map() to extract a specific property from the object
    13
          Predicate<Person> adult = p -> p.getAge() >= 21;
    14
          pList.stream().filter(adult).map(p -> p.getName()).forEach(name -> System.out.println(name));
    15
          pList.stream().filter(adult).map(Person::getName).forEach(System.out::println);
    16
    17
          // Apply aggregate operation average(), sum() to an int property extracted via mapToInt()
    18
          System.out.println(pList.stream().filter(adult).mapToInt(p -> p.getAge()).average().getAsDouble());
    19
          System.out.println(pList.stream().filter(adult).mapToInt(Person::getAge).average().getAsDouble());
    20
          System.out.println(pList.stream().filter(adult).mapToInt(Person::getAge).sum());
    21
       }
    22
    }

    管道(Pipeline)

    一个管道就是基于集合(或数组)的操作序列,这些序列包括:

    1. 一个源:例如一个集合或数组,就像上面的List<Person>
    2. stream():用于处理一个流,这个流是从源到管道的元素集合序列
    3. 一些中间操作:例如filter(Predicate)。这个方法会输出符合条件Predicate的元素集合
    4. 一个结束操作(规约操作):如forEach()方法,将处理求得的结果。

    java.util.stream.Stream接口

    一个流就是元素的序列,在流的管道中,可以直接串行和并行两种操作。可以通过下面的两个方法创建流:

    1
    interface Collection<E> {
    2
       default Stream<E> stream()          // Returns a sequential Stream with this Collection as its source
    3
       default Stream<E> parallelStream()  // Returns a possibly parallel Stream with this Collection as its source
    4
       ......
    5
    }

    有三个原始类型的特定的流:IntStreamLongStream 和 DoubleStream

    管理链中的方法

    aCollection.stream(): 返回以这个集合为源的元素序列.

    aStream.filter(aPredicate): 用指定的Predicate条件过滤流

    1
    Stream<T> filter(Predicate<? super T> predicate)

    aStream.forEach(aConsumer): 执行一个Consumer指定的行为

    1
    Stream<T> filter(Predicate<? super T> predicate)

    aStream.map(aFunction): 用给定的Function应用映射(或者叫转换),从一个对象转换为<T,R>的map

    1
    <R> Stream<R> map(Function<? super T, ? extends R> mapper)

    aStream.mapToInt(anToIntFunction): map()方法的一个特殊形式,返回一个intStream

    1
    IntStream mapToInt(ToIntFunction<? super T> mapper)

    anIntStream.average().getAsDouble(): 计算给定流的平均值

    1
    OptionalDouble average()  // Returns an OptionalDouble for the average of this stream,
    2
    3
                              // or an empty OptionalDouble if this stream is empty.

    返回值中的java.util.OptionDouble对象, 包含了一个或多个double值。如果值存在的话, isPresent() 返回true,getAsDouble() 将返回相应的值

    anIntStream.sum(): 返回int元素的总和

    1
    int sum()  // Returns the sum of elements in this stream as int


    3.8 JDK8的java.util.function包


    3.9 JDK8的java.util.stream包


    3.10 更多关于Lambda表达式和函数式编程的内容


    4. JDK8 日期/时间(Date/Time)API

    4.1 java.time示例


    4.2 java.time.DayOfWeek和java.time.Month枚举


    5. Collection API实现

    5.1 迭代器的forEach()方法

    JDK8在java.lang.Iterable迭代器接口中添加了一个forEach()方法。由于java.util.Collection本身就是Iterable的子接口,因此forEach()也是可用的。forEach()方法是Iterable接口的默认方法,有一个Consumer类型的参数:

    1
    default void forEach(java.util.function.Consumer<? super T> action) {
    2
       Objects.requireNonNull(action);  // Ensure that action is NOT null
    3
       for (T t : this) {
    4
          action.accept(t);
    5
       }
    6
    }

    示例

    TestIterableForEach.java:

    1
    import java.util.*;
    2
    import java.util.function.*;
    3
    4
    public class TestIterableForEach {
    5
       public static void main(String[] args) {
    6
          List<Person> pList = new ArrayList<>();
    7
          pList.add(new Person("Peter", 21));
    8
          pList.add(new Person("Paul", 60));
    9
          pList.add(new Person("Patrick", 15));
    10
          System.out.println(pList);
    11
    12
          // Pre-JDK 8: Using for-each loop
    13
          for (Person p: pList) {
    14
             System.out.println(p);
    15
             System.out.println(p.getName());
    16
          }
    17
    18
          // Pre-JDK 8: Using Iterator
    19
          Iterator<Person> iter = pList.iterator();
    20
             while (iter.hasNext()) {
    21
                Person p = iter.next();
    22
                System.out.println(p.getName());
    23
             }
    24
    25
          // JDK 8 Iterable's forEach(): with Consumer anonymous inner class
    26
          pList.forEach(new Consumer<Person>() {
    27
             @Override
    28
             public void accept(Person p) {
    29
                p.sayHello();
    30
             }
    31
          });
    32
          
    33
          // JDK 8 Iterable's forEach(): with Lambda Expression
    34
          pList.forEach(p -> System.out.println(p));
    35
          pList.forEach(p -> System.out.println(p.getName()));
    36
          pList.forEach(p -> p.sayHello());
    37
    38
          // JDK Iterable's forEach(): with Method Reference
    39
          pList.forEach(System.out::println);
    40
          pList.forEach(Person::sayHello);
    41
       }
    42
    }

    注意:Iterable.forEach()不同于Stream.forEach()

    5.2 其他

    ~ java.lang.Iterabler接口的forEach()方法,前面提到的

    ~ java.util.Iterator的默认方法forEachRemaining(Consumer<? super E> action) 用来让剩余元素来执行某种操作

    ~ 接口 java.util.Collection的默认方法removeIf(Predicate<? super E> filter) 移除这个集合中满足指定条件的所有元素,这个实现了已存在的remove(Object o)和removeAll(Collection<?> c)抽象方法

    ~ 接口java.util.Collection的默认方法stream()和 parallelStream() 创建一个串行或并行的流,spliterator() 方法用来创建一个分流器,可以支持并行和串行操作

    ~ 接口 java.util.Map的默认方法compute(), merge(), remove(), replace(),等等

    ~ 接口 java.uitl.Comparator的默认方法

    more.

    6. IO实现

    TODO

    7. 并发API实现

    TODO

    8. 其他API的更新

    8.1 包装类Integer、Long和Double中的min(), max(), sum()方法

    TODO

    8.2 支持无符号int和long

    JDK8中并没有引入像C语言那样的无符号int,但是在包装类Integer和Long中可以把int和long当作无符号值来对待。例如:

    1
    public class TestUnsignedInteger {
    2
       public static void main(String[] args) {
    3
          // Pr-JDK 8
    4
          // 32-bit signed int ranges from −2,147,483,648 −(2^31) to 2,147,483,647 (2^31 – 1)
    5
          System.out.println(Integer.parseInt("2147483647"));  // max 32-bit unsigned integer
    6
          System.out.println(Integer.parseInt("-2147483648")); // min 32-bit unsigned integer
    7
          //System.out.println(Integer.parseInt("2147483648"));  // error: NumberFormatException
    8
    9
          // JDK 8
    10
          // 32-bit unsigned int ranges from 0 to 4,294,967,295 (2^32 – 1)
    11
          int i1 = Integer.parseUnsignedInt("4294967295");  // max 32-bit unsigned integer
    12
          System.out.println(i1);   // -1 (treated as signed int)
    13
          System.out.println(Integer.toUnsignedString(i1));  // 4294967295
    14
          System.out.println(Integer.toUnsignedString(-1));  // 4294967295
    15
    16
          long l1 = Long.parseUnsignedLong("18446744073709551615");  // max 64-bit unsigned integer
    17
          System.out.println(l1);  // -1 (treated as signed long)
    18
          System.out.println(Long.toUnsignedString(l1));  // 18446744073709551615
    19
          System.out.println(Long.toUnsignedString(-1));  // 18446744073709551615
    20
       }
    21
    }

    JDK 8在java.lang.Integer类中添加了静态方法用以处理无符号int值:

    static int compareUnsigned(int x, int y): 

    static int divideUnsigned(int dividend, int divisor):

    static int remainderUnsigned(int dividend, int divisor):

    static int parseUnsignedInt(...):

    static String toUnsignedString(int i):

    相似的静态方法在java.lang.Long中也存在。


    8.3 Boolean包装类中的logicalAnd(), logicalOr(), logicalXor()方法

    TODO

    8.4 java.lang.Math包中其他实用功能

    int addExact​(int x, int y):如果结果超出int取值范围会抛出异常

    long addExact​(long x, long y):如果结果超出long取值范围会抛出异常

    floorDiv​()floorMod​()

    int toIntExact​(long value):

    nextDown​(double), nextDown​(float):

    8.5 其他

    ~ 添加了jjs命令调用Nashorm的JavaScript引擎

    ~ 添加了jdeps命令用来分析类文件

    ~ JDBC-ODBC被移除了


    原文链接:JDK 8 New Feature

    参考链接:What's New in JDK 8





    https://www.gaofi.cn/article/detail/272

    展开全文
  • JDK8下载及其环境配置

    2020-04-15 09:09:31
    在网上有查找很多有关的知识,但都不太好,因为我实在是太新手了...###直接百度JDK8,选择第一个_oracle jdk 8 - Java SE Development Kit 8 - Downloads_.或者网址:https://www.oracle.com/technetwork/java/javas...

    JDK8是编程Java的必要软件,在网上有查找很多有关的知识,但都不太好,因为我实在是太新手了,那些大佬不理解新手需要什么。这里把我坎坷后的成功经验分享出来供大家参考。

    JDK8的下载

    1.直接百度JDK8,选择第一个 oracle jdk 8 - Java SE Development Kit 8 - Downloads .或者网址:https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
    注意一下:JDK8的条款生效了,不再是免费开放的了,需要注册一个Oracle账号才能下载
    可以在这下载:链接:https://pan.baidu.com/s/11aCGIjuJv6Eaiuj510Za3A 提取码:ig60
    2.进入后如图选择最下面一个(我的电脑是64位的)
    在这里插入图片描述
    3.之后下载就可以了,安装时自己选择位置,我的安装位置是 D:\JDK8,安装时会跳出来窗口让关闭什么进程,忽略就行。安装完毕后他会主动跳出来一个jre让你安装(下面第一张图),直接关闭就可以,JDK8里面自带了jre。这是安装后的目录(下面第二张图):
    在这里插入图片描述
    在这里插入图片描述

    环境配置

    1.打开电脑属性
    在这里插入图片描述
    2.打开高级系统设置
    在这里插入图片描述
    3.选择 高级-环境变量
    在这里插入图片描述
    4.在系统变量里选择新建
    如图输入 JAVA_HOME
    D:\JDK8
    在这里插入图片描述
    5.点击确定,左键点击系统设置里面的 CLASSPATH,再点击编辑(如果没有CLASSPATH就新建一个)如图输入 ,注意最前面的 .; 都不要少
    .;%JAVA_HOME%\lib;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar
    在这里插入图片描述
    6.点击系统配置里的 Path ,选择编辑,滑到最下面,点击新建,然后输入图片的最下面三行
    注意会有部分电脑需要把这三行上移到最前面,否则会报错,大部分电脑不用上移
    ;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin
    D:\JDK8\bin
    d:\JDK8\jre\bin
    在这里插入图片描述
    7.点击确认,关闭,JDK8的环境配置就完毕了,这里建议大家选择和我一样的安装路径

    测试:第一个 Java 程序 – HelloWorld

    1.在D盘新建一个文件夹 myjava. 里面新建一个txt文本,打开,输入以下代码:

    public class hello {
        public static void main(String args[]) {
        System.out.println("Hello World!");
        }
    }
    

    2.点击另存为,名字为 hello.java ,注意名字要与类的名字一样,格式为:所有文件,保存到同样的目录 D:\ myjava下。
    保存后如下图:
    在这里插入图片描述
    3.按键盘组合键:WIN键+R键,在命令行输入 cmd 就打开终端了。先输入 javac,看下显示的内容是否一样,不一样说明前面哪错了。
    在这里插入图片描述
    4.之后进入到hello.java的文件夹里面,依次输入:
    d:
    cd myjava
    如图:
    在这里插入图片描述
    5.输入: javac hello.java
    未报错,继续输入: java hello
    就会运行成功了,如图:
    在这里插入图片描述
    到此就结束啦,你回到 myjava 文件里面会发现里面多了一个 hello.class 文件,这是可执行文件。

    听说许多人(包括我)一开始下载了Eclipse的安装包后就不会点了,安装包就是Eclipse官网中间点击下载或百度后直接下载的那种,一打开会看到下面这个界面:
    在这里插入图片描述
    点击第二个就好了,然后安装完毕打开后又又一个不知道干什么的界面,这里没图,点击靠近左上角的关闭就好了,最后新建 java project 时又不知道点什么了,点击 file -> new ,选择 project 或者 others 即可,在弹出的窗口里面找到 java project。

    感谢大家借鉴!

    展开全文
  • JDK8时间类

    2019-04-15 14:16:27
    1. JDK8之前的时间日期API 1.1 java.lang.System类 public static native long currentTimeMillis(); 用于返回当前时间与1970年1月1日0:0:0之间以毫秒为单位的时间差 时间戳 1.2 java.util.Date类 两个构造器...

    1. JDK8之前的时间日期API

    1.1 java.lang.System类

    • public static native long currentTimeMillis();
      • 用于返回当前时间与1970年1月1日0:0:0之间以毫秒为单位的时间差
      • 时间戳

    1.2 java.util.Date类

    • 两个构造器

      • new Date(); —> 当前时间
      • new Date(Long 毫秒数) — > 根据毫秒数创建指定日期
    • 两个方法的使用

      • toString() 显示当前的年,月,日,时,分,秒
      • getTime() 获取当前date对象的对应的毫秒数(时间戳)
    • java.util.Date 和java.sql.Date 互相转换

      • Date date = new java.sql.Date()
      • java.sql.Date date2 = (java.sql.Date) date;
      • java.sql.Date date3 = new java.sql.Date(new Date().getTime());

    1.3 java.text.SimpleDateFormat类

    • Date类的API不易于国际化,大部分被废弃,SimpleDateFormat类 一个与语言环境有关的方式来格式化和解析时间的具体类
    • format() 方法 按照具体的格式格式化时间
    • parse() 方法将字符串解析成时间

    1.4 java.util.Calendar 日历类

    • 获取Calendar的实例
      • 使用其子类 (GregorianCalendar)的对象
      • 使用Calendar.getInstance()
    • 常用方法
      • set()
        • calendar.set(Calendar.DAY_OF_MONTH,22) —> 将日期设置为这个月的第几天
      • get()
        • calendar.get(Calendar.DAY_OF_MONTH)----->这个月的第几天,返回值是int
        • calendar.get(Calendar.DAY_OF_YEAR) —>这一年的第几天
      • add()
        • calendar.add(Calendar.DAY_OF_MONTH,3) ----> 在现有的日期上加3天
      • getTime()
        • calendar.getTime(); —> 返回Date()
      • setTime()
        • calendar.setTime(new Date()) — > 将日期设置为某日期

    2 JDK8新日期时间的API

    • 可变性 : 像日期和时间这样的类应该是不可变的,---->返回一个值,原来的对象不变
    • 偏移性 : Date中的年份是从1900开始的,而月份是从0开始的
      • 日期表示需要减 new Date(2020-1900,9-1,8) 这样才可以表示2020年9月8日
    • 格式化; 格式化日期只对Date有用,Calendar则不行
    • 线程不安全的,不能处理闰秒等
    • Java8 吸收了Joda-Time精华,开启了新的API,新的java.time包含了如下子类
      • 本地日期 LocalDate
      • 本地时间 LocalTime
      • 本地日期时间 LocalDateTime
      • 时区 ZonedDateTime
      • 持续时间 Duration

    2.1 JDK8 的新日期的API

    • java.time -包含值对象的基础包
    • java.time.chrono - 提供不同日历系统的访问
    • java.time.format - 格式化和解析时间和日期
    • java.time.temporal - 包含底层框架和扩展特性
    • java.time.zone - 包含时区支持的类

    2.2 LocalDate,LocalTime,LocalDateTime

       // LocalDate LocalTime LocalDateTime
       // 获取当前时间
       LocalDate localDate = LocalDate.now();
       LocalTime localTime = LocalTime.now();
       LocalDateTime localDateTime = LocalDateTime.now();
       System.out.println(localDate);
       System.out.println(localTime);
       System.out.println(localDateTime);
    
       // LocalDateTime  使用频率较高
       // of() 设置指定的年月日时分秒  体现不偏移性
       LocalDateTime dateTime = LocalDateTime.of(2019, 04, 10, 23, 03);
       System.out.println(dateTime);
    
       // getXxx()
       System.out.println(dateTime.getDayOfMonth());
       System.out.println(dateTime.getDayOfWeek());
       System.out.println(dateTime.getMonth());
       System.out.println(dateTime.getMinute());
       System.out.println(dateTime.getMonthValue());
    
       // withXxx   体现不可变性
       LocalDate localDate1 = localDate.withDayOfMonth(12);
       System.out.println(localDate);
       System.out.println(localDate1);
       // 设置分钟
       LocalDateTime localDateTime1 = localDateTime.withMinute(20);
       System.out.println(localDateTime);
       System.out.println(localDateTime1);
    
       // plusXxx()   当前的时间做加法
       LocalDate localDate2 = localDate.plusMonths(1);
       System.out.println(localDate);
       System.out.println(localDate2);
       
       // 结果
       2019-04-10
       23:14:42.994
       2019-04-10T23:14:42.994
       2019-04-10T23:03
       10
       WEDNESDAY
       APRIL
       3
       4
       2019-04-10
       2019-04-12
       2019-04-10T23:14:42.994
       2019-04-10T23:20:42.994
       2019-04-10
       2019-05-10
    

    2.3 Instant 瞬时

    • 时间线上的一个瞬时点,这可能用于记录应用程序的事件时间戳
    • Instant的精度可以达到纳秒级
       // Instant 和java.util.Date 很像
       
       // 获取本初子午线的标准时间
       Instant now = Instant.now();
       System.out.println(now);    // 2019-04-10T15:19:51.640Z
       
       // 东八区的时间       偏移量
       OffsetDateTime offsetDateTime = now.atOffset(ZoneOffset.ofHours(8));
       System.out.println(offsetDateTime); // 2019-04-10T23:21:47.598+08:00
       
       // 距离1970年1月1日0:0:0(UTC) 开始的毫秒数
       long l = now.toEpochMilli();
       System.out.println(l);
       
       // 根据偏移量获取时间
       Instant instant = Instant.ofEpochMilli(l);
       System.out.println(instant);
       
       --------------------结果------------------------
       2019-04-10T15:23:52.587Z
       2019-04-10T23:23:52.587+08:00
       1554909832587
       2019-04-10T15:23:52.587Z
    

    2.4 java.time.format.DateTimeFormatter 格式化或者解析时间

    • 预定义的标准格式 如:ISO_LOCAL_DATE,ISO_LOCAL_DATE_TIME,ISO_LOCAL_TIME
      *

    • 本地化相关的格式 如:ofLocalizedDateTime(FormatStyle.LONG)

    • 自定义的格式 如:ofPattern("yyyy-MM-dd HH:mm:ss E")

           // 1. 预定义的标准格式  ISO_LOCAL_DATE_TIME,ISO_LOCAL_DATE,ISO_LOCAL_TIME
           // 格式化日期 --- > 字符串
           DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
           LocalDateTime now = LocalDateTime.now();
           System.out.println(formatter.format(now));  //2019-04-14T11:26:07.555
           System.out.println(now);    //2019-04-14T11:26:07.555
    
           // 字符串--->时间
           TemporalAccessor parse = formatter.parse("2019-04-14T11:26:07.555");
           System.out.println(parse);
    
           // 方式二
           // 本地化相关格式      ofLocalizedDateTime()
           // FormatStyle.LONG     /   FormatStyle.MEDIUM  /   FormatStyle.SHORT
           DateTimeFormatter dateTime = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);
           System.out.println(dateTime.format(now));       //2019年4月14日 上午11时30分54秒
    
    
           // 方式三 自定义格式
           // ofPattern("yyyy-MM-dd hh:mm:ss") -->和SimpleDateFormat相似
    

    3. 其他API

    • ZoneId :该类包含了所有的时区信息,一个时区的Id,如Europe/Paris
    • ZoneDateTime: 一个在ISO-8601日历系统时区的时间
      • 其中每个时区都有对应的Id,每个地区Id都有"{区域}/{城市}" 例如 Asia/Shanghai
    • Clock :使用时区提供的当前及时,日期和时间的访问的时钟
    • 持续时间Duration,用于计算两个"时间"的间隔
    • 日期间隔: Period ,用于计算两个"日期"的间隔
    • TemporalAdjuster : 时间校正器
    • TemporalAdjusters: 通过该类的静态方法(firstDayOfXxx()/lastDayOfXxx()/nextXxx()) 提供大量的常用TemporalAdjuster的实现
       //ZoneId:类中包含了所有的时区信息
       // ZoneId的getAvailableZoneIds():获取所有的ZoneId
       Set<String> zoneIds = ZoneId.getAvailableZoneIds();
       for (String s : zoneIds) {
       System.out.println(s);
       }
       // ZoneId的of():获取指定时区的时间
       LocalDateTime localDateTime = LocalDateTime.now(ZoneId.of("Asia/Tokyo"));
       System.out.println(localDateTime);
       //ZonedDateTime:带时区的日期时间
       // ZonedDateTime的now():获取本时区的ZonedDateTime对象
       ZonedDateTime zonedDateTime = ZonedDateTime.now();
       System.out.println(zonedDateTime);
       // ZonedDateTime的now(ZoneId id):获取指定时区的ZonedDateTime对象
       ZonedDateTime zonedDateTime1 = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
       System.out.println(zonedDateTime1);
       
       //Duration:用于计算两个“时间”间隔,以秒和纳秒为基准
       LocalTime localTime = LocalTime.now();
       LocalTime localTime1 = LocalTime.of(15, 23, 32);
       //between():静态方法,返回Duration对象,表示两个时间的间隔
       Duration duration = Duration.between(localTime1, localTime);
       System.out.println(duration);
       System.out.println(duration.getSeconds());
       System.out.println(duration.getNano());
       LocalDateTime localDateTime = LocalDateTime.of(2016, 6, 12, 15, 23, 32);
       LocalDateTime localDateTime1 = LocalDateTime.of(2017, 6, 12, 15, 23, 32);
       Duration duration1 = Duration.between(localDateTime1, localDateTime);
       System.out.println(duration1.toDays());
       
       //Period:用于计算两个“日期”间隔,以年、月、日衡量
       LocalDate localDate = LocalDate.now();
       LocalDate localDate1 = LocalDate.of(2028, 3, 18);
       Period period = Period.between(localDate, localDate1);
       System.out.println(period);
       System.out.println(period.getYears());
       System.out.println(period.getMonths());
       System.out.println(period.getDays());
       Period period1 = period.withYears(2);
       System.out.println(period1);
       
       // TemporalAdjuster:时间校正器
       // 获取当前日期的下一个周日是哪天?
       TemporalAdjuster temporalAdjuster = TemporalAdjusters.next(DayOfWeek.SUNDAY);
       LocalDateTime localDateTime = LocalDateTime.now().with(temporalAdjuster);
       System.out.println(localDateTime);
       // 获取下一个工作日是哪天?
       LocalDate localDate = LocalDate.now().with(new TemporalAdjuster() {
       @Override
       public Temporal adjustInto(Temporal temporal) {
       LocalDate date = (LocalDate) temporal;
       if (date.getDayOfWeek().equals(DayOfWeek.FRIDAY)) {
       return date.plusDays(3);
       } else if (date.getDayOfWeek().equals(DayOfWeek.SATURDAY)) {
       return date.plusDays(2);
       } else {
       return date.plusDays(1);
       }
       }
       });
       System.out.println("下一个工作日是:" + localDate);
    
    展开全文
  • JDK8版本下载 Oracle现在实行登陆下载.所以如果你想用最新版本的jdk.那就需要未雨绸缪早早注册个账号 Oracle官方地址:https://www.oracle.com/cn/index.html 往上滑轮可以国际化成中文界面,这是通过正...

    JDK所有版本下载:  https://www.oracle.com/technetwork/java/archive-139210.html

    JDK8版本下载

    Oracle现在实行登陆下载.所以如果你想用最新版本的jdk.那就需要未雨绸缪早早注册个账号

    Oracle官方地址:https://www.oracle.com/cn/index.html

    往上滑轮可以国际化成中文界面,这是通过正常来下的.

    还有一种就靠获取路径来下免去登陆的麻烦,具体在下面的博文中:

    https://blog.csdn.net/wanghaiping1993/article/details/52287722

     

    提供下载链接

    JDK1.81:

    http://download.oracle.com/otn-pub/java/jdk/8u181-b13/96a7b8442fe848ef90c96a2fad6ed6d1/jdk-8u181-windows-x64.exe

    JDK1.81演示demo

    http://download.oracle.com/otn-pub/java/jdk/8u181-b13-demos/96a7b8442fe848ef90c96a2fad6ed6d1/jdk-8u181-windows-x64-demos.zip

    展开全文
  • 1、语言新特性1.1接口新增默认方法与静态方法 1.1.1 Interface Default Method:For creating a default method in java interface, we need to use “default” keyword with the method ...package com.java8.d...
  • jdk8-linux

    2020-07-30 23:32:02
    Linux版的JDK8,java的开发环境,省得访问官网下载了。
  • jdk7与jdk8

    2020-07-30 23:31:23
    由于上传文件不能大于110MB,下载文本里给出云盘下载link, win(jdk7,jdk8) linux(jdk7)
  • jdk8虽然出现很久了,但是可能我们还是有很多人并不太熟悉,本文主要就是介绍说明一些jdk8相关的内容。 主要会讲解: lambda表达式 方法引用 默认方法 Stream 用Optional取代null 新的日志和时间 CompletableFuture...
  • jdk8 windows

    2020-07-30 23:33:33
    window版jdk8 java开发
  • JDK8新特性一览

    2017-04-20 11:41:35
    Jdk8新特性.png 下面对几个常用的特性做下重点说明。 一、Lambda表达式 1.1 函数式编程 百科介绍:...
  • 作为一名Java程序员,多多少少有些技能是必备的,例如...现在JDK10都出来了,所以我们也要紧跟着技术的潮流走,JDK8现在肯定已经比以前成熟很多了,所有我们在这里采用的就是JDK8。首先我们得在官网上面先下载JDK8 ...
  • 其实这个问题本身就是有问题的,因为收费的并不是JDK8 , 而是JDK8后续的update (更新) 。 什么是update? 如果你下载过JDK, 就会看到那些8u191, 8u192这样的东西,191,192就是update 的编号。 这些update中通常会...
  • 有时候某个插件只支持jdk7,而电脑又安装的是jdk8,这时需要卸载jdk8再装jdk7,当想用jdk8时又得切换回去。能不能同时安装jdk7和jdk8呢?当然可以,步骤如下: 1.下载并安装jdk7和jdk8 下载地址 jdk7百度网盘...
  • JDK8到JDK11,带来了哪些新特性新变化 文章目录从JDK8到JDK11,带来了哪些新特性新变化写在前面下载链接Stringlines()repeat(int)isBlank()strip()/stripLeading()/stripTrailing()CharSequencecompare...
  • linux安装jdk8

    2020-04-15 13:21:19
    目录 1.下载jdk8 2.源码包解压 3.配置jdk环境变量 4.测试是否安装成功 操作系统:Centos6.4 64位 工具:Xftp5、Xshell5 1.下载jdk8 方法一:官网手动下载 下载Linux环境下的jdk1.8 ...
  • JDK8安装教程

    2019-06-13 10:31:56
    我写这文章已经升级到java12,那不太熟悉所以我在网上搜索了JDK8的. 以下是安装JDK8的截图 确定之后,单击“下一步”。 注:当提示安装JRE时,可以选择不要安装。 2、配置环境变量: 对于Java程序开发而言,...
  • jdk10和jdk8共存和快速切换 某次空闲时间我我把jdk升级到了10(原先版本是8),后来因为项目需求,要用到jdk8,但是我又不想卸载掉10,于是想到了jdk共存,按照百度经验操作,发现不管怎么样都是jdk10 原因如下 首先...
1 2 3 4 5 ... 20
收藏数 1,148,594
精华内容 459,437
关键字:

jdk8