Openjdk是jdk的开放源代码版本
二者授权协议不同
OpenJDK不包含部署功能 (javaweb start /控制面板)
OpenJDK源码不完整,部分代码使用开源代码替换

多个jdk切换实现

JDK各个版本新特性 - 图1

source /etc/profile
切换命令: jdk11jdk12

JDK 5

可变参数,泛型

① 可变参数本质就是一个数组,arr就是一个数组的引用地址(反编译工具查看源代码)
②一个方法 可以有可变参数和普通参数,但是可变参数必须放到参数列表末尾;
③ 一个方法 有且只能有一个可变参数;

  1. public class Main {
  2. public static void main(String[] args) {
  3. String[] a = raaaaa("a","v","a");
  4. System.out.println(a.length);
  5. }
  6. private static <T> T[] raaaaa(T... values){
  7. for (T value : values) {
  8. // sout
  9. }
  10. return values;
  11. }
  12. }

foreach

JDK 7

try multi catch
@Override
AutoCloseable

JDK 8

https://www.shiyanlou.com/courses/539/learning/?id=1832

面对大型数据集合,java还欠缺高效的并行操作 —-> Lambda表达式
面向对象编程是对数据进行抽象,函数式编程是对行为进行抽象

一、Lambda表达式 ☆☆☆☆☆

设计匿名内部类时,是为了将代码作为数据传递,不过匿名内部类不够简便

在lambda表达式中访问外层作用域和老版本的匿名对象中的方式很相似。你可以直接访问标记了final的外层局部变量,或者实例的字段以及静态变量。

Lamda优缺点
优点:1. 简洁。2. 非常容易并行计算。3. 可能代表未来的编程趋势。
缺点:1. 若不用并行计算,很多时候计算速度没有比传统的 for 循环快。(并行计算有时需要预热才显示出效率优势)2. 不容易调试。3. 不易读

例1 旧版本如何对StringList排序

  1. List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");
  2. //传入一个List对象以及一个匿名的比较器对象 给sort方法
  3. Collections.sort(names, new Comparator<String>() {
  4. @Override
  5. public int compare(String a, String b) {
  6. return b.compareTo(a);
  7. }
  8. });

修改为lambda表达式

  1. Collections.sort(names, (String a, String b) -> {
  2. return b.compareTo(a);
  3. });

再优化(对于函数体只有一行代码的,你可以去掉大括号{}以及return关键字)

  1. Collections.sort(names, (String a, String b) -> b.compareTo(a));

再优化(Java编译器可以自动推导出参数类型,所以你可以不用再写一次类型。)

  1. Collections.sort(names, (a, b) -> b.compareTo(a));

例2 遍历赋值

外部迭代的方式,也就是for或者while循环。

  1. List persons = asList(new Person("Joe"), new Person("Jim"), new Person("John"));
  2. for (Person p : persons) {
  3. p.setLastName("Doe");
  4. }

lambda表达式

  1. persons.forEach(p->p.setLastName("Doe"));

例3 Map 的 merge 方法

  1. merge() 可以这么理解:它将新的值赋值到 key (如果不存在)或更新给定的key 值对应的
  2. 该方法接收三个参数,一个 key 值,一个 value,一个 remappingFunction ,如果给定的key不存在,它就变成了 put(key, value) 。但是,如果 key 已经存在一些值,我们 remappingFunction 可以选择合并的方式,然后将合并得到的 newValue 赋值给原先的 key。 ```java Map studentScoreMap2 = new HashMap<>(); studentScoreList.forEach(studentScore -> studentScoreMap2.merge( studentScore.getStuName(), studentScore.getScore(), Integer::sum) );

System.out.println(objectMapper.writeValueAsString(studentScoreMap2));

// 结果如下: // {“李四”:228,”张三”:215,”王五”:235}

  1. <a name="4a97f032"></a>
  2. ### Lambda表达式的几个最重要的特征:
  3. - 可选的类型声明:你不用去声明参数的类型。编译器可以从参数的值来推断它是什么类型。
  4. - 可选的参数周围的括号:你可以不用在括号内声明单个参数。但是对于很多参数的情况,括号是必需的。
  5. - 可选的大括号:如果表达式体里面只有一个语句,那么你不必用大括号括起来。
  6. - 可选的返回关键字:如果表达式体只有单个表达式用于值的返回,那么编译器会自动完成这一步。若要指示表达式来返回某个值,则需要使用大括号。
  7. <a name="8778a43d"></a>
  8. ## 二、流Stream ☆☆☆
  9. Stream作为java8的新特性,基于lambda表达式,是对集合对象功能的增强,它专注于**对集合对象进行各种高效、便利的聚合操作或者大批量的数据操作**<br />**Stream的原理:**将要处理的元素看做一种流,流在管道中传输,并且可以在管道的节点上处理,包括过滤筛选、去重、排序、聚合等。元素流在管道中经过中间操作的处理,最后由最终操作得到前面处理的结果。
  10. - stream() − 为集合创建串行流
  11. - parallelStream() - 为集合创建并行流
  12. - 中间操作主要有以下方法(此类型方法返回的都是Stream):map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered
  13. - 终止操作主要有以下方法:forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator
  14. **分组**
  15. ```java
  16. //List 以ID分组 Map<Integer,List<Apple>>
  17. Map<Integer, List<Apple>> groupBy = appleList.stream().collect(Collectors.groupingBy(Apple::getId));
  18. System.err.println("groupBy:"+groupBy);
  19. {1=[Apple{id=1, name='苹果1', money=3.25, num=10}, Apple{id=1, name='苹果2', money=1.35, num=20}], 2=[Apple{id=2, name='香蕉', money=2.89, num=30}], 3=[Apple{id=3, name='荔枝', money=9.99, num=40}]}

map(转换)

List<String> addresses = students
                            .stream()
                            .map(s ->"--"+s.getAddress())
                            .collect(Collectors.toList());
/**
 * List -> Map
 * 需要注意的是:
 * toMap 如果集合对象有重复的key,会报错Duplicate key ....
 *  apple1,apple12的id都为1。
 *  可以用 (k1,k2)->k1 来设置,如果有重复的key,则保留key1,舍弃key2
 */
Map<Integer, Apple> appleMap = appleList.stream().collect(Collectors.toMap(Apple::getId, a -> a,(k1,k2)->k1));

distinct(去重) 重写了equals和hashCode()方法

List<String> addresses = students
                .stream()
                .map(s ->"--"+s.getAddress())
                .distinct()
                .collect(Collectors.toList());

filter

Stream<Person> personStream = collection.stream().filter(new Predicate<Person>() {
    @Override
    public boolean test(Person person) {
         return "男".equals(person.getGender());//只保留男性
    }
});

Stream<Person> personStream = collection.stream()
                //只保留男性
                   .filter(person -> "男".equals(person.getGender()));

去重后遍历

students
        .stream()
        .map(s -> "--" + s.getAddress())
        .distinct()
        .forEach(addr->{
            System.out.println(addr+"--");
        });

sorted(排序)

students
        .stream()
        .map(Student::getAge)
        .distinct()
        .sorted()
        .forEach(age->{
            System.out.println(age+"--");
        });

limit(限制返回个数)
集合limit,返回前几个元素

skip(删除元素)
集合skip,删除前n个元素

reduce(聚合)

List<String> list = Arrays.asList("欢","迎","你");
 String appendStr = list.stream().reduce("北京",(a,b) -> a+b);
 System.out.println(appendStr);

求和

//计算 总金额
BigDecimal totalMoney = appleList.stream().map(Apple::getMoney).reduce(BigDecimal.ZERO, BigDecimal::add);
System.err.println("totalMoney:"+totalMoney);

min 找最小

Optional<Student> s = students
        .stream()
        .distinct()
        .min((o1, o2) -> {
            if (o1.getAge() > o2.getAge()) {
                return 1;
            } else {
                return -1;
            }
        });
System.out.println(s.get().id);

三、Optional ☆☆

public final class Optional<T> extends Object
Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。
Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
Optional 类的引入很好的解决空指针异常。

四、默认方法(Default Methods) ☆☆

在 java 8 之前,接口与其实现类之间的 耦合度 太高了(tightly coupled),当需要为一个接口添加方法时,所有的实现类都必须随之修改。默认方法解决了这个问题,它可以为接口添加新的方法,而不会破坏已有的接口的实现。这在 lambda 表达式作为 java 8 语言的重要特性而出现之际,为升级旧接口且保持向后兼容(backward compatibility)提供了途径。

五、时间

由于 SimpleDateFormat 是线程不安全的(一般使用 SimpleDateFormat 的时会把它定义成静态变量,从而避免频繁地创建它的对象实例,但 SimpleDateFormat 内部使用 Calendar 去完成日期的转换,多线程情况下可能会出现线程不安全情况)

相互转化: https://www.cnblogs.com/zszxz/p/12255663.html

可以使用Instant代替Date

// 加8小时,北京时间
Instant now = Instant.now().plusMillis(TimeUnit.HOURS.toMillis(8));
System.out.println("秒数:"+now.getEpochSecond());
System.out.println("毫秒数:"+now.toEpochMilli());

LocalDateTime代替Calendar

//获取秒数 (东8区,也就是北京时间)
Long second = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
//获取毫秒数(东8区,也就是北京时间)
Long milliSecond = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();

// 输出当前时间:2019-04-24T19:41:21.858
LocalDateTime now = LocalDateTime.now();
System.out.println(now);

// 当前时间增加20分钟
LocalDateTime afterPlusTime = LocalDateTime.now().plus(20, ChronoUnit.MINUTES);
System.out.println(afterPlusTime);

// 二者转化
Long timestamp = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
LocalDateTime time2 =LocalDateTime.ofEpochSecond(timestamp/1000,0,ZoneOffset.ofHours(8));

// 比较大小
//你的时间在当前时间之前是true
System.out.println(localDateTime.isBefore(LocalDateTime.now()));
//在当前时间之后是
System.out.println(localDateTime.isAfter(LocalDateTime.now()));

// 加减时间  2019-01-31
LocalDate localDate = LocalDate.now();
//计算去年    2018-01-31
LocalDate previousYear = localDate.minus( 1, ChronoUnit.YEARS ); 
//减30天     2019-01-01
LocalDate previousDay = localDate.minus( 30, ChronoUnit.DAYS );
// jia 坑!: 需要赋值
startLocalDateTime = startLocalDateTime.plus( 1, ChronoUnit.MONTHS);

LocalDate localDate = LocalDate.now();//当前日期
int week = localDate.getDayOfWeek().getValue();  //计算今天是星期几
LocalDate endTime = localDate.minusDays( week ); //计算上周日的日期

DateTimeFormatter代替SimpleDateFormat

LocalDateTime time = LocalDateTime.now();
String timeStr = time.format(DateTimeFormatter.ofPattern("yyyy年年MM月dd日 HH:mm:ss"));
System.out.println(timeStr);

JDK9

模块化

JDK10

var

JDK11

重要:

  1. JEP181基于嵌套的访问控制 Nest

JDK各个版本新特性 - 图2
嵌套类可以访问其他类的私有成员(1.源码级访问2.反射)
JDK各个版本新特性 - 图3

  1. JEP309 动态类文件常量
  2. JEP321 标准HTTP客户端 java.net.http包
    JDK各个版本新特性 - 图4
    同步发送get
    JDK各个版本新特性 - 图5
    异步发送get
    JDK各个版本新特性 - 图6

JDK各个版本新特性 - 图7
不重要
JDK各个版本新特性 - 图8

JDK12

20190319

重要
1.增强的switch语句
JDK各个版本新特性 - 图9
JDK各个版本新特性 - 图10

不重要
JDK各个版本新特性 - 图11

JDK 14

改进的switch表达式

第一次出现在Java 12和13中,在Java 14中获得了完全的支持
新的switch表达式的优点是,不再有缺省跳过行为(fall-through),更全面,而且表达式和组合形式更容易编写,因此出现bug的可能性就更低。例如,switch表达式现在可以使用箭头语法,如下所示:

文本块

  • instanceof支持模式匹配(语言特性)
  • NullPointerException(JVM特性)