学习Java8看这篇文章就够了

Java8 高效编程

    • 一、Lambda表达式
      • 1.Lambda表达式的组成
      • 2.使用Lambda表达式的条件
        • 什么是函数式接口?
        • java常用的几个函数式接口:
        • 如何把函数式接口写成Lambda表达式
      • 3.使用Lambda表达式
      • 4.更多的函数式接口
      • 5.使用Lambda表达式访问外部变量
      • 5.方法引用
      • 6.构造函数
        • 多个构造函数,使用自定义函数接口:
    • 二、Spring流API
      • 1.基本概念
        • 获取流:
        • 流只能被使用一次
        • 中间操作和终端操作
      • 2.使用流
        • 筛选和切片
          • filter过滤操作
          • distinct筛选去重
          • limit截断
          • skip跳过
        • 映射
          • map映射
          • flatmap映射
        • 查找和匹配
          • anyMatch
          • allMatch
          • noneMatch
          • findAny
          • findFirst
        • 归约
      • 3.数值流
      • 4.构建流
        • Stream.of
        • Arrays.stream
        • 无限流
      • collect
        • 获取数量:
        • 获取最大最小值:
          • 求和:
          • 平均数:
        • 同时获取:
          • 连接字符串:
        • 归纳
        • 分组
        • 分区
    • 三、接口的静态方法和默认方法
      • 1.静态方法
      • 2.默认方法
    • 四、Optional
      • 1.创建Optional对象
        • 创建空对象
        • 创建一个非Null对象
        • 创建一个可以Null值对象
      • 2.使用Optional检查空指针
      • 3.Optional的方法
      • 4.基础类型的Optional
    • 五、日期和时间API
      • 1.Java8中新增的时间日期类
      • 2.LocalDate日期API
      • 3.LocalTime时间API
      • 4.LocalDateTime日期时间函数
      • 5.Instant时间戳
      • 6.获取时间和日期间的间隔
      • 7.TemporalAdjuster

一、Lambda表达式

1.Lambda表达式的组成

参数列表
箭头
Lambda主体
比如:
(String s) -> s.length()

2.使用Lambda表达式的条件

使用lambda表达式要满足函数式接口。

什么是函数式接口?

函数式接口,就是只定义了一个抽象方法的接口。

java常用的几个函数式接口:

  • java.util.function.Predicate
public interface Predicate<T> {
	boolean test(T t);
}

这个接口的意思是接收一个泛型对象T,返回true或者false。
用实现这个接口的方式来表达类似于:

public class MyObj implements Predicate<T> {
	public boolean test (T t) {
		// 代码执行逻辑...
		return true // 函数一个返回 true 或者 false
	}
}
  • java.util.Comparator
public interface Compartor<T> {
	int compare(T o1, T o2);
}
  • java.lang.Runnable
public interface Runnable {
	public abstract void run();
}
  • java.util.concurrent.Callable
public interface Callable<V> {
	V call() throw Exception;
}

如何把函数式接口写成Lambda表达式

  • 例一
    如:
public interface Runnable {
	public abstract void run();
}

写成Lambda表达式后的接口为:

 Runnable r = () -> System.out.println("hello lambda!");
 r.run();

等同于:

Runnable r1 = new Runnable() {

    @Override
    public void run() {
        System.out.println("hello lambda!");
    }
};
r1.run();
  • 例二
    如:
public class Main {

    public static void main(String[] args) {
        // 获取数组中所有偶数
        int arr[] = {1, 2, 3, 4, 5, 6,  7, 8};
        // 参数传递一个lambda表达式 相当于一个匿名实现类 但是这个实现类只有一个抽象函数
        // 否则这个方法体不知道给那个要实现的方法...
        List<Integer> evenNumber = getEvenNumber(arr, (Integer i) -> i % 2 == 0);
        System.out.println(evenNumber);

    }

    // 参数是一个接口
    public static List<Integer> getEvenNumber(int[] arrs , Predicate<Integer> p) {
        List<Integer> result = new ArrayList<>();
        for (int i = 0; i < arrs.length; i++) {
            if (p.test(arrs[i])) {
                result.add(arrs[i]);
            }
        }
        return result;
    }

}

3.使用Lambda表达式

  • Predicate
@FunctionalInterface
public interface Predicate<T> {
	boolean test(T t);
}

示例:

public class Java8 {

    @Test
    public void testPredicate() {
        List<Integer> array = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
        List<Integer> filter = filter(array, (Integer i) -> i >= 4);
        System.out.println(filter);

    }

    public static <T> List<T> filter(List<T> arr, Predicate<T> p) {
        List<T> list = new ArrayList<T>();
        for (T t: arr) {
            if (p.test(t)) {
                list.add(t);
            }
        }
        return list;
    }
}
  • Consumer
@FunctionalInterface
public interface Consumer<T> {
	void accept(T t);
}

示例:

@Test
public void testConsumer() {
     Consumer<String> consumer = (String s) -> System.out.println(s);
     accept("hello java 8", consumer);
 }

 public static void accept(String msg, Consumer<String> consumer) {
     consumer.accept(msg);
 }
  • Function
@FunctionalInterface
public interface Function<T, R> {
	R apply(T t);
}

示例:

 @Test
 public void testFunction() {
      Function<Integer, String> fn = (Integer i) -> "hello " + i;
      String apply = apply(fn);
      System.out.println(apply);
  }

  public static String apply(Function<Integer, String> fn) {
      return fn.apply(12);
  }

4.更多的函数式接口

  • Predicate
@FunctionalInterface
public interface Predicate<T> {
	boolean test(T t);
}
  • Consumer
@FunctionalInterface
public interface Consumer<T> {
	void accept(T t);
}
  • Function
 */
@FunctionalInterface
public interface Function<T, R> {
	R apply(T t);
}
  • Supplier
@FunctionalInterface
public interface Supplier<T> {
    T get();
}

  • UnaryOperator
    继承Function,所以有T apply(T t);
@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {
}
  • BinaryOperator
    继承BiFunction,所以有T apply(T t, T u);
@FunctionalInterface
public interface BinaryOperator<T> extends BiFunction<T,T,T> {
}
  • BiPredicate
@FunctionalInterface
public interface BiPredicate<T, U> {
    boolean test(T t, U u);
}
  • BiConsumer
@FunctionalInterface
public interface BiConsumer<T, U> {
    void accept(T t, U u);
 }
  • BiFunction
@FunctionalInterface
public interface BiFunction<T, U, R> {
    R apply(T t, U u);
}

5.使用Lambda表达式访问外部变量

在Lambda表达式中访问外部变量,**外部变量(这里指的是局部变量)**应该是不能改变的,或者说是final的,比如:
这个是正确的:

@Test
public void testVariable() {
    int i = 10;
    Runnable rn = () -> System.out.println(i);
}

这个是错误的,因为改变了变量i的值:

@Test
public void testVariable() {
     int i = 10;
     Runnable rn = () -> System.out.println(i);
     i = 20;
 }

原因:原来的线程局部变量i,i使用完后可能会被回收,Lambda是在另一个线程中的,访问的是i的副本,所以i不应该改变。

5.方法引用

排序的例子:

@Test
public void testMethod() {
    List<Apple> apples = new ArrayList();
    apples.add(new Apple("red", 10));
    apples.add(new Apple("red", 20));
    apples.add(new Apple("red", 30));
    apples.add(new Apple("red", 40));
    // 方式1
    apples.sort((a, b) -> a.getWeight().compareTo(b.getWeight()));
    // 方式2
    apples.sort(comparing((Apple a) -> a.getWeight()));
    // 方式3
    apples.sort(comparing(Apple::getWeight));
    
}

例子中的方法引用:
(Apple a) -> a.getWeight()的方法引用就是:Apple::getWeight

  • 指向静态方法的方法引用
    Integer::parseInt
  • 指向任意类型实例方法的方法引用
    String::length
  • 指向现有对象实例方法的方法引用
    Apple::getWeight
    学习Java8看这篇文章就够了_第1张图片

6.构造函数

@Test
public void testSupplier() {
    // 调用无参构造函数
    Supplier<Apple> appleSupplier = Apple::new;
    Apple apple = appleSupplier.get();
    System.out.println(apple);
    // 调用构造函数是 Integer的那个
    Function<Integer, Apple> appleFunction = Apple::new;
    Apple apply = appleFunction.apply(100);
    System.out.println(apply);
}

Supplier appleSupplier = Apple::new;等价于Supplier appleSupplier = () -> new Apple();
Function appleFunction = Apple::new;等价于Function appleFunction = (weight) -> new Apple(weight);

@Test
public void testSupplier() {
    // 调用无参构造函数
    Supplier<Apple> appleSupplier = Apple::new;
    Apple apple = appleSupplier.get();
    // 等价于
    Supplier<Apple> a = new Supplier() {
        @Override
        public Object get() {
            return new Apple();
        }
    };
    
    
    // 调用构造函数是 Integer的那个
    Function<Integer, Apple> appleFunction = Apple::new;
    Apple apply = appleFunction.apply(100);
    // 等价于
    Function<Integer, Apple> f = new Function<Integer, Apple>() {
        @Override
        public Apple apply(Integer integer) {
            return new Apple(integer);
        }
    };
    
}

应用示例:

@Test
public void test() {
    List<Integer> weight = Arrays.asList(10, 20, 30, 40, 50);
    List<Apple> apple = createApple(weight, Apple::new);
    System.out.println(apple);
}

public static List<Apple> createApple(List<Integer> weight, Function<Integer, Apple> fn) {
    List<Apple> apples = new ArrayList<>();
    for (Integer i: weight) {
        apples.add(fn.apply(i));
    }
    return apples;
}

两个构造函数:

 @Test
public void twoParametersConstructor() {
    BiFunction<String, Integer, Apple> appleBiFunction = Apple::new;
    Apple redApple = appleBiFunction.apply("red", 10);
    System.out.println(redApple);
    // 等价于
    BiFunction<String, Integer, Apple> appleBiFunction1 = new BiFunction<String, Integer, Apple>() {
        @Override
        public Apple apply(String s, Integer integer) {
            return new Apple(s, integer);
        }
    };
    Apple greenApple = appleBiFunction1.apply("green", 30);
    System.out.println(greenApple);
}

多个构造函数,使用自定义函数接口:

public interface InterfaceApple<T, U, V, R> {
	// 三个参数的构造函数 
    R apply(T t, U u, V v);
}

应用:

@Test
public void threeParametersConstructor() {
    InterfaceApple<String, Integer, String, Apple> apple = Apple::new;
    Apple apply = apple.apply("red", 10, "green apple");
    System.out.println(apply);
}

二、Spring流API

1.基本概念

获取流:

@Test
public void testStream1() {
     List<String> strs = Arrays.asList("java", "in", "action");
     Stream<String> stream = strs.stream();
     stream.forEach(System.out::println);
 }

流只能被使用一次

流只能被操作一次,操作完后流就被关闭了。

@Test
public void testStream1() {
     List<String> strs = Arrays.asList("java", "in", "action");
     Stream<String> stream = strs.stream();
     stream.forEach(System.out::println);
     // 这里两次操作这个流就会报错
     stream.forEach(System.out::println);
 }

中间操作和终端操作

一个流执行一个方法返回一个新流的操作是中间操作,如果返回一个不是一个流的值或者void,那么这个方法就是终端操作。例如:

@Test
public void testStream1() {
    List<String> strs = Arrays.asList("java", "in", "action");
    Stream<String> stream = strs.stream();
    stream.filter(s -> s.length() > 3).forEach(System.out::println);
}

上面的filter方法执行后返回的就是一个stream流,这就是一个中间操作,而forEach返回的是void而不是一个新流,这就是一个终端操作。

2.使用流

筛选和切片

filter过滤操作

filter方法,接收一人Predicate接口子类,返回一个满足条件的新流。

@Test
public void filter() {
    List<Dish> list = menu.stream()
            // 接收一个Predicate,接收一个boolean类型
            .filter(d -> d.getCalories() > 400)
            .collect(Collectors.toList());
    System.out.println(list);
}
distinct筛选去重

distinct会根据元素的hashCode和equalse方法返回一个新流。

@Test
public void distinct() {
    List<Integer> numbers = Arrays.asList(1, 2, 1, 4, 2, 6, 4, 8);
    List<Integer> list = numbers.stream()
            // 去重,通过比较equals和hashCode方法
            .distinct()
            .collect(Collectors.toList());
    System.out.println(list);
}
limit截断

limit方法接收一个long类型数值,从前向后截断指定个数的元素并,并返回对应的一个新流。

 @Test
public void limit() {
    List<Integer> numbers = Arrays.asList(1, 2, 1, 4, 2, 6, 4, 8);
    List<Integer> list = numbers.stream()
            // 截断,接收一个long类型的长度
            .limit(2)
            .collect(Collectors.toList());
    System.out.println(list);
}
skip跳过

与limit方法相反,skip方法接收一个long类型参数,表示跳过前面指定数值的元素,保留后面的元素。

 @Test
 public void skip() {
     List<Integer> numbers = Arrays.asList(1, 2, 1, 4, 2, 6, 4, 8);
     List<Integer> list = numbers.stream()
             // 跳过前两个元素
             .skip(2)
             .collect(Collectors.toList());
     System.out.println(list);
 }

映射

map映射

map方法可以映射生成一个新的流,.map(Dish::getName)就是生成一个以name为值的新流,.map(String::length)把name为值的新流生成一个name的长度的新流。

@Test
public void map() {
    List<Integer> collect = menu.stream()
            .map(Dish::getName)
            .map(String::length)
            .collect(Collectors.toList());
    System.out.println(collect);
}
flatmap映射

.map(d -> d.split(""))把字符串分割成了两数组,.flatMap(Arrays::stream)把每个流中的每个元素分别映射成一个流。然后把所有的流连接起来成为一个流。

@Test
public void flatMap() {
    String[] strs = {"hello", "world"};
    List<String> collect = Arrays.stream(strs)
            .map(d -> d.split(""))
            .flatMap(Arrays::stream)
            .distinct()
            .collect(Collectors.toList());
    System.out.println(collect); // [h, e, l, o, w, r, d]
}

感受下面的例子:

@Test
public void testFlatmap() {
     List<Integer> ints1 = Arrays.asList(1, 2, 3);
     List<Integer> ints2 = Arrays.asList(3, 4);
     List<int[]> collect = ints1.stream()
             .flatMap(d ->
                     ints2.stream().
                             map(j -> new int[]{d, j})
             )
             .collect(Collectors.toList());
 }

.flatMap(d ->ints2.stream().map(j -> new int[]{d, j}) )d ->ints2.stream().map(j -> new int[]{d, j})会生成3个流,这三个流会被flatMap合并成一个流,这个流再被.collect(Collectors.toList());转换成list。

查找和匹配

anyMatch

查找是否有一个匹配,返回值是一个boolean类型

@Test
public void anyMatch() {
	// 只要有一个对象的d.getCalories()大于400,就返回true
    boolean b = menu.stream().anyMatch(d -> d.getCalories() > 400);
}
allMatch

查找是否全部匹配

@Test
public void allMatch() {
	// 只有全部大于400 才返回true
     boolean b = menu.stream().allMatch(d -> d.getCalories() > 400);
     System.out.println(b);
 }
noneMatch

查找是否没有匹配的

@Test
public void noneMatch() {
	// 没有大于4000的就返回true
    boolean b = menu.stream().noneMatch(d -> d.getCalories() > 4000);
    System.out.println(b);
}
findAny

返回任一元素

@Test
public void findAny() {
    // findAny 返回流中的元素,返回类型是Optional容器类
    List<Integer> numbers = Arrays.asList(2, 3, 4, 5, 6, 7);
    Optional<Integer> any = numbers.stream().findAny();
}
findFirst

查找第一个元素

@Test
public void findFirst() {
    // 查找第一个元素
    List<Integer> numbers = Arrays.asList(2, 3, 4, 5, 6, 7);
    Optional<Integer> first = numbers.stream().findFirst();
    // 如果 Optional 中在就执行
    first.ifPresent(System.out::println);
}

归约

@Test
public void reduce() {
        List<Integer> numbers = Arrays.asList(2, 3, 4, 5, 6);
        Integer reduce = numbers.stream()
                // 第一个参数 0 是初始值 依次执行0+2=2 2+3=5 5+4=9 9+5=14 14+6=20,也即a依次为0,2,5,9,14
                .reduce(0, (a, b) -> a + b);
        // 直接使用Integer的sum方法
        reduce = numbers.stream().reduce(0, Integer::sum);
        System.out.println(reduce);
    }

如果不指定初始值返回Optional对象Optional sum = numbers.stream().reduce((a, b) -> a + b);
用来计算最小值:

numbers.stream().reduce(Integer::min);

3.数值流

数值流:IntStream、DoubleStream、LongStream,与Stream等相比减少了自动拆箱的过程。而且能直接使用sum等操作。

@Test
public void test() {
    // Stream
    Stream<Integer> integerStream = ps.stream().map(P::getNumber);
    // IntStream
    IntStream intStream = ps.stream().mapToInt(P::getNumber);
    // Stream 与 IntStream 相比 少了自动拆箱的过程,提高了效率
}

求和:

@Test
public void test() {
    // IntStream
    IntStream intStream = ps.stream().mapToInt(P::getNumber);
    // Stream 与 IntStream 相比 少了自动拆箱的过程,提高了效率
    int sum = intStream.sum();
    System.out.println(sum);
}

数值流转换成普通流boxed

@Test
public void test() {
   IntStream intStream = ps.stream().mapToInt(P::getNumber);
   Stream<Integer> boxed = intStream.boxed();
}

求最大值操作:

@Test
public void test() {
    IntStream intStream = ps.stream().mapToInt(P::getNumber);
    // 获取最大值
    OptionalInt max = intStream.max();
    // 如果存在 就是最大值 否则就是 30
    int i = max.orElse(30);
    System.out.println(i);
}

4.构建流

Stream.of

通过Stream.of接收一组数据创建流。

 @Test
 public void streamOf() {
     Stream<String> a = Stream.of("a", "ab", "abc", "abcd");
     a.map(String::toUpperCase).forEach(System.out::println);
 }

Arrays.stream

通过Arrays.stream接收一个数组创建流。

@Test
public void arraysStream() {
    int[] a = new int[] {1, 2, 3, 4, 6};
    IntStream stream = Arrays.stream(a);
    stream.forEach(System.out::println);
}

无限流

Stream.iterate生成无限流:


@Test
public void streamIterate() {
    Stream.iterate(0, n -> n + 2)
            .limit(3)
            .forEach(System.out::println);
}

Stream.generate生成无限流:

@Test
public void streamGenerate() {
    Stream.generate(() -> 1).limit(5).forEach(System.out::println);
}

collect

Collectors提供了很多工厂方法

获取数量:

@Test
public void collectors() {
    Long collect = menu.stream().collect(Collectors.counting());
    long count = menu.stream().count();
}

获取最大最小值:

@Test
public void minOrMax() {
    Comparator<Dish> comparing = comparing(Dish::getCalories);
    Optional<Dish> collect = menu.stream().collect(Collectors.maxBy(comparing));
    Optional<Dish> collect1 = menu.stream().collect(Collectors.minBy(comparing));
    collect.ifPresent(System.out::println);
}
求和:
@Test
public void summingInt() {
    Integer collect = menu.stream().collect(Collectors.summingInt(Dish::getCalories));
    System.out.println(collect);
}
平均数:
@Test
public void average() {
   Double collect = menu.stream().collect(Collectors.averagingInt(Dish::getCalories));
   System.out.println(collect);
}

同时获取:

@Test
public void summarizing() {
    IntSummaryStatistics collect = menu.stream().collect(Collectors.summarizingInt(Dish::getCalories));
    double average = collect.getAverage();
    int max = collect.getMax();
    int min = collect.getMin();
    long sum = collect.getSum();
}
连接字符串:
@Test
public void joining() {
    String collect = menu.stream().map(Dish::getName).collect(Collectors.joining());
    // 使用分割符
    String collect1 = menu.stream().map(Dish::getName).collect(Collectors.joining(","));
    System.out.println(collect);
    System.out.println(collect1);
}

归纳

@Test
public void collectReduce() {
    menu.stream().collect(Collectors.reducing(0, Dish::getCalories, (i, j) -> i + j));
}

分组

@Test
public void groupingBy() {
    Map<Dish.Type, List<Dish>> collect = menu.stream().collect(Collectors.groupingBy(Dish::getType));
    System.out.println(collect);
}

自定义分组:

@Test
public void groupingBy1() {
    Map<String, List<Dish>> collect = menu.stream().collect(Collectors.groupingBy(dish -> {
        if (dish.getCalories() > 400) return "123";
        else if (dish.getCalories() > 800) return "456";
        else return "789";
    }));
    System.out.println(collect);
}

多级分组:

@Test
public void groupingBy2() {
    Map<Integer, Map<String, List<Dish>>> collect = menu.stream().collect(Collectors.groupingBy(Dish::getCalories, Collectors.groupingBy(dish -> {
        if (dish.getCalories() > 400) return "123";
        else if (dish.getCalories() > 800) return "456";
        else return "789";
    })));
    System.out.println(collect);
}

分组第二个参数:

@Test
public void groupingBy3() {
    Map<Dish.Type, Long> collect = menu.stream()
            .collect(Collectors.groupingBy(Dish::getType, Collectors.counting()));
    System.out.println(collect); // {FISH=2, MEAT=3, OTHER=4}
}

分区

Collectors.partitioningBy接收boolean值,通过属性的true和false来筛选:

@Test
public void partitioningBy() {
    Map<Boolean, List<Dish>> collect = menu.stream().collect(Collectors.partitioningBy(Dish::isVegetarian));
    System.out.println(collect);
}

三、接口的静态方法和默认方法

1.静态方法

1.在接口中的静态方法和类中的静态方法一样是可以通过接口名直接调用的。
2.实现类实现了接口,实现类不能调用静态方法。(类的继承,子类是可以调用父类中的静态方法的,接口继承也不能调用 )

2.默认方法

如果一个接口确定被许多实现者实现了,然后这个接口需要添加新的方法,那么所有实现了这个接口的类都要为其添加一个新的方法的实现。default可以在接口中添加一个有方法体的方法,而且实现类不需要实现这个方法。

四、Optional

1.创建Optional对象

创建空对象

 // 创建一个空的Optional对象
 Optional<Person> person = Optional.empty();

创建一个非Null对象

要注意的是如果of()方法接收的对象是一个 null值,程序会报错。

 // 创建一个非null的Optional
 Person p = new Person();
 p.setUsername("tom");
 p.setAge(10);
 Optional<Person> person = Optional.of(p);

创建一个可以Null值对象

通过of()方法创建的Optional对象如果接收的是一个null值是会报错的,如果要接收一个为null的对象,可以用方法ofNullable()方法。这个方法的意思是可以接收一个为null的对象,当然也可以接收一个对象不为null。

// 创建一个可以为Null的Optional对象
Person p = null;
Optional<Person> person = Optional.ofNullable(p);

2.使用Optional检查空指针

map方法,可以用来获取一次对象。

 Person p = new Person();
 p.setAge(10);
 p.setUsername("Tom");
 Address address = new Address();
 City city1 = new City();
 city1.setName("sz");
 address.setCity(city1);
 p.setAddress(address);
 Optional<Person> p1 = Optional.of(p);
 // 从Optional中获取对象
 Optional<City> city = p1.map(x -> p.getAddress()).map(a -> a.getCity());
 // 检查是否存在
 System.out.println(city.isPresent());

3.Optional的方法

  • get():返回Optional中的值,如果Optional中没有值就会抛出异常
  • orElse(T t):如果Optional中没有值,那么就使用orElse方法指定的值 t
  • orElseGet:(Supplier t):如果Optional中没有值就通用Supplier
  • orElseThrow(Supplier exceptionSupplier):没有值是执行抛出异常
  • isPresent():值存在返回true,否则返回false
  • ifPresent(Consumer consumer):值存在是执行Consumer
  • filter:过滤操作
  • empty:返回一个空的Optional实例
  • map:操作值
  • flatMap:操作值
  • of:生成Optional对象,不能接收null值
  • ofNullable:生成Optional对象,可接收null值

Optional可以作与Stream类似的操作,例如map(),flatMap,filter等。

4.基础类型的Optional

OptionalInt、OptionalDouble、OptionalLong、OptionalBoolean,但是基础类Optional不支持map等操作。

五、日期和时间API

1.Java8中新增的时间日期类

LocalDate:操作日期API
LocalTime:操作时间API
Instant:
Duration:
Period:

2.LocalDate日期API

创建日期对象以及获取日期信息:

// 生成指定时间的日期对象
LocalDate time = LocalDate.of(2018, 12, 3);
// 生成当前日期对象
LocalDate now = LocalDate.now();
// 从LocalDate中获取时间信息
time.getDayOfMonth();
time.getYear();
time.getMonth();
time.getDayOfWeek();
time.getDayOfYear();
time.lengthOfMonth();
time.lengthOfYear();

通过public int get(TemporalField field)获取日期信息:

time.get(ChronoField.DAY_OF_MONTH);
time.get(ChronoField.DAY_OF_YEAR);

字符串转换为日期:

LocalDate parse = LocalDate.parse("2018-10-20");

3.LocalTime时间API

// 生成时间
LocalTime time = LocalTime.of(10, 10, 10);
// 获取时间
time.getHour();
time.getMinute();
time.getNano();
time.getSecond();
// 通过TemporalField获取时间中信息
time.get(ChronoField.HOUR_OF_DAY);
time.get(ChronoField.MINUTE_OF_DAY);
time.get(ChronoField.SECOND_OF_DAY);

字符串转时间:

LocalTime time = LocalTime.parse("20:10:20");

4.LocalDateTime日期时间函数

创建对象:

public static LocalDateTime of(int year, Month month, int dayOfMonth, int hour, int minute)
public LocalDateTime of(LocalDate date, LocalTime time) 
public static LocalDateTime of(int year, int month, int dayOfMonth, int hour, int minute)

通过LocalDate和LocalTime对象生成LocalDateTime对象:

LocalDate date = LocalDate.now();
// 通过 LocalDate 对象的atTime方法生成
 LocalDateTime localDateTime = date.atTime(10, 20);// hour minute

 LocalTime time = LocalTime.now();
 // 通过 LocalTime 的 atDate 方法生成
 LocalDateTime localDateTime1 = time.atDate(date);

LocalDateTime转LocalDate和LocalTime:

LocalDateTime now = LocalDateTime.now();
LocalDate date = now.toLocalDate();
LocalTime time = now.toLocalTime();

5.Instant时间戳

生成Instant对象:

// 时间戳 毫秒
Instant instant = Instant.ofEpochMilli(100_000);
// 时间戳  秒
Instant instant1 = Instant.ofEpochSecond(100_000);
// 时间戳 秒 + 纳秒
Instant.ofEpochSecond(120, 100_000_000);

从Instant对象中获取时间戳:

Instant.ofEpochSecond(120, 100_000_000);
Instant now = Instant.now();
// 获取秒数
System.out.println(now.getEpochSecond());
// 获取毫秒数
System.out.println(now.toEpochMilli());
// 获取纳秒数
System.out.println(now.getNano());

6.获取时间和日期间的间隔

 LocalDateTime dateTime = LocalDateTime.now();
 Duration between = Duration.between(dateTime, dateTime);
 // Duration 用于获取时间相关 秒和纳秒
 System.out.println(between.getSeconds());

 LocalDate data = LocalDate.now();
 Period between1 = Period.between(data, data);
 // Period 主要获取日期相关 年月日等
 System.out.println(between1.getYears());

操纵日期:

 // 通过 withXxx方法操作日期
 LocalDate date = LocalDate.of(2018, 10, 20); // 2018-10-20
 LocalDate date1 = date.withYear(2010); // 2010-10-20
 LocalDate date2 = date.withMonth(8);// 2010-08-20
 LocalDate with = date.with(ChronoField.MONTH_OF_YEAR, 1); // 2018-01-20
 // 对日期进行加减操作
 LocalDate date3 = date.plusMonths(1); // 2018-11-20
 LocalDate plus = date.plus(2, ChronoUnit.MONTHS); // 2018-12-20
 // 对日期进行减操作
 LocalDate minus = date.minus(10, ChronoUnit.YEARS); // 2008-10-20

按照指定格式转换日期:

// 定义转换格式
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
LocalDate now = LocalDate.now();
// 日期按照指定格式转换
String format = now.format(dateTimeFormatter);
// 默认
LocalDate now = LocalDate.now();
String format = now.format(DateTimeFormatter.BASIC_ISO_DATE); // 20190320
String format1 = now.format(DateTimeFormatter.ISO_DATE); // 2019-03-20
// 反向操作
LocalDate parse = LocalDate.parse("20190320", DateTimeFormatter.BASIC_ISO_DATE);
LocalDate parse1 = LocalDate.parse("2019-03-20", DateTimeFormatter.ISO_DATE);

7.TemporalAdjuster

dayOfWeekInMonth 创建一个新的日期,它的值为同一个月中每一周的第几天
firstDayOfMonth 创建一个新的日期,它的值为当月的第一天
firstDayOfNextMonth 创建一个新的日期,它的值为下月的第一天
firstDayOfNextYear 创建一个新的日期,它的值为明年的第一天
firstDayOfYear 创建一个新的日期,它的值为当年的第一天
firstInMonth 创建一个新的日期,它的值为同一个月中,第一个符合星期几要求的值
lastDayOfMonth 创建一个新的日期,它的值为当月的最后一天
lastDayOfNextMonth 创建一个新的日期,它的值为下月的最后一天
lastDayOfNextYear 创建一个新的日期,它的值为明年的最后一天
lastDayOfYear 创建一个新的日期,它的值为今年的最后一天
lastInMonth 创建一个新的日期,它的值为同一个月中,最后一个符合星期几要求的值
next/previous 创建一个新的日期,并将其值设定为日期调整后或者调整前,第一个符合指定星期几要求的日期
nextOrSame/previousOrSame 创建一个新的日期,并将其值设定为日期调整后或者调整前,第一个符合指定星期几要求的日期,如果该日期已经符合要求,直接返回该对象

使用示例:

LocalDate lastDayOfMonth = date.with(TemporalAdjusters.lastDayOfMonth());

你可能感兴趣的:(学习Java8看这篇文章就够了)