Do you use the new features of java8?

Preface

This article mainly describes the use of some new syntax features of JDK1.8 in Java, mainly about the use of Lambda, Stream and LocalDate dates.

Lambda

Lambda introduction

Lambda expression is an anonymous function. Lambda expression is named based on the λ calculus in mathematics. It directly corresponds to the lambda abstraction in it. It is an anonymous function, that is, a function without a function name.

Lambda expression structure

  • A Lambda expression can have zero or more parameters

  • The type of the parameter can either be declared explicitly or inferred from the context. For example: (int a) has the same effect as (a)

  • All parameters must be enclosed in parentheses, separated by commas. For example: (a, b) or (int a, int b) or (String a, int b, float c)

  • Empty parentheses indicate that the parameter set is empty. For example: () -> 42

  • When there is only one parameter and its type can be deduced, the parentheses () can be omitted. For example: a -> return a*a

  • The body of the lambda expression can contain zero or more statements

  • If the main body of the Lambda expression has only one statement, the curly braces {} can be omitted. The return type of the anonymous function is consistent with the body expression

  • If the body of the Lambda expression contains more than one statement, the expression must be enclosed in curly braces {} (to form a code block). The return type of the anonymous function is the same as the return type of the code block, if there is no return, it is empty

Use of lambda expressions

Let's first use a simple example to see the effect of Lambda.

For example, our traditional way of traversing Map is as follows:

  Map<String, String> map = new HashMap<>();
  map.put("a", "a");
  map.put("b", "b");
  map.put("c", "c");
  map.put("d", "d");

  System.out.println("map普通方式遍历:");
  for (String key : map.keySet()) {
   System.out.println("k=" + key + ",v=" + map.get(key));
  }

Use Lambda to traverse:

  System.out.println("map拉姆达表达式遍历:");
  map.forEach((k, v) -> {
   System.out.println("k=" + k + ",v=" + v);
 });

The same is true for List, but List can also be traversed by the double colon operator:

  List<String> list = new ArrayList<String>();
  list.add("a");
  list.add("bb");
  list.add("ccc");
  list.add("dddd");
  System.out.println("list拉姆达表达式遍历:");
  list.forEach(v -> {
   System.out.println(v);
  });
  System.out.println("list双冒号运算符遍历:");
  list.forEach(System.out::println);

Output result:

 map普通方式遍历:
 k=a,v=a
 k=b,v=b
 k=c,v=c
 k=d,v=d
 map拉姆达表达式遍历:
 k=a,v=a
 k=b,v=b
 k=c,v=c
 k=d,v=d
 list拉姆达表达式遍历:
 a
 bb
 ccc
 dddd
 list双冒号运算符遍历:
 a
 bb
 ccc
 dddd

In addition to being used in for loop traversal, Lambda can also replace anonymous inner classes. For example, the thread creation in the following example:

 //使用普通的方式创建
 Runnable r1 = new Runnable() {
  @Override
  public void run() {
   System.out.println("普通方式创建!");
  }
 };
 
 //使用拉姆达方式创建
 Runnable r2 = ()-> System.out.println("拉姆达方式创建!");

Note: When using Lambda expression in this example, the compiler will automatically infer: According to the constructor signature of the thread class Runnable r {}, assign the Lambda expression to the Runnable interface.

The difference between Lambda expressions and anonymous classes One major difference between using anonymous classes and Lambda expressions is the use of keywords. For anonymous classes, the keyword this is interpreted as an anonymous class, and for Lambda expressions, the keyword this is interpreted as an external class written as Lambda.

Precautions for using Lambda expressions

Although Lambda simplifies the writing of code, it also reduces readability.

Stream

Stream introduction

Stream uses an intuitive way similar to querying data from a database using SQL statements to provide a high-level abstraction of Java set operations and expressions. Stream API can greatly improve the productivity of Java programmers, allowing programmers to write efficient, clean, and concise code. This style regards the collection of elements to be processed as a kind of flow, which is transmitted in the pipeline and can be processed on the nodes of the pipeline, such as filtering, sorting, and aggregation.

Stream features:

  • Not a data structure: it has no internal storage, it just uses an operation pipeline to fetch data from the source (data structure, array, generator function, IO channel). It will never modify the data of the underlying data structure that it encapsulates. For example, the filter operation of Stream will generate a new Stream that does not contain the filtered elements, instead of deleting those elements from the source.

  • Index access is not supported: but it is easy to generate an array or List.

  • Laziness: Many Stream operations are delayed backwards until it knows how much data is needed in the end. Intermediate operations are always lazy.

  • Parallel ability. When a Stream is parallelized, there is no need to write multithreaded code, and all operations on it will be automatically performed in parallel.

  • It can be infinite: the collection has a fixed size, but Stream does not. Short-circuiting operations such as limit(n) and findFirst() can perform operations on unlimited Streams and complete them quickly.

  • Note: All Stream operations must take a lambda expression as a parameter.

Stream operation type:

  • Intermediate: A stream can be followed by zero or more intermediate operations. The main purpose is to open the stream, do a certain degree of data mapping/filtering, and then return a new stream to be used by the next operation. This type of operation is lazy, that is, just calling this type of method does not really start the traversal of the stream.

  • Terminal: A stream can only have one terminal operation. When this operation is executed, the stream is used "light" and can no longer be operated. So this must be the last operation of the stream. The execution of the Terminal operation will actually start the traversal of the stream, and will generate a result, or a side effect.

Stream use

Here we still use a simple example to take a look. In development, we sometimes need to filter some data. If it is a traditional way, we need to traverse and filter this batch of data, which will be more cumbersome. If you use the steam streaming method, it can be easily processed.

First filter by ordinary means:

List<String> list = Arrays.asList("张三", "李四", "王五", "xuwujing");
 System.out.println("过滤之前:" + list);
 List<String> result = new ArrayList<>();
 for (String str : list) {
  if (!"李四".equals(str)) {
   result.add(str);
  }
 }
 System.out.println("过滤之后:" + result);

Use Steam to filter:

List<String> result2 = list.stream().filter(str -> !"李四".equals(str)).collect(Collectors.toList());
System.out.println("stream 过滤之后:" + result2);

Output result:

过滤之前:[张三, 李四, 王五, xuwujing]
过滤之后:[张三, 王五, xuwujing]
stream 过滤之后:[张三, 王五, xuwujing]

Is it very concise and convenient? In fact, there are more ways to use Stream, and filter is just one of them. So here we will learn to understand these usages.

1. The way to construct Stream

 Stream stream = Stream.of("a", "b", "c");
 String[] strArray = new String[] { "a", "b", "c" };
 stream = Stream.of(strArray);
 stream = Arrays.stream(strArray);
 List<String> list = Arrays.asList(strArray);
 stream = list.stream();

2. Conversion between Stream streams

Note: A Stream can only be used once. This code is reused several times for brevity, so it will throw stream has already been operated upon or closed exception.

try {
  Stream<String> stream2 = Stream.of("a", "b", "c");
  // 转换成 Array
  String[] strArray1 = stream2.toArray(String[]::new);

  // 转换成 Collection
  List<String> list1 = stream2.collect(Collectors.toList());
  List<String> list2 = stream2.collect(Collectors.toCollection(ArrayList::new));   
  Set set1 = stream2.collect(Collectors.toSet());
  Stack stack1 = stream2.collect(Collectors.toCollection(Stack::new));

  // 转换成 String
  String str = stream.collect(Collectors.joining()).toString();
 } catch (Exception e) {
  e.printStackTrace();
 }

3. Map use of Stream

The map method is used to map each element to the corresponding result, one to one.

Example 1: Convert uppercase

 List<String> list3 = Arrays.asList("zhangSan", "liSi", "wangWu");
 System.out.println("转换之前的数据:" + list3);
 List<String> list4 = list3.stream().map(String::toUpperCase).collect(Collectors.toList());
 System.out.println("转换之后的数据:" + list4); 
 // 转换之后的数据:[ZHANGSAN, LISI,WANGWU]

Example 2: Convert the data type

 List<String> list31 = Arrays.asList("1", "2", "3");
 System.out.println("转换之前的数据:" + list31);
 List<Integer> list41 = list31.stream().map(Integer::valueOf).collect(Collectors.toList());
 System.out.println("转换之后的数据:" + list41); 
 // [1, 2, 3]

Example 3: Get the square

 List<Integer> list5 = Arrays.asList(new Integer[] { 1, 2, 3, 4, 5 });
 List<Integer> list6 = list5.stream().map(n -> n * n).collect(Collectors.toList());
 System.out.println("平方的数据:" + list6);
 // [1, 4, 9, 16, 25]

4.Stream flow filter usage

The filter method is used to filter out elements through the set conditions.

Example 2: Get the value of if/else by and findAny

List<String> list = Arrays.asList("张三", "李四", "王五", "xuwujing");
String result3 = list.stream().filter(str -> "李四".equals(str)).findAny().orElse("找不到!");
String result4 = list.stream().filter(str -> "李二".equals(str)).findAny().orElse("找不到!");

System.out.println("stream 过滤之后 2:" + result3);
System.out.println("stream 过滤之后 3:" + result4);
//stream 过滤之后 2:李四
//stream 过滤之后 3:找不到!

Example 3: Calculate the sum with mapToInt

 List<User> lists = new ArrayList<User>();
 lists.add(new User(6, "张三"));
 lists.add(new User(2, "李四"));
 lists.add(new User(3, "王五"));
 lists.add(new User(1, "张三"));
 // 计算这个list中出现 "张三" id的值
 int sum = lists.stream().filter(u -> "张三".equals(u.getName())).mapToInt(u -> u.getId()).sum();

 System.out.println("计算结果:" + sum); 
 // 7

5. Use of flatMap for Stream

The flatMap method is used to map each element to the corresponding result, one to many.

Example: get words from sentences

 String worlds = "The way of the future";
 List<String> list7 = new ArrayList<>();
 list7.add(worlds);
 List<String> list8 = list7.stream().flatMap(str -> Stream.of(str.split(" ")))
   .filter(world -> world.length() > 0).collect(Collectors.toList());
 System.out.println("单词:");
 list8.forEach(System.out::println);
 // 单词:
 // The 
 // way 
 // of 
 // the 
 // future

6. Stream limit usage

The limit method is used to obtain a specified number of streams.

Example 1: Get the first n data

 Random rd = new Random();
 System.out.println("取到的前三条数据:");
 rd.ints().limit(3).forEach(System.out::println);
 // 取到的前三条数据:
 // 1167267754
 // -1164558977
 // 1977868798

Example 2: Use skip to get the required data

skip means to throw away the first n elements.

List<User> list9 = new ArrayList<User>();
 for (int i = 1; i < 4; i++) {
  User user = new User(i, "pancm" + i);
  list9.add(user);
 }
 System.out.println("截取之前的数据:");
 // 取前3条数据,但是扔掉了前面的2条,可以理解为拿到的数据为 2<=i<3 (i 是数值下标)
 List<String> list10 = list9.stream().map(User::getName).limit(3).skip(2).collect(Collectors.toList());
 System.out.println("截取之后的数据:" + list10);
 //  截取之前的数据:
 //  姓名:pancm1
 //  姓名:pancm2
 //  姓名:pancm3
 //  截取之后的数据:[pancm3]

Note: The getName method in the User entity class will print the name.

7. Sort use of Stream

The sorted method is used to sort the stream in ascending order.

Example 1: Random value sorting

 Random rd2 = new Random();
 System.out.println("取到的前三条数据然后进行排序:");
 rd2.ints().limit(3).sorted().forEach(System.out::println);
 // 取到的前三条数据然后进行排序:
 // -2043456377
 // -1778595703
 // 1013369565

Example 2: Optimize sorting

Tips: Get it first, and the sorting efficiency will be higher!

 //普通的排序取值
 List<User> list11 = list9.stream().sorted((u1, u2) -> u1.getName().compareTo(u2.getName())).limit(3)
   .collect(Collectors.toList());
 System.out.println("排序之后的数据:" + list11);
 //优化排序取值
 List<User> list12 = list9.stream().limit(3).sorted((u1, u2) -> u1.getName().compareTo(u2.getName()))
   .collect(Collectors.toList());
 System.out.println("优化排序之后的数据:" + list12);
 //排序之后的数据:[{"id":1,"name":"pancm1"}, {"id":2,"name":"pancm2"}, {"id":3,"name":"pancm3"}]
 //优化排序之后的数据:[{"id":1,"name":"pancm1"}, {"id":2,"name":"pancm2"}, {"id":3,"name":"pancm3"}]

8. Stream peek use

peek performs operations on each element and returns a new Stream

Example: double operation

 System.out.println("peek使用:");
 Stream.of("one", "two", "three", "four").filter(e -> e.length() > 3).peek(e -> System.out.println("转换之前: " + e))
   .map(String::toUpperCase).peek(e -> System.out.println("转换之后: " + e)).collect(Collectors.toList());
 
 // 转换之前: three
 // 转换之后: THREE
 // 转换之前: four
 // 转换之后: FOUR

9. Parallel use of Stream

parallelStream is an alternative to stream parallel processing programs.

Example: get the number of empty strings

 List<String> strings = Arrays.asList("a", "", "c", "", "e","", " ");
 // 获取空字符串的数量
 long count =  strings.parallelStream().filter(string -> string.isEmpty()).count();
 System.out.println("空字符串的个数:"+count);

10. Max/min/distinct use of Stream

Example 1: Get the maximum and minimum values

 List<String> list13 = Arrays.asList("zhangsan","lisi","wangwu","xuwujing");
 int maxLines = list13.stream().mapToInt(String::length).max().getAsInt();
 int minLines = list13.stream().mapToInt(String::length).min().getAsInt();
 System.out.println("最长字符的长度:" + maxLines+",最短字符的长度:"+minLines);
 //最长字符的长度:8,最短字符的长度:4

Example 2: Get the data after deduplication

 String lines = "good good study day day up";
 List<String> list14 = new ArrayList<String>();
 list14.add(lines);
 List<String> words = list14.stream().flatMap(line -> Stream.of(line.split(" "))).filter(word -> word.length() > 0)
   .map(String::toLowerCase).distinct().sorted().collect(Collectors.toList());
 System.out.println("去重复之后:" + words);
 //去重复之后:[day, good, study, up]

11. Use of Match for Stream

  • allMatch: Returns true if all elements in the Stream match;

  • anyMatch: As long as one element in the Stream matches, it returns true;

  • noneMatch: Return true if none of the elements in the stream match.

Example: Does the data match

 boolean all = lists.stream().allMatch(u -> u.getId() > 3);
 System.out.println("是否都大于3:" + all);
 boolean any = lists.stream().anyMatch(u -> u.getId() > 3);
 System.out.println("是否有一个大于3:" + any);
 boolean none = lists.stream().noneMatch(u -> u.getId() > 3);
 System.out.println("是否没有一个大于3的:" + none);  
 // 是否都大于3:false
 // 是否有一个大于3:true
 // 是否没有一个大于3的:false

12. Stream reduce usage

The main function of reduce is to combine Stream elements to perform operations.

Example 1: String concatenation

String concat = Stream.of("A", "B", "C", "D").reduce("", String::concat);
System.out.println("字符串拼接:" + concat);

Example 2: Get the minimum value

 double minValue = Stream.of(-4.0, 1.0, 3.0, -2.0).reduce(Double.MAX_VALUE, Double::min);
 System.out.println("最小值:" + minValue);
 //最小值:-4.0

Example 3: Sum

 // 求和, 无起始值
 int sumValue = Stream.of(1, 2, 3, 4).reduce(Integer::sum).get();
 System.out.println("有无起始值求和:" + sumValue);
 // 求和, 有起始值
  sumValue = Stream.of(1, 2, 3, 4).reduce(1, Integer::sum);
  System.out.println("有起始值求和:" + sumValue);
 // 有无起始值求和:10
 // 有起始值求和:11

Example 4: Filtering and splicing

concat = Stream.of("a", "B", "c", "D", "e", "F").filter(x -> x.compareTo("Z") > 0).reduce("", String::concat);
System.out.println("过滤和字符串连接:" + concat);
 //过滤和字符串连接:ace

13. Stream iterate usage

Iterate is similar to the reduce operation, accepting a seed value and an UnaryOperator (for example, f). Then the seed value becomes the first element of the Stream, f(seed) is the second, f(f(seed)) is the third, and so on. In iterate, the pipeline must have operations such as limit to limit the size of the Stream.

Example: Generate an arithmetic queue

 System.out.println("从2开始生成一个等差队列:");
 Stream.iterate(2, n -> n + 2).limit(5).forEach(x -> System.out.print(x + " "));
 // 从2开始生成一个等差队列:
 // 2 4 6 8 10

14.Supplier use of Stream

You can customize the flow calculation rules by implementing the methods of the Supplier class.

Example: Obtain two pieces of user information randomly

 System.out.println("自定义一个流进行计算输出:");
 Stream.generate(new UserSupplier()).limit(2).forEach(u -> System.out.println(u.getId() + ", " + u.getName()));
 
 //第一次:
 //自定义一个流进行计算输出:
 //10, pancm7
 //11, pancm6
 
 //第二次:
 //自定义一个流进行计算输出:
 //10, pancm4
 //11, pancm2
 
 //第三次:
 //自定义一个流进行计算输出:
 //10, pancm4
 //11, pancm8


class UserSupplier implements Supplier<User> {
 private int index = 10;
 private Random random = new Random();

 @Override
 public User get() {
  return new User(index++, "pancm" + random.nextInt(10));
 }
}

15. Use of groupingBy/partitioningBy of Stream

  • groupingBy: grouping and sorting;

  • partitioningBy: partition sorting.

Example 1: Sort by group

 System.out.println("通过id进行分组排序:");
 Map<Integer, List<User>> personGroups = Stream.generate(new UserSupplier2()).limit(5)
   .collect(Collectors.groupingBy(User::getId));
 Iterator it = personGroups.entrySet().iterator();
 while (it.hasNext()) {
  Map.Entry<Integer, List<User>> persons = (Map.Entry) it.next();
  System.out.println("id " + persons.getKey() + " = " + persons.getValue());
 }
 
 // 通过id进行分组排序:
 // id 10 = [{"id":10,"name":"pancm1"}] 
 // id 11 = [{"id":11,"name":"pancm3"}, {"id":11,"name":"pancm6"}, {"id":11,"name":"pancm4"}, {"id":11,"name":"pancm7"}]



 class UserSupplier2 implements Supplier<User> {
  private int index = 10;
  private Random random = new Random();
 
  @Override
  public User get() {
   return new User(index % 2 == 0 ? index++ : index, "pancm" + random.nextInt(10));
  }
 }

Example 2: Partition sort

    System.out.println("通过年龄进行分区排序:");
 Map<Boolean, List<User>> children = Stream.generate(new UserSupplier3()).limit(5)
   .collect(Collectors.partitioningBy(p -> p.getId() < 18));

 System.out.println("小孩: " + children.get(true));
 System.out.println("成年人: " + children.get(false));
 
 // 通过年龄进行分区排序:
 // 小孩: [{"id":16,"name":"pancm7"}, {"id":17,"name":"pancm2"}]
 // 成年人: [{"id":18,"name":"pancm4"}, {"id":19,"name":"pancm9"}, {"id":20,"name":"pancm6"}]

  class UserSupplier3 implements Supplier<User> {
  private int index = 16;
  private Random random = new Random();
 
  @Override
  public User get() {
   return new User(index++, "pancm" + random.nextInt(10));
  }
 }

16. The use of summaryStatistics for Stream

IntSummaryStatistics is a status object used to collect statistics (such as count, min, max, sum, and average).

Example: Get the maximum, minimum, sum and average.

 List<Integer> numbers = Arrays.asList(1, 5, 7, 3, 9);
 IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics();
  
 System.out.println("列表中最大的数 : " + stats.getMax());
 System.out.println("列表中最小的数 : " + stats.getMin());
 System.out.println("所有数之和 : " + stats.getSum());
 System.out.println("平均数 : " + stats.getAverage());
 
 // 列表中最大的数 : 9
 // 列表中最小的数 : 1
 // 所有数之和 : 25
 // 平均数 : 5.0

That's it for the introduction of Stream. There are actually many uses of Stream in JDK1.8. For more usages, you need to check the API documentation of JDK1.8.

LocalDateTime

Introduction

In addition to adding lambda expressions and streams, JDK1.8 also added a new date and time API. Before JDK1.8, the way Java handles dates, calendars, and time has been criticized by the community. The setting of java.util.Date as a variable type and the non-thread safety of SimpleDateFormat make its application very limited. Therefore, the java.time package was launched. All classes under this package are immutable and thread-safe.

Key category

  • Instant: Instantaneous time.

  • LocalDate: local date, excluding specific time, format yyyy-MM-dd.

  • LocalTime: Local time, excluding date. Format yyyy-MM-dd HH:mm:ss.SSS.

  • LocalDateTime: A combination of date and time, but does not include time difference and time zone information.

  • ZonedDateTime: The most complete date and time, including the time zone and the time difference relative to UTC or Greenwich.

use

1. Get the current date and time

Get the current time through the static factory method now().

 //本地日期,不包括时分秒
 LocalDate nowDate = LocalDate.now();
 //本地日期,包括时分秒
 LocalDateTime nowDateTime = LocalDateTime.now();
 System.out.println("当前时间:"+nowDate);
 System.out.println("当前时间:"+nowDateTime);
 //  当前时间:2018-12-19
 //  当前时间:2018-12-19T15:24:35.822

2. Get the current year, month, day, hour, minute, and second

After obtaining the time, directly get the year, month, day, hour, minute and second.

  //获取当前的时间,包括毫秒
  LocalDateTime ldt = LocalDateTime.now();
  System.out.println("当前年:"+ldt.getYear());   //2018
  System.out.println("当前年份天数:"+ldt.getDayOfYear());//172 
  System.out.println("当前月:"+ldt.getMonthValue());
  System.out.println("当前时:"+ldt.getHour());
  System.out.println("当前分:"+ldt.getMinute());
  System.out.println("当前时间:"+ldt.toString());
 //   当前年:2018
 //   当前年份天数:353
 //   当前月:12
 //   当前时:15
 //   当前分:24
 //   当前时间:2018-12-19T15:24:35.833

3. Format the time

Format time format needs to use DateTimeFormatter class.

LocalDateTime ldt = LocalDateTime.now();
System.out.println("格式化时间: "+ ldt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")));
//格式化时间:2018-12-19 15:37:47.119

4. Time increase and decrease

Increase/decrease year, month, day, hour, minute, and second at the specified time.

  LocalDateTime ldt = LocalDateTime.now();
  System.out.println("后5天时间:"+ldt.plusDays(5));
  System.out.println("前5天时间并格式化:"+ldt.minusDays(5).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); //2018-06-16
  System.out.println("前一个月的时间:"+ldt2.minusMonths(1).format(DateTimeFormatter.ofPattern("yyyyMM"))); //2018-06-16
  System.out.println("后一个月的时间:"+ldt2.plusMonths(1)); //2018-06-16
  System.out.println("指定2099年的当前时间:"+ldt.withYear(2099)); //2099-06-21T15:07:39.506
 //  后5天时间:2018-12-24T15:50:37.508
 //  前5天时间并格式化:2018-12-14
 //  前一个月的时间:201712
 //  后一个月的时间:2018-02-04T09:19:29.499
 //  指定2099年的当前时间:2099-12-19T15:50:37.508

5. Create the specified time

Create by specifying the year, month, and day.

 LocalDate ld3=LocalDate.of(2017, Month.NOVEMBER, 17);
 LocalDate ld4=LocalDate.of(2018, 02, 11);

6. Time difference comparison

Compare the year, month, day, hour, minute and second.

Example 1: The specific year, month and day of the difference

 LocalDate ld=LocalDate.parse("2017-11-17");
 LocalDate ld2=LocalDate.parse("2018-01-05");
 Period p=Period.between(ld, ld2);
 System.out.println("相差年: "+p.getYears()+" 相差月 :"+p.getMonths() +" 相差天:"+p.getDays());
 // 相差年: 0 相差月 :1 相差天:19

Note: The month here does not satisfy one year, and the number of days does not satisfy one month. The actual difference here is January 19, which is 49 days.

Example 2: The total time difference

ChronoUnit The standard collection of date period units.

    LocalDate startDate = LocalDate.of(2017, 11, 17);
        LocalDate endDate = LocalDate.of(2018, 01, 05);
        System.out.println("相差月份:"+ChronoUnit.MONTHS.between(startDate, endDate));
        System.out.println("两月之间的相差的天数   : " + ChronoUnit.DAYS.between(startDate, endDate));
  //        相差月份:1
  //        两天之间的差在天数   : 49

Note: ChronoUnit can also calculate the difference in hours, minutes and seconds.

Example 3: Accuracy time difference

Duration This class models the amount or amount of time in seconds and nanoseconds.

 Instant inst1 = Instant.now();
    System.out.println("当前时间戳 : " + inst1);
    Instant inst2 = inst1.plus(Duration.ofSeconds(10));
    System.out.println("增加之后的时间 : " + inst2);
    System.out.println("相差毫秒 : " + Duration.between(inst1, inst2).toMillis());
    System.out.println("相毫秒 : " + Duration.between(inst1, inst2).getSeconds());
 // 当前时间戳 : 2018-12-19T08:14:21.675Z
 // 增加之后的时间 : 2018-12-19T08:14:31.675Z
 // 相差毫秒 : 10000
 // 相毫秒 : 10

Example 4: Time size comparison

  LocalDateTime ldt4 = LocalDateTime.now();
  LocalDateTime ldt5 = ldt4.plusMinutes(10);
  System.out.println("当前时间是否大于:"+ldt4.isAfter(ldt5));
  System.out.println("当前时间是否小于"+ldt4.isBefore(ldt5));
  // false
  // true

7. Time zone time calculation

Get the time in other time zones.

Example 1: Obtain calculations through the Clock class

The Clock class is used to obtain the time stamp at that time, or the date and time information in the current time zone.

  Clock clock = Clock.systemUTC();
  System.out.println("当前时间戳 : " + clock.millis());
  Clock clock2 = Clock.system(ZoneId.of("Asia/Shanghai"));
  System.out.println("亚洲上海此时的时间戳:"+clock2.millis());
  Clock clock3 = Clock.system(ZoneId.of("America/New_York"));
  System.out.println("美国纽约此时的时间戳:"+clock3.millis());
  //  当前时间戳 : 1545209277657
  //  亚洲上海此时的时间戳:1545209277657
  //  美国纽约此时的时间戳:1545209277658

Example 2: Through ZonedDateTime class and ZoneId

  ZoneId zoneId= ZoneId.of("America/New_York");
  ZonedDateTime dateTime=ZonedDateTime.now(zoneId);
  System.out.println("美国纽约此时的时间 : " + dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")));
  System.out.println("美国纽约此时的时间 和时区: " + dateTime);
  //  美国纽约此时的时间 : 2018-12-19 03:52:22.494
  // 美国纽约此时的时间 和时区: 2018-12-19T03:52:22.494-05:00[America/New_York]

Summary of Java 8 date and time API:

  • Provide javax.time.ZoneId to get the time zone.

  • Provides LocalDate and LocalTime classes.

  • All date and time APIs of Java 8 are immutable and thread-safe, while the existing Date and Calendar APIs java.util.Date and SimpleDateFormat are not thread-safe.

  • The main package is java.time, which contains some classes that represent date, time, and time interval. There are two sub-packages java.time.format for formatting and java.time.temporal for lower-level operations.

  • The time zone represents the standard time commonly used in a certain area on the earth. Each time zone has a code, the format is usually composed of region/city (Asia/Tokyo), plus the time difference with Greenwich or UTC. For example: The time difference in Tokyo is +09:00.

  • The OffsetDateTime class actually combines the LocalDateTime class and the ZoneOffset class. It is used to represent the complete date (year, month, day) and time (hour, minute, second, nanosecond) information including the time difference from Greenwich or UTC.

  • The DateTimeFormatter class is used to format and parse time. Unlike SimpleDateFormat, this class is immutable and thread-safe. You can assign static constants when needed. The DateTimeFormatter class provides a lot of built-in formatting tools, but also allows you to customize. In terms of conversion, parse() is also provided to parse the string into a date. If the parsing error occurs, a DateTimeParseException will be thrown. The DateTimeFormatter class also has format() to format the date. If an error occurs, a DateTimeException will be thrown.

  • One more thing, the date format "MMM d yyyy" and "MMM dd yyyy" have some subtle differences. The first format can parse "Jan 2 2014" and "Jan 14 2014", while the second is parsed "Jan 2 "2014" will throw an exception because the second format requires that the day must be two digits. If you want to make corrections, you must add zeros in front of the date when there are only single digits, which means that "Jan 2 2014" should be written as "Jan 02 2014".

other

Reference article:

http://blog.oneapm.com/apm-tech/226.html https://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/ http://www.importnew.com/15637.html

END
喜欢本文的朋友们,欢迎长按下图关注订阅号成猿之路,收看更多精彩内容!

推荐阅读:
《SpringBoot技术栈搭建个人博客》《推荐几个不错的黑科技网站》《一份从0到1的Java项目实践清单,看这篇就对了!》《2020前端面试:第一波面试题总结(你可能被问过)》《教你如何使用GitHub精准搜索开源项目?》

我知道你 “在看”

Guess you like

Origin blog.csdn.net/qq_39507327/article/details/108114413