java8中重要的4个新特性:
- Lambda
- Stream
- Optional
- 日期时间API
- 接口方法(default和static方法,jdk9可定义private方法)
一、Lambda
1 import java.util.Comparator; 2 import java.util.function.Consumer; 3 4 /** 5 * @author zhaojigang 6 * @date 2018/5/19 7 */ 8 public class LambdaTest { 9 /**10 * Lambda 是一个匿名函数。11 * 1、语法12 * Lambda表达式引入了操作符为"->",该操作符将Lambda分为两个部分:13 * 左侧:指定了Lambda表达式需要的所有参数14 * 右侧:指定了Lambda体,即Lambda表达式要执行的功能。15 *16 * 2、示例17 */18 public void testLambda() {19 /**20 * 语法格式一:无参,无返回值21 */22 Runnable task = () -> System.out.println("hello lambda");23 /**24 * 语法格式二:一个参数,无返回值25 * 注意:参数类型可以通过26 */27 Consumerconsumer = str -> System.out.println(str);28 /**29 * 语法格式三:一个参数,有返回值30 * 注意:当Lambda体只有一条语句时,省略大括号和return31 */32 Comparator comparator = (x, y) -> Integer.compare(x, y);33 }34 35 /**36 * 函数式接口:只包含一个抽象方法的接口。37 * 1、可以通过Lambda表达式来创建该接口的对象38 * 2、可以在任意函数式接口上使用@FunctionalInterface注解,这样做可以检查它是否是一个函数式接口39 *40 * Java内置了四大核心函数式接口:41 * 1、Consumer :void accept(T t),消费型接口42 * 2、Supplier :T get(),供给型接口43 * 3、Function :R apply(T t),函数型接口44 * 4、Predicate :boolean test(T t),断言型接口45 * 还有部分子接口。46 */47 public void testFunctionalInterface() {48 Consumer consumer = str -> System.out.println(str);49 }50 }
二、Stream
1 import java.util.ArrayList; 2 import java.util.HashMap; 3 import java.util.List; 4 import java.util.Map; 5 import java.util.Optional; 6 import java.util.OptionalLong; 7 import java.util.stream.LongStream; 8 9 /** 10 * @author zhaojigang 11 * @date 2018/5/19 12 */ 13 public class StreamTest { 14 15 static ListintegerList = new ArrayList () { { 16 add(1); 17 add(2); 18 add(3); 19 add(4); 20 add(5); 21 add(5); 22 add(5); 23 }}; 24 25 static List integerList2 = new ArrayList () { { 26 add(10); 27 add(20); 28 add(30); 29 }}; 30 31 static Map > map1 = new HashMap<>(); 32 33 static { 34 map1.put("list1", integerList); 35 map1.put("list2", integerList2); 36 } 37 38 /** 39 * 分片与筛选 40 */ 41 public static void test1() { 42 integerList.stream() 43 .filter(x -> x > 2) // 3,4,5,5,5 44 .skip(2) //5,5,5 45 .limit(2) //5,5 短路:一旦获取到2个元素后不再向后迭代 46 .distinct() //5 47 .forEach(System.out::println); 48 } 49 50 /** 51 * 映射 52 * map(Function f):接收一个函数作为参数,该函数会被应用到每个元 素上,并将其映射成一个新的元素 53 * flatMap(Function f):接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流 54 */ 55 public static void test2() { 56 integerList.stream() 57 .map(x -> x + 10) 58 .forEach(System.out::println); 59 60 map1.values().stream() 61 .flatMap(x -> x.stream()) // x是每一个List,flatMap将每一个List的Stream合并起来 62 .forEach(System.out::println); 63 64 } 65 66 /** 67 * 排序 68 * sorted():产生一个新流,其中按自然顺序排序(按照元素的Comparable接口) 69 * sorted(Comparator comp):产生一个新流,其中按比较器顺序排序(按照自定义的Comparator) 70 */ 71 public static void test3() { 72 integerList.stream() 73 .sorted() 74 .forEach(System.out::println); 75 76 integerList.stream() 77 .sorted((x, y) -> { 78 if (x < y) { 79 return 1; 80 } else { 81 return -1; 82 } 83 }) 84 .forEach(System.out::println); 85 86 } 87 88 /** 89 * 查找与匹配 90 * allMatch(Predicate p):检查是否匹配所有元素 91 * anyMatch(Predicate p):检查是否至少匹配一个元素 92 * noneMatch(Predicate p):检查是否没有匹配所有元素 93 * findFirst():返回第一个元素 94 * findAny():返回当前流中的任意元素 95 * count():返回流中元素总数 96 * max(Comparator c):返回流中最大值 97 * min(Comparator c):返回流中最小值 98 */ 99 public static void test4() {100 final boolean allMatch = integerList.stream().allMatch(x -> x > 4);101 final boolean anyMatch = integerList.stream().anyMatch(x -> x > 4);102 final boolean noneMatch = integerList.stream().noneMatch(x -> x > 4);103 final Optional first = integerList.stream().filter(x -> x > 3).findFirst();104 final Optional any = integerList.stream().filter(x -> x > 3).findAny();105 final long count = integerList.stream().filter(x -> x > 4).count();106 final Optional max = integerList.stream()107 .max((x, y) -> {108 if (x < y) {109 return 1;110 } else {111 return -1;112 }113 });114 115 }116 117 /**118 * 规约119 * 120 * reduce(T iden, BinaryOperator b):可以将流中元素反复结合起来,得到一个值。返回T,其中iden是初始值121 * reduce(BinaryOperator b):可以将流中元素反复结合起来,得到一个值。返回Optional
122 */123 public static void test5() {124 // 计算:100+1+2+3+4+5+5+5125 final Integer sum = integerList.stream().reduce(100, (x, y) -> x + y);126 final Optional sumOptional = integerList.stream().reduce((x, y) -> x + y);127 }128 129 /**130 * 收集131 * 常用:132 * 1、将流元素收集到List:List emps= list.stream().collect(Collectors.toList());133 * 2、将流元素收集到Set:List emps= list.stream().collect(Collectors.toSet());134 * 3、连接流中每个字符串:String str= list.stream().map(Employee::getName).collect(Collectors.joining());135 * 4、分组: Map > map= list.stream().collect(Collectors.groupingBy(Employee::getStatus));136 *137 * 不常用:138 * 1、根据true或false进行分区:Map >vd= list.stream().collect(Collectors.partitioningBy(Employee::getManage));139 * 2、根据比较器选择最大值:Optional max= list.stream().collect(Collectors.maxBy(comparingInt(Employee::getSalary)));140 * 3、根据比较器选择最小值:Optional min = list.stream().collect(Collectors.minBy(comparingInt(Employee::getSalary)));141 * 4、将流元素收集到任意指定集合:Collection emps=list.stream().collect(Collectors.toCollection(ArrayList::new));142 * 5、计算流中元素的个数:long count = list.stream().collect(Collectors.counting());143 * 6、对流中元素的属性求和:int total=list.stream().collect(Collectors.summingInt(Employee::getSalary));144 * 7、计算流中元素Integer属性的平均值:double avg= list.stream().collect(Collectors.averagingInt(Employee::getSalary));145 */146 public static void test6() {147 }148 149 /**150 * 并行流与串行流151 * 并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。152 * 底层:fork/join153 * Stream API可以声明性地通过parallel()与sequential()在并行流与顺序流之间进行切换154 */155 public static void test7(){156 long start = System.currentTimeMillis();157 158 final OptionalLong sum = LongStream.rangeClosed(0, 100000000000L)159 .parallel()160 .reduce(Long::sum);161 162 System.out.println(sum + "-" + (System.currentTimeMillis() - start));163 }164 165 public static void main(String[] args) {166 test7();167 }168 }
三、Optional
1 import java.util.Optional; 2 3 /** 4 * @author zhaojigang 5 * @date 2018/5/19 6 */ 7 public class OptionalTest { 8 9 public static void main(String[] args) {10 // String godName = "shijia";11 String godName = null;12 // 常用方式13 final String god = Optional.ofNullable(godName).orElse("yesu");14 System.out.println(god);15 }16 }
四、日期时间API
1 import java.time.Duration; 2 import java.time.Instant; 3 import java.time.LocalDateTime; 4 import java.time.format.DateTimeFormatter; 5 6 /** 7 * @author zhaojigang 8 * @date 2018/5/19 9 */10 public class TimeTest {11 12 /**13 * 一、日期创建:14 * LocalDate localDate = LocalDate.now();15 * LocalTime localTime = LocalTime.now();16 * LocalDateTime localDateTime = LocalDateTime.now();17 *18 * LocalDate localDate = LocalDate.of(2016, 10, 26);19 * LocalTime localTime = LocalTime.of(02, 22, 56);20 * LocalDateTime localDateTime = LocalDateTime.of(2016, 10, 26, 12, 10, 55);21 *22 * 二、日期加减运算23 * plusDays, plusWeeks, plusMonths, plusYears24 * minusDays, minusWeeks, minusMonths, minusYears25 * plus, minus26 *27 * 三、日期比较计算28 * isBefore, isAfter29 *30 * 四、是否闰年31 * isLeapYear32 *33 * 五、时间戳与时间间隔运算34 * Instant 时间戳:以Unix元年(传统的设定为UTC时区1970年1月1日午夜时分)开始所经历的描述进行运算35 * Duration:用于计算两个“时间”间隔36 * Period:用于计算两个“日期”间隔37 *38 * 六、时间校正器39 * TemporalAdjuster/TemporalAdjusters 调整时间:例如获取下一个周日等40 *41 * 七、日期解析和格式化42 * java.time.format.DateTimeFormatter类43 */44 public static void main(String[] args) {45 /**46 * 计算时间间隔47 */48 Instant in1 = Instant.now();49 Instant in2 = Instant.now();50 System.out.println(Duration.between(in1, in2).toMillis());51 52 /**53 * 日期格式化54 */55 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");56 LocalDateTime time1 = LocalDateTime.now();57 String formatDateTime = time1.format(formatter);58 59 /**60 * 日期解析61 */62 LocalDateTime dateTime = LocalDateTime.parse(formatDateTime, formatter);63 }64 }
日期操作我们通常会使用Apache commons包,但是这样就会引入一个包,能够使用java本身的就是用java本身的。
五、接口方法
1 /** 2 * @author zhaojigang 3 * @date 2018/5/19 4 */ 5 public class InterfaceTest { 6 public static void main(String[] args) { 7 MyImpl myClass = new MyImpl(); 8 System.out.println(myClass.getName()); 9 System.out.println(MyInterface.getAge());10 }11 }12 13 interface MyInterface {14 default String getName(){15 return "nana";16 }17 18 static Integer getAge(){19 return 18;20 }21 }22 23 /**24 * 若一个接口中定义了一个默认方法,而另外一个父类中又定义了一个同名的方法时,取父类25 * 若一个接口中定义了一个默认方法,而另外一个实现接口中又定义了一个同名的方法时,实现类需要执行重写其中一个26 */27 class MyImpl implements MyInterface {28 }
在jdk9中,接口中可以定义private方法。