一.JDK1.7版本的新特性
1.二进制字面量
2.数字字面量可以出现下划线
3.switch 语句可以用字符串
二.JDK1.8版本的新特性
1.新特性一:新增的日期时间相关类
LocalDate、 LocalTime、 LocalDateTime类
Instant 时间戳类
Duration类和Period类
TemporalAdjuster时间矫正器
DateTimeFormatter解析和格式化日期或时间的类
ZoneID 世界时区类
2.特性二:Lambda表达式
Lambda表达式的书写语法
匿名内部类的Lambda表达式简化规则
Lambda表达式可作为参数传递
Lambda表达式的另一种写法, 方法引用
构造器引用
3 .特性三:Stream流
Stream 的操作三个步骤
创建Stream的方式
Stream 的中间操作
Stream 的终止操作
JDK7开始,可以 用二进制来表示整数 (byte,short,int和long)。使用二进制字面量的好处是可以使代码更容易被理解。语法非常简单,只要在二进制数值前面加 0b或者0B, 例: int x = 0b110110.
为了增强对数值的阅读性,如我们经常把数据用逗号分隔一样。JDK7提供了 _对数据分隔 。注意事项:不能出现在进制标识和数值之间 / 不能出现在数值开头和结尾 / 不能出现在小数点旁边. 例:int x = 100_1000;
public class Test {
public static void main(String[] args) {
String s="HELLO";
switch (s){
case "a":
System.out.println("a");
break;
case "HELLO":
System.out.println("HELLO");
break;
}
}
}
还有一个泛型简化的特性
LocalDate、 LocalTime、 LocalDateTime类的实例是不可变的对象, 分别表示使用 ISO-8601日历系统的 日期、时间、日期和时间。 它们提供了简单的日期或时间,并不包含当前的时间信息。也不包含与时区相关的信息。 注: ISO-8601日历系统是国际标准化组织制定的现代公民的日期和时间的表示法 这些新增的日期时间API都在 java.time包下
获取对象的方法
常用方法
Duration 是用于 计算两个“时间”间隔 的类, 而 Period 是用于 计算两个“日期”间隔 的类 .
Duration类常用的方法如下:
Period类计算两个日期之间的间隔的代码如下:
LocalDate s = LocalDate.of(1985, 03, 05);
LocalDate now = LocalDate.now();
Period be = Period.between(s, now);
System.out.println(be.getYears());间隔了多少年
System.out.println(be.getMonths());间隔了多少月
System.out.println(be.getDays());间隔多少天
TemporalAdjuster时间矫正器是一个接口,一般我们用该接口的一个对应的工具类, TemporalAdjusters中的一些常量,来指定日期
LocalDate now = LocalDate.now();
System.out.println(now);
//1 使用TemporalAdjusters自带的常量来设置日期
LocalDate with = now.with(TemporalAdjusters.lastDayOfYear());
System.out.println(with);
//2 采用TemporalAdjusters中的next方法来指定日期
LocalDate date = now.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
System.out.println(date);
例如:TemporalAdjusters.next(DayOfWeek.SUNDAY) 本周的星期天
例如:TemporalAdjusters.nextOrSame(DayOfWeek.MONDAY) 下一周的星期一
//3 采用自定义的方式来指定日期 比如指定下个工作日
LocalDateTime ldt = LocalDateTime.now();
LocalDateTime workDay = ldt.with(new TemporalAdjuster() {
@Override
public Temporal adjustInto(Temporal temporal) {
//向下转型
LocalDateTime ld = (LocalDateTime) temporal;
//获取这周的星期几
DayOfWeek dayOfWeek = ld.getDayOfWeek();
if (dayOfWeek.equals(DayOfWeek.FRIDAY)) {
return ld.plusDays(3);//如果这天是星期五,那下个工做日就加3天
} else if (dayOfWeek.equals(DayOfWeek.SATURDAY)) {
return ld.plusDays(2);//如果这天是星期六,那下个工做日就加2天
} else {
//其他就加一天
return ld.plusDays(1);
}
}
});
System.out.println(workDay);
常用的方法:
DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDateTime now = LocalDateTime.now();
String format1 = dateFormat.format(now);
System.out.println(format1);
LocalDateTime now1 = LocalDateTime.now();
//使用日期类中的format方法 传入一个日期格式化类对象
//使用DateTimeFormatter中提供好的日期格式常量
now1.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
DateTimeFormatter timeFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");//自定义一个日期格式
String time = now1.format(timeFormat);
System.out.println(time);
DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDateTime parse = LocalDateTime.parse(time, timeFormat);
System.out.println(parse);
补: ZonedDate,ZonedTime和ZonedDateTime : 带时区的时间或日期, 用法和 LocalDate、 LocalTime、 LocalDateTime 一样 只不过ZonedDate,ZonedTime、ZonedDateTime 这三个带有当前系统的默认时区
//创建日期对象
LocalDateTime now = LocalDateTime.now();
//获取不同国家的日期时间根据各个地区的时区ID名创建对象
ZoneId timeID = ZoneId.of("Asia/Shanghai");
//根据时区ID获取带有时区的日期时间对象
ZonedDateTime time = now.atZone(timeID);
System.out.println(time);
//方式2 通过时区ID 获取日期对象
LocalDateTime now2 = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
System.out.println(now2);
Lambda 是一个匿名函数,我们可以把 Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。也就相当于一种简写模式!
Lambda 表达式在Java 语言中引入了一个新的语法元素和操作符。这个操作符为 “ ->” , 该操作符被称为 Lambda 操作符或箭头操作符。它将 Lambda 分为两个部分:左侧和右侧!
左侧: 指定了 Lambda 表达式需要的所有参数(形参列表) 右侧: 指定了 Lambda 体,即 Lambda 表达式要执行的功能 。(方法的具体实现)例:
public static void main(String[] args) {
//匿名内部类
MyInterface myInterface = new MyInterface() {
@Override
public void show() {
System.out.println("哈哈");
}
};
//lambda表达式
MyInterface myInterface2 = () -> {
System.out.println("哈哈");
};
MyInterface myInterface = new MyInterface() {
@Override
public Integer show(Integer a, Integer b) {
return a + b;
}
};
//第一步:简化 左边部分:是形参列表 右边部分:是对接口的抽象方法的具体实现
MyInterface myInterface2 = (Integer a, Integer b) -> {
return a + b;
};
//第二步简化:可以省略形参类型
MyInterface myInterface3 = (a, b) -> {
return a + b;
};
//第三步简化:对接中的方法的实现只有一行代码,那么{}和return都可以省略不写
MyInterface myInterface4 = (a, b) -> a + b;
//如果对接中的方法的实现,不止有一行代码,那么{}和return 不能省略
MyInterface myInterface = new MyInterface() {
@Override
public Integer show(Integer a, Integer b) {
a += 10;
b += 20;
return a + b;
}
};
//省略后
MyInterface myInterface5 = (a, b) -> {
a += 10;
b += 20;
return a + b;
};
//如果 形参只有一个,形参的括号可以省略不写
AA aa = a -> System.out.println(a);
}
}
Lambda表达式, 只支持函数式接口 。函数式接口就是这个接口中只有一个抽象方法。 @FunctionalInterface 这个注解可以标识他是一个函数式接口 。我们可以在任意函数式接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口。
@FunctionalInterface //这个注解可以标识他是一个函数式接口
//函数式接口
public interface MyInterface {
Integer show(Integer a, Integer b);
}
public class MyTest {
public static void main(String[] args) {
Integer[] arr = {20, 1, 6};
//给数组arr排序
Arrays.sort(arr, new Comparator() {
@Override
public int compare(Integer x, Integer y) {
return x - y;
}
});
//Lambda表达式 作为参数传递
Comparator tComparator = (a, b) -> a - b;
Arrays.sort(arr, tComparator);
Arrays.sort(arr, (a, b) -> a - b);
}
}
Java中提供的4大核心函数式接口
函数式接口 |
参数类型 |
返回类型 |
用途 |
Consumer 消费型接口 |
T |
void |
对类型为T的对象应用操 |
Supplier 供给型接口 |
无 |
T |
返回类型为T的对象,包 |
Function 函数型接口 |
T |
R |
对类型为T的对象应用操 |
Predicate |
T |
boolean |
确定类型为T的对象是否 |
方法引用其实是Lambda表达式的另一种写法, 当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用. 注意:实现抽象方法的参数列表,必须与方法引用方法的参数列表保持一致!方法引用:使用操作符 “ ::” 将方法名和对象或类的名字分隔开来。存在三种主要使用情况,对象::实例方法 / 类::静态方法 / 类::实例方法
public class MyTest {
public static void main(String[] args) {
//情况一 对象::实例方法
Consumer consumer = new Consumer() {
@Override
public void accept(String s) {
PrintStream out = System.out;
out.println(s);
}
};
Consumer consumer2 = msg -> System.out.println(msg);
//最终版的简化
Consumer consumer3 = System.out::println;
//情况二 类::静态方法
int max = Math.max(5, 6);
BiFunction biFunction = new BiFunction() {
@Override
public Integer apply(Integer x, Integer y) {
return Math.max(x, y);
}
};
BiFunction biFunction2 = (x, y) -> Math.max(x, y);
//最终简化
BiFunction biFunction3 = Math::max;
//情况三 类::实例方法
Comparator comparator = new Comparator() {
@Override
public int compare(String x, String y) {
return x.compareTo(y);
}
};
Comparator comparator2 = (x, y) -> x.compareTo(y);
//最终简化
Comparator comparator3 = String::compareTo;
}
}
构造器引用的格式:ClassName::new。与函数式接口相结合,自动与函数式接口中方法兼容。可以把构造器引用赋值给定义的方法,与构造器参数列表要与接口中抽象方法的参数列表一致!
public class Student {
String name;
int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
}
public class MyTest {
public static void main(String[] args) {
Supplier supplier = new Supplier() {
@Override
public Student get() {
return new Student();
}
};
Supplier supplier2 = () -> new Student();
//最终简化
Supplier supplier3 = Student::new;
BiFunction biFunction = new BiFunction() {
@Override
public Student apply(String name, Integer age) {
return new Student(name, age);
}
};
BiFunction biFunction2 = (name, age) -> new Student(name, age);
//最终简化
BiFunction biFunction3 = Student::new;
}
}
Stream 是 Java8 中处理集合的关键抽象概念, 它可以指定你希望对集合进行的操作, 可以执行非常复杂的查找、过滤和映射数据等操作。 使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。 简而言之, Stream API 提供了一种高效且易于使用的处理数据的方式。
流(Stream)是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。 集合讲的是数据,流讲的是计算! 需要注意:
Java8 中的 Collection 接口被扩展,提供了两个获取流的方法:
Java8 中的 Arrays 的静态方法 stream() 可以获取数组流:static
由值创建流,可以使用静态方法 Stream.of(), 通过显示值创建一个流。它可以接收任意数量的参数。
由函数创建流:创建无限流可以使用静态方法 Stream.iterate()和Stream.generate(), 创建无限流。
public class MyTest {
public static void main(String[] args) {
//创建流
//方式1:
List list = Arrays.asList(100, 200, 300, 7000, 90, 4);
//集合里面有一个 stream() 方法,就可以得到这个流
Stream stream = list.stream();
Integer[] arr = {20, 30, 80, 35, 85};
//方式2
//Arrays里面的静态方法stream()方法,就可以得到这个流
Stream stream1 = Arrays.stream(arr);
//方式3 Stream类他有一个静态方法,可以得到这个流
Stream stream2 = Stream.of(100, 200, 300, 7000, 90, 100);
//方式4 创建无限流
Stream generate = Stream.generate(Math::random);
//方式5:创建无限流
Stream iterate = Stream.iterate(1, new UnaryOperator() {
@Override
public Integer apply(Integer integer) {
return integer + 1;
}
});
iterate.limit(10).forEach(System.out::println);
}
}
多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为“ 惰性求值 ”。
筛选与切片
映射
排序
终端操作会从流的流水线生成结果。其结果可以是任何不是流的值,例如:List、Integer,甚至是 void 。
查找与匹配
归约
备注:map 和 reduce 的连接通常称为 map-reduce 模式,因 Google 用它来进行网络搜索而出名。
收集
public class MyTest {
public static void main(String[] args) {
//终止操作
List list = Arrays.asList(
new Employee(101, "张三", 18, 9999.99),
new Employee(101, "张三", 18, 9999.99),
new Employee(101, "张三", 18, 9999.99),
new Employee(101, "张三", 18, 9999.99),
new Employee(103, "王五", 28, 3333.33),
new Employee(102, "李四", 59, 6666.66),
new Employee(104, "赵六", 80, 7777.77),
new Employee(104, "赵六", 80, 7777.77),
new Employee(104, "赵六", 80, 7777.77),
new Employee(105, "田七", 38, 5555.55)
);
//判断是否所有员工都满18岁了
//allMatch(Predicate p) 检查是否匹配所有元素
boolean b = list.stream().allMatch(emp -> emp.getAge() >= 18);
System.out.println(b);
//判断员工有么有姓王的
boolean b1 = list.stream().anyMatch(ele -> ele.getName().startsWith("刘"));
System.out.println(b1);
//是不是员工没有姓王
boolean b2 = list.stream().noneMatch(ele -> ele.getName().startsWith("王"));
System.out.println(b2);
//获取工资最高的员工
Optional first = list.stream().sorted((x, y) -> (int) (y.getSalary() - x.getSalary())).findFirst();
Employee employee = first.get();
System.out.println(employee);
//获取最高工资
//findFirst() 返回第一个元素
Optional first1 = list.stream().map(Employee::getSalary).sorted((x, y) -> (int) (y - x)).findFirst();
Double aDouble = first1.get();
System.out.println(aDouble);
Employee employee = list.stream().max((a, b) -> (int) (a.getSalary() - b.getSalary())).get();
System.out.println(employee);
//要最小工资
Double aDouble = list.stream().map(Employee::getSalary).min((a, b) -> (int) (a - b)).get();
System.out.println(aDouble);
//统计总工资
Optional reduce = list.stream().map(Employee::getAge).distinct().reduce((a, b) -> a + b);
Integer sum = reduce.get();
System.out.println(sum);
System.out.println("=============================");
Integer reduce1 = list.stream().distinct().map(Employee::getAge).reduce(0, (a, b) -> a + b);
System.out.println(reduce1);
//串行流 stream()
//并行流: parallelStream()
Optional any = list.parallelStream().distinct().findAny();
Employee employee1 = any.get();
System.out.println(employee1);
long count = list.stream().distinct().count();
System.out.println(count);
}
}
Collectors 中的方法
Collector 接口中方法的实现决定了如何对流执行收集操作(如收集到 List、Set、Map)。但是 Collectors 实用类提供了很多静态方法,可以方便地创建常见收集器实例,具体方法与实例如下
public class MyTest {
public static void main(String[] args) {
List list = Arrays.asList(
new Employee(102, "李四", 59, 6666.66),
new Employee(101, "张三", 18, 9999.99),
new Employee(103, "王五", 28, 3333.33),
new Employee(104, "赵六", 8, 7777.77),
new Employee(104, "赵六", 8, 7777.77),
new Employee(104, "赵六", 8, 7777.77),
new Employee(105, "田七", 38, 5555.55)
);
//把员工的姓名收集到一个新集合
//Collectors 他里面有很多的方法
List collect = list.stream().distinct().map(Employee::getName).collect(Collectors.toList());
System.out.println(collect);
Set collect1 = list.stream().map(Employee::getName).collect(Collectors.toSet());
System.out.println(collect1);
//可以收集到指定的集合
LinkedHashSet collect2 = list.stream().map(Employee::getName).collect(Collectors.toCollection(LinkedHashSet::new));
System.out.println(collect2);
Long collect3 = list.stream().distinct().collect(Collectors.counting());
System.out.println(collect3);
Integer collect4 = list.stream().distinct().collect(Collectors.summingInt(Employee::getAge));
System.out.println(collect4);
System.out.println("===================================");
Double collect5 = list.stream().collect(Collectors.averagingDouble(Employee::getSalary));
System.out.println(collect5);
System.out.println("============================================");
DoubleSummaryStatistics dss = list.stream().collect(Collectors.summarizingDouble(Employee::getSalary));
double max = dss.getMax();
double min = dss.getMin();
long count = dss.getCount();
double sum = dss.getSum();
double average = dss.getAverage();
System.out.println(max);
System.out.println(min);
System.out.println(count);
System.out.println(average);
System.out.println(sum);
System.out.println("==========================================");
String collect6 = list.stream().map(Employee::getName).collect(Collectors.joining("-"));
System.out.println(collect6);
String collect7 = list.stream().map(Employee::getName).collect(Collectors.joining("-", "[", "]"));
System.out.println(collect7);
}
}
补:并行流stream()与串行流 parallelStream(), 并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。Java 8 中将并行进行了优化,我们可以很容易的对数据进行并行操作。Stream API 可以声明性地通过 parallel() 与sequential() 在并行流与顺序流之间进行切换。
(小编也在努力学习更多哟!以后再慢慢分享的啦!)
希望对友友们有所帮助!!!!