java map 拉姆达 key排序 java lambda map函数_java8的新特性


某天【二蛋】突然说他在学习 java8 得新特性,想让自己得代码变得更优雅,逼格更高,我这才发觉Java 8已经发布很长时间了,生命在于运动,任何时候都不能停止向前探索的勇气,是时候总结一下,这个版本包含语言、编译器、库、工具和JVM等方面的十多个新特性。

  • Lambda 表达式
  • 方法引用
  • 函数式接口
  • 默认方法
  • Stream
  • Optional 类
  • Nashorn, JavaScript 引擎
  • 新的日期时间 API
  • Base64

1 Lambda 表达式

C++的程序媛笑了,这不就是函数指针吗? Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中),语法包含参数与方法体,方法体只有一条不用写return;


(parameters) -> expression 或 (parameters) ->{ statements; }


举个栗子,实现一个MathOperation接口 :


MathOperation addition = (int a, int b) -> a + b;


2 方法引用

2.1 构造器引用

语法是Class::new,或者更一般的Class< T >::new,要求构造器方法是没有参数;Java编译器会自动根据Factory.create方法的签名来选择函数。


final Car car = Car.create( Car::new ); //相当于new了一个car


2.2 静态方法引用:

它的语法是Class::static_method,实例如下:


cars.forEach( Car::collide );


2.3 特定类的任意对象的方法引用:

它的语法是Class::method实例如下:


cars.forEach( Car::repair );


2.4 特定对象的方法引用:

它的语法是instance::method实例如下:


final Car police = Car.create( Car::new );
cars.forEach( police::follow );


3 函数式接口

函数式接口就是只有一个方法的普通接口。java.lang.Runnable concurrent.Callable是函数式接口最典型的例子。采用@FunctionalInterface注解 ,函数式接口可被隐式转换为lambda 表达式。

如定义了一个函数式接口如下:


@FunctionalInterface
interface GreetingService {
 void sayMessage(String message);
}


那么就可以使用Lambda表达式来表示该接口的一个实现(注:JAVA 8 之前一般是用匿名类实现的):


GreetingService greetService1 = message -> System.out.println("Hello " + message);


4 接口中可以写默认方法实现(接口定义公共方法)

简单说,默认方法就是接口可以有实现方法,而且不需要实现类去实现其方法。我们只需在方法名前面加个 default 关键字即可实现默认方法。或者直接写静态 static方法实现也可。

对于实现类,处理接口中的方法:可覆盖,或者可直接调用super.do();

5 Optional 类

Optional 类解决空指针异常。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。


//Optional.ofNullable - 允许传递为 null 参数 
Optional<Integer> a = Optional.ofNullable(value1); 

// Optional.of - 如果传递的参数是 null,抛出异常 NullPointerException 
Optional<Integer> b = Optional.of(value2);

// Optional.orElse - 如果值存在,返回它,否则返回默认值 
Integer value1 = a.orElse(new Integer(0));


常用栗子:


//user为null,value也为null,搁在以前,user为null,再判断时会报错的
String value =Optional.ofNullable(user).map(User::getUserName);


6 Nashorn JavaScriptnue

略;

7 Stream

Java 8 API添加了一个新的抽象称为流Stream,Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象.

这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。4大管道技术:


java map 拉姆达 key排序 java lambda map函数_java8新特性_02


java map 拉姆达 key排序 java lambda map函数_java8的新特性_03


7.1 创建流

  • stream()
  • parallelStream() − 为集合创建并行流。
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); 
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());


7.2 forEach

Stream 提供了新的方法 'forEach' 来迭代流中的每个数据。以下代码片段使用 forEach 输出了10个随机数:


Random random = new Random();
random.ints().limit(10).forEach(System.out::println);


7.3 map

map 方法用于映射每个元素到对应的结果,以下代码片段使用 map 输出了元素对应的平方数:


List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); 
List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());


7.4 filter

filter 方法用于通过设置的条件过滤出元素。以下代码片段使用 filter 方法过滤出空字符串:


List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); 
// 获取空字符串的数量 
int count = strings.stream().filter(string -> string.isEmpty()).count();


7.5 limit

limit 方法用于获取指定数量的流。


Random random = new Random(); 
random.ints().limit(10).forEach(System.out::println);


7.6 sorted

sorted 方法用于对流进行排序。以下代码片段使用 sorted 方法对输出的 10 个随机数进行排序:


Random random = new Random(); random.ints().limit(10).sorted().forEach(System.out::println);


7.7 并行(parallel)程序

parallelStream 是流并行处理程序的代替方法。以下实例我们使用 parallelStream 来输出空字符串的数量:


List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); 
// 获取空字符串的数量
int count = strings.parallelStream().filter(string -> string.isEmpty()).count();


我们可以很容易的在顺序运行和并行直接切换。

7.8 Collectors

Collectors 类实现了很多归约操作,例如将流转换成集合和聚合元素。Collectors 可用于返回列表或字符串:


List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList()); 
System.out.println("筛选列表: " + filtered); 

String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", ")); 
System.out.println("合并字符串: " + mergedString);


7.9 统计summaryStatistics

另外,一些产生统计结果的收集器也非常有用。它们主要用于int、double、long等基本类型上,它们可以用来产生类似如下的统计结果。


List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); 

IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics(); System.out.println("列表中最大的数 : " + stats.getMax()); 
System.out.println("列表中最小的数 : " + stats.getMin());
System.out.println("所有数之和 : " + stats.getSum()); 
System.out.println("平均数 : " + stats.getAverage());


8 日期时间 API

Java 8通过发布新的Date-Time API (JSR 310)来进一步加强对日期与时间的处理。

旧版的 Java 中,日期时间 API 存在诸多问题,其中有:

  • · 非线程安全
  • · 设计很差 java.util.Date、 java.sql.Date 都包含日期。
  • · 时区处理麻烦

新版Java 8 在 java.time

  • · Local(本地) − 简化了日期时间的处理,没有时区的问题。
  • · Zoned(时区) − 通过制定的时区处理日期时间。
LocalDate,LocalTime,LocalDateTime : 时间
Instant : 时间戳(以Unix元年:1970年1月一日 00:00:00到某个时间时间的毫秒值)
Duration : 计算两个“时间”之间的间隔
Period : 计算两个“日期”之间的间隔
TemporalAdjust :时间校正器
DateTimeFormatter :格式化时间/日期
ZonedDate,ZonedTime,ZonedDateTime : 时区


不考虑时区sample:


java map 拉姆达 key排序 java lambda map函数_java8的新特性_04


考虑时区:


java map 拉姆达 key排序 java lambda map函数_java8的新特性_05


9 Base64

编码解码等。