Java学习笔记

1 Java中从函数式编程中引入的两个核心思想:将方法和Lambda作为一等值,以
及在没有可变共享状态时,函数或方法可以有效、安全地并行执行。
这两个要点(没有共享的可变数据,将方法和函数即代码传递给其他方法的能力)是我们平
常所说的函数式编程范式的基石。

2 利用已定义的函数式接口,可以解析一个Lambda表达式。函数式接口作用是,用于描述各种lamdba表达式的签名。

例如 ()->new apple(10); 这个lambda利用的是Supplier<apple>这个函数式接口,它的描述是()->T

而对于方法的创建,创建方法时,传入的参数可以是函数式接口,这样方法就可以接收一个lambda表达式。例如forEach方法就是:

Consumer接口:

@FunctionalInterface
public interface Consumer<T>{
void accept(T t);
}

创建forEach方法:
public static <T> void forEach(List<T> list, Consumer<T> c){
for(T i: list){
c.accept(i);
}
}

使用forEach方法:
forEach(
Arrays.asList(1,2,3,4,5),
(Integer i) -> System.out.println(i)
);
Lambda的类型是从使用Lambda的上下文推断出来的。

例如这里的 Consumer<T>  c =(Integer i) -> System.out.println(i)解析时T绑定到integer,

Consumer的抽象方法Accept正好也接收一个interger,返回void,而System.out.println(i)符合这一签名,因此代码类型检查无误。
3 关于lambda中为什么不能使用非final的局部变量:
Java 8Lambda和匿名类可以做类似于闭包的事情:
它们可以作为参数传递给方法,并且可以访问其作用域之外的变量。但有一个限制:它们不
能修改定义Lambda的方法的局部变量的内容。这些变量必须是隐式最终的。可以认为Lambda
是对值封闭,而不是对变量封闭。如前所述,这种限制存在的原因在于局部变量保存在栈上,
并且隐式表示它们仅限于其所在线程。如果允许捕获可改变的局部变量,就会引发造成线程
不安全的新的可能性,而这是我们不想看到的(实例变量可以,因为它们保存在堆中,而堆
是在线程之间共享的)。
4 流数据streama
流只能被消费一次。比如,同一个流不能用两次foreach。

与集合相比java8 用的内部迭代,处理器能够优化处理顺序,并行等,性能更优一些。流操作:连接起来的流操作称为中间操作,关闭流的操作称为终端操作 

Optional<T>类(java.util.Optional)是一个容器类,代表一个值存在或不存在

 如 果 包 含 一 个值就打印它,否则什么都不做 

menu.stream().filter(Dish::isVegetarian).findAny()--------------------------返回一个Optional<Dish> 

.ifPresent(d -> System.out.println(d.getName())

6 有状态和无状态

诸如mapfilter等操作会从输入流中获取每一个元素,并在输出流中得到01个结果。
这些操作一般都是无状态的:它们没有内部状态
但诸如reducesummax等操作需要内部状态来累积结果。在上面的情况下,内部状态
很小。在我们的例子里就是一个intdouble。不管流中有多少元素要处理,内部状态都是 
有界的。

相反,诸如sortdistinct等操作一开始都和filtermap差不多——都是接受一个
流,再生成一个流(中间操作),但有一个关键的区别。从流中排序和删除重复项时都需要知
道先前的历史。例如,排序要求所有元素都放入缓冲区后才能给输出流加入一个项目,这一操
作的存储要求是无界的。要是流比较大或是无限的,就可能会有问题(把质数流倒序会做什么
呢?它应当返回最大的质数,但数学告诉我们它不存在)。我们把这些操作叫作有状态操作。
流有三种基本的原始类型特化: IntStreamDoubleStreamLongStream。它们的操
作也有相应的特化。 节省了装箱成本。
8 Optional类的使用

a 将可能为空的对象创建一个option对象Optional.ofNullable(object);
b 如果还有可能为空的对象,则继续使用optional类,调用map方法

c 如果没有为空的对象了,用orElse将optional类中的值取出来进行下一步处理。可将值.stream利用里面的方法进行计算。

 9 java8中的日期和时间

Duration类主要用于以秒和纳秒衡量时间的长短,你不能仅向between方法传递一个LocalDate对象做参数。 

Duration d1 = Duration.between(dateTime1, dateTime2);
Duration d2 = Duration.between(instant1, instant2);
如果你需要以年、月或者日的方式对多个时间单位建模,可以使用Period
Period tenDays = Period.between(LocalDate.of(2014, 3, 8),

LocalDate.of(2014, 3, 18));
10. 每个特定的ZoneId对象对应一个地区Id表示

ZoneId romeZone = ZoneId.of("Europe/Rome");

一旦得到一个ZoneId对象,你就可以将它与LocalDateLocalDateTime或者是Instant
对象整合起来,构造为一个ZonedDateTime实例,它代表了相对于指定时区的时间点,

通过ZoneId,可以将LocalDateTime转换为Instant
LocalDateTime dateTime = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45);
Instant instantFromDateTime = dateTime.toInstant(romeZone);
也可以通过反向的方式得到LocalDateTime对象:
Instant instant = Instant.now();
LocalDateTime timeFromInstant = LocalDateTime.ofInstant(instant, romeZone);
11 新版的日期和时间API中,日期时间对象是不可变的。
你可以用绝对或者相对的方式操纵日期和时间,操作的结果总是返回一个新的实例,老
的日期时间对象不会发生变化。



 

posted @ 2019-02-21 11:11  ZECDLLG  阅读(157)  评论(0编辑  收藏  举报