代码如下:
// 获取当前的日期时间 LocalDateTime currentTime = LocalDateTime.now(); System.out.println("当前时间: " + currentTime); //获取当前日期 LocalDate date1 = currentTime.toLocalDate(); System.out.println("date1: " + date1); //获取年月日 Month month = currentTime.getMonth(); int monthValue =currentTime.getMonthValue(); int year = currentTime.getYear(); int day = currentTime.getDayOfMonth(); int seconds = currentTime.getSecond(); System.out.println("年:"+year+" 英文月:" + month+" 数字月:"+month.getValue()+" 数字月:"+monthValue+" 日: " + day +" 秒: " + seconds); //设定日期,设定为2012-4-10 *这个不会修改原值 LocalDateTime date2 = currentTime.withDayOfMonth(10).withYear(2012).withMonth(3); System.out.println("date2: " + date2); // 2019-4-26 LocalDate date3 = LocalDate.of(2019, 4, 26); LocalDate date4 = LocalDate.of(2019, Month.APRIL, 26); System.out.println("date3: " + date3); System.out.println("date4: " + date4); // 22 小时 15 分钟 LocalTime time1 = LocalTime.of(22, 15); System.out.println("time1: " + time1); // 解析字符串 LocalTime time2 = LocalTime.parse("20:15:30"); System.out.println("time2: " + time2);
LocalDateTime -> timestamp
LocalDate -> date
LocalTime -> time
代码如下
// 获取当前时间日期 ZonedDateTime zone = ZonedDateTime.parse("2019-04-28T10:15:30+05:30[Asia/Shanghai]"); System.out.println("zone: " + zone); ZoneId id = ZoneId.of("Europe/Paris"); System.out.println("ZoneId: " + id); ZoneId currentZone = ZoneId.systemDefault(); System.out.println("当期时区: " + currentZone);
接口中添加新的方法,即不强制那些实现了该接口的类也同时实现这个新加的方法。
default +方法名+代码块 or static+方法名+代码块
代码如下
public interface Animal { default void print(){ System.out.println("animal"); } static void staticPrint(){ System.out.println("staticPrint"); } } public interface Dog { default void print(){ System.out.println("dog"); } static void staticPrint(){ System.out.println("staticPrint"); } } //如果实现多个接口,同一个方法的话,实现类必须复写 public class Bone implements Dog,Animal { @Override public void print() { Dog.super.print(); Animal.super.print(); System.out.println("bone"); } private void test(){ Dog.staticPrint(); } } //单一的可以不用实现 public class Bone2 implements Dog { }
“Lambda 表达式”(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。
写法:
// 1. 不需要参数,返回值为 5 // () -> 5 // 2. 接收一个参数(数字类型),返回其2倍的值 // x -> 2 * x // 3. 接受2个参数(数字),并返回他们的差值 // (x, y) -> x – y // 4. 接收2个int型整数,返回他们的和 // (int x, int y) -> x + y // 只有表达式内部代码块只有一行时可以省略大括号和关键字 // (int x, int y) -> {return x+y;} // 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void) // (String s) -> System.out.print(s)
特点:
1.写法优化了。
2.编译不像匿名类会产生class文件。
3.对外部变量使用更灵活了。this关键字指向外部变量与匿名内部类有区别。
定义:有且仅有一个抽象方法(Object的public,default,static 除外)的接口。
写法:使用@FunctionalInterface注解
自定义的函数式接口:
@FunctionalInterface public interface Eat { void eat(); boolean equals(Object obj); default void print(){ System.out.println("eat"); } static void sayHello(){ System.out.println("hello"); } }
常用的4中函数式接口:
1.Consumer
//1.抽象方法,传一个对象,执行,没有返回值。 void accept(T t); //2.连续执行,即f(g(x))的意思,先执行本体,后执行传入的 default Consumer<T> andThen(Consumer<? super T> after) { Objects.requireNonNull(after); return (T t) -> { accept(t); after.accept(t); }; }
2.Supplier
T get();
不传入,反而得到一个对象。
3.Function<T, R>
//1.传入点东西,执行,得到点东西。 R apply(T t); //2.和andThen相反,先执行传入的那一个,后执行本体 default <V> Function<V, R> compose(Function<? super V, ? extends T> before) { Objects.requireNonNull(before); return (V v) -> apply(before.apply(v)); } //3.不解释 default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) { Objects.requireNonNull(after); return (T t) -> after.apply(apply(t)); } //4.f(x)=x 的既视感,也不太明白使用场景是啥 static <T> Function<T, T> identity() { return t -> t; }
4.Predicate
//1.传入一个对象,执行逻辑判断后得到一个布尔值, boolean test(T t); //2.逻辑且的意思 default Predicate<T> and(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) && other.test(t); } //3.逻辑非的意思 default Predicate<T> negate() { return (t) -> !test(t); } //4.逻辑或的意思 default Predicate<T> or(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) || other.test(t); } //5.判断是不是null,不是null掉obejct的equals方法,目前还不知道使用场景 static <T> Predicate<T> isEqual(Object targetRef) { return (null == targetRef) ? Objects::isNull : object -> targetRef.equals(object); }
定义:方法引用是用来直接访问类或者实例的已经存在的方法或者构造方法。方法引用提供了一种引用而不执行方法的方式,它需要由兼容的函数式接口构成的目标类型上下文。计算时,方法引用会创建函数式接口的一个实例。
当Lambda表达式中只是执行一个方法调用时,不用Lambda表达式,直接通过方法引用的形式可读性更高一些。方法引用是一种更简洁易懂的Lambda表达式。
注意方法引用是一个Lambda表达式,其中方法引用的操作符是双冒号"::"。
4种类型
类型 | 示例 |
---|---|
引用静态方法 | ContainingClass::staticMethodName |
引用某个对象的实例方法 | containingObject::instanceMethodName |
引用某个类型的任意对象的实例方法 | ContainingType::methodName |
引用构造方法 | ClassName::new |
ps:这里引用构造方法,返回的不是一个实例对象,是一个实例对象的工厂。
Demo:
public class Test { public static void main(String args[]){ List names = new ArrayList(); names.add("Google"); names.add("Runoob"); names.add("Taobao"); names.add("Baidu"); names.add("Sina"); names.forEach(System.out::println); } }
简单的说,optional就是一个对类的加工,一种包装器,主要用来解决NPE的问题。
简单用法:
Demo
public class Test { public static void main(String args[]){ Test test = new Test(); Integer value1 = null; Integer value2 = new Integer(10); // Optional.ofNullable - 允许传递为 null 参数 Optional<Integer> a = Optional.ofNullable(value1); //请少用下面这个 // Optional.of - 如果传递的参数是 null,抛出异常 NullPointerException Optional<Integer> b = Optional.of(value2); System.out.println(test.sum(a,b)); } public Integer sum(Optional<Integer> a, Optional<Integer> b){ //也请少用 // Optional.isPresent - 判断值是否存在 System.out.println("第一个参数值存在: " + a.isPresent()); System.out.println("第二个参数值存在: " + b.isPresent()); // Optional.orElse - 如果值存在,返回它,否则返回默认值 Integer value1 = a.orElse(new Integer(0)); //Optional.get - 获取值,值需要存在 Integer value2 = b.get(); return value1 + value2; } }
高级用法
Demo
public class User { private long id; private String name; private int age; private Optional<Long> phone; private Optional<String> email; public User(String name, int age) { this.name = name; this.age = age; } // 省略setter和getter } public class OptionalDemo { public static void main(String[] args) { User user = new User("jh",25); Optional<User> optUser= Optional.ofNullable(user); String name = optUser.map(User::getName).orElse("no name"); //long phone = optUser.map(User::getPhone).orElse(-1L); 这个是错误的 //map(User::getPhone) 返回的是 Optional<Optional<Long>> long phone = optUser.map(User::getPhone).map(Optional::get).orElse(-1L); long phone2 = optUser.flatMap(User::getPhone).orElse(-1L); optUser.filter(u -> u.getAge() >= 18).ifPresent(u -> System.out.println("Adult:" + u)); } }
ps:
Optional是一个final类,未实现任何接口,所以如果我们定义的类有序列化的需求,那么因为Optional没有实现Serializable接口,这个时候执行序列化操作就会有问题:
public class User implements Serializable{ private long id; private String name; private int age; private Optional<Long> phone; // 不能序列化 private Optional<String> email; // 不能序列化 }
采用这种方式替换:
private long phone; public Optional<Long> getPhone() { return Optional.ofNullable(this.phone); }
流的概念定义:支持数据处理操作的源生成的元素序列。
Stream不是集合元素,它不是数据结构并不保存数据,它是有关算法和计算的,它更像一个高级版本的Iterator。
Stream操作:1.生成stream。2.中间操作(各种处理)。3.结束操作(形成最终结果)。
特点:
1 . 不是数据结构,不会保存数据。
demo:
//常用的流的获取 //Collection下的 List<String> list = new ArrayList<>(); Stream<String> listStream = list.stream(); //获取一个顺序流 Stream<String> parallelStream = list.parallelStream(); //获取一个并行流 //arrays下的 Integer[] nums = new Integer[10]; Stream<Integer> stream = Arrays.stream(nums); //静态方法 of,iterate,generate Stream<Integer> stream1 = Stream.of(1,2,3,4,5,6); Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 2).limit(6); stream2.forEach(System.out::println); // 0 2 4 6 8 10 Stream<Double> stream3 = Stream.generate(Math::random).limit(2); stream3.forEach(System.out::println); //从文件中读取 BufferedReader reader = null; try { reader = new BufferedReader(new FileReader("F:\\test_stream.txt")); } catch (FileNotFoundException e) { e.printStackTrace(); } Stream<String> lineStream = reader.lines(); //常用的中间操作 Stream<Integer> stream = Stream.of(6, 4, 6, 7, 3, 9, 8, 10, 12, 14, 14); Stream<Integer> newStream = stream.filter(s -> s > 5) //过滤 6 6 7 9 8 10 12 14 14 .distinct() //去重 6 7 9 8 10 12 14 .skip(2) //跳过前n个 9 8 10 12 14 .limit(2) //获取前n个 9 8 .map(n->n+1) // 10 9 映射成一个新的流 .sorted(); //排序,有重载方法可自定义排序规则 //扁平化 Stream<List<Integer>> inputStream = Stream.of( Arrays.asList(1), Arrays.asList(2, 3), Arrays.asList(4, 5, 6) ); Stream<Integer> outputStream = inputStream. flatMap((childList) -> childList.stream()); //常用的结束操作 List<Integer> list = Arrays.asList(1, 2, 3, 4, 5); boolean allMatch = list.stream().allMatch(e -> e > 10); //false boolean noneMatch = list.stream().noneMatch(e -> e > 10); //true boolean anyMatch = list.stream().anyMatch(e -> e > 4); //true Integer findFirst = list.stream().findFirst().get(); //1 Integer findAny = list.stream().findAny().get(); //1 long count = list.stream().count(); //5 Integer max = list.stream().max(Integer::compareTo).get(); //5 Integer min = list.stream().min(Integer::compareTo).get();//1 //常用结束操作 boolean allMatch = list.stream().allMatch(e -> e > 10); //false boolean noneMatch = list.stream().noneMatch(e -> e > 10); //true boolean anyMatch = list.stream().anyMatch(e -> e > 4); //true Integer findFirst = list.stream().findFirst().get(); //1 Integer findAny = list.stream().findAny().get(); //1 long count = list.stream().count(); //5 Integer max = list.stream().max(Integer::compareTo).get(); //5 Integer min = list.stream().min(Integer::compareTo).get();//1 list.stream().forEach(System.out::println); List<String> list2 = Arrays.asList("1","2","3","4"); List<Integer> collect = list2.stream().map(Integer::parseInt).collect(Collectors.toList()); //ps Collector 工具库:Collectors很强大,建议大家下来看看