关于java8能够用到的新特性

2014年java8就已经被提出来了,越来越多的公司项目也都开始使用了Lambdas表达式,所以本着学习的角度,写一篇主体是Lambdas的文章。
先讲一些java8能用到的新特性:

  1. 接口当中写实现方法,只需要添加一个default的关键字
public interface IInterface {
    default void init(){//default要求最低版本要24 所以基本没用
        Log.i("dargon","init");
    }
}
static int create(int i){//还可以在接口中设置静态方法
        return 1;
    }
  1. Lambdas表达式,Lambdas写出来的代码非常简洁,漂亮,他允许开发者将方法的引用当做参数传进去,但是由此会带来阅读性下降,并且需要了解Lambdas才能看懂他的代码。
  2. 函数式接口,其实目的也是为了更好的支持lambdas表达式。函数式接口是只包含一个抽象方法的接口,可以加注解@FunctionalInterface ,编译器会注意到这个标注,如果你的接口中定义了第二个抽象方法的话,编译器会抛出异常。可以不加。
@FunctionalInterface //可以不加
public interface IConverter<F,T> {
    T convert(F f);
}
 IConverter<String,Integer> converter = (from) -> Integer.valueOf(from);
 converter.convert("123");//返回123
//说的清楚一点就是创建了一个实现这个接口的子类,实现convert方法,之后就可以直接调用方法了,就是写的非常简洁一点,编译器会自动适配到相应的方法的。
可以写的更加简洁一点:
IConverter<String,Integer> converter = Integer::valueOf;//Java 8 允许你通过::关键字获取方法或者构造函数的的引用。

如果还是不清楚 ,可以看这个三个代码块,从原型到精简版:

 List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");
        Collections.sort(names, new Comparator<String>() {//原型
            @Override
            public int compare(String a, String b) {
                return b.compareTo(a);
            }
        });
Collections.sort(names, (String a, String b) -> { return b.compareTo(a);});//精简版1
//当只有一行代码的时候 你甚至可以不要return 跟大括号
Collections.sort(names,(String a, String b) -> b.compareTo(a));//精简版2  
Collections.sort(names, (a, b) -> b.compareTo(a));//最终版
  1. ::符号,在java8中被定义了新的特性,可以直接引用已有java类或对象的方法或构造器。
第一种方法引用是构造器引用,它的语法是Class::new,或者更一般的Class< T >::new。请注意构造器没有参数。
final Car car = Car.create( Car::new );
final List< Car > cars = Arrays.asList( car );
第二种方法引用是静态方法引用,它的语法是Class::static_method。请注意这个方法接受一个Car类型的参数。
cars.forEach( Car::collide );
第三种方法引用是特定类的任意对象的方法引用,它的语法是Class::method。请注意,这个方法没有参数。
cars.forEach( Car::repair );
最后,第四种方法引用是特定对象的方法引用,它的语法是instance::method。请注意,这个方法接受一个Car类型的参数
final Car police = Car.create( Car::new );
cars.forEach( police::follow );
  1. 重复注解:之前注解在一个地方只能声明一次,java8可以使相同的注解在同一个地方声明多次,通过数组的形式。
  2. 扩展注解的支持,java8可以为任何东西添加注解,局部变量、泛型类、父类与接口的实现,就连方法的异常也能添加注解。
  3. 对于编译器的优化:java8通过反射可以获取到参数的名字
  4. 类库的增加:Optional类,通过它来做空指针的判断
Optional实际上是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。更多详情请参考[官方文档](http://docs.oracle.com/javase/8/docs/api/)。
我们下面用两个小例子来演示如何使用Optional类:一个允许为空值,一个不允许为空值。
Optional< String > fullName = Optional.ofNullable(null);
System.out.println("Full Name is set? "+ fullName.isPresent() );       
System.out.println("Full Name: "+ fullName.orElseGet( () ->"[none]") );
System.out.println( fullName.map( s ->"Hey "+ s +"!").orElse("Hey Stranger!") );
如果Optional类的实例为非空值的话,isPresent()返回true,否从返回false。为了防止Optional为空值,orElseGet()方法通过回调函数来产生一个默认值。map()函数对当前Optional的值进行转化,然后返回一个新的Optional实例。orElse()方法和orElseGet()方法类似,但是orElse接受一个默认值而不是一个回调函数。下面是这个程序的输出:
Full Name isset?false
Full Name: [none]
Hey Stranger!
让我们来看看另一个例子:
Optional< String > firstName = Optional.of("Tom");
System.out.println("First Name is set? "+ firstName.isPresent() );       
System.out.println("First Name: "+ firstName.orElseGet( () ->"[none]") );
System.out.println( firstName.map( s ->"Hey "+ s +"!").orElse("Hey Stranger!") );
System.out.println();
下面是程序的输出:
First Name isset?true
First Name: Tom
Hey Tom!

还有一个stream类,他可以很大程度上简化对集合的处理步骤跟效率,写法上跟rxjava其实很类似。

让我们以一个简单的Task类为例进行介绍:

public class Streams  {
private enum Status {        OPEN, CLOSED    };
private static final class Task { 
private final Status status;
private final Integer points;
Task( final Status status,final Integer points ) {            
this.status = status;         
this.points = points;}
public Integer getPoints() {     return points;}        
public Status getStatus() {            
return status;      
}
      
@Override  
public String toString() {    
    return String.format("[%s, %d]", status, points );
        }
    }
}

Task类有一个分数的概念(或者说是伪复杂度),其次是还有一个值可以为OPEN或CLOSED的状态.让我们引入一个Task的小集合作为演示例子:
final Collection< Task > tasks = Arrays.asList(new Task( Status.OPEN,5),new Task( Status.OPEN,13),new Task( Status.CLOSED,8));
我们下面要讨论的第一个问题是所有状态为OPEN的任务一共有多少分数?在Java 8以前,一般的解决方式用foreach循环,但是在Java 8里面我们可以使用stream:一串支持连续、并行聚集操作的元素。
// Calculate total points of all active tasks using sum()
final long totalPointsOfOpenTasks = tasks.stream() 
.filter( task -> task.getStatus() == Status.OPEN )
.mapToInt( Task::getPoints )
.sum();
System.out.println("Total points: "+ totalPointsOfOpenTasks );
程序在控制台上的输出如下:
Total points: 18
这里有几个注意事项。第一,task集合被转换化为其相应的stream表示。然后,filter操作过滤掉状态为CLOSED的task。下一步,mapToInt操作通过Task::getPoints这种方式调用每个task实例的getPoints方法把Task的stream转化为Integer的stream。最后,用sum函数把所有的分数加起来,得到最终的结果。
在继续讲解下面的例子之前,关于stream有一些需要注意的地方(详情[在这里](http://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#StreamOps)).stream操作被分成了中间操作与最终操作这两种。
中间操作返回一个新的stream对象。中间操作总是采用惰性求值方式,运行一个像filter这样的中间操作实际上没有进行任何过滤,相反它在遍历元素时会产生了一个新的stream对象,这个新的stream对象包含原始stream中符合给定谓词的所有元素。
像forEach、sum这样的最终操作可能直接遍历stream,产生一个结果或副作用。当最终操作执行结束之后,stream管道被认为已经被消耗了,没有可能再被使用了。在大多数情况下,最终操作都是采用及早求值方式,及早完成底层数据源的遍历。
stream另一个有价值的地方是能够原生支持并行处理。让我们来看看这个算task分数和的例子。
// Calculate total points of all tasks
final double totalPoints = tasks  .stream()  .parallel()   .map( task -> task.getPoints() ) // or map( Task::getPoints )
.reduce(0, Integer::sum );
System.out.println("Total points (all tasks): "+ totalPoints );
这个例子和第一个例子很相似,但这个例子的不同之处在于这个程序是并行运行的,其次使用reduce方法来算最终的结果。下面是这个例子在控制台的输出:
Total points (all tasks): 26.0
经常会有这个一个需求:我们需要按照某种准则来对集合中的元素进行分组。Stream也可以处理这样的需求,下面是一个例子:
// Group tasks by their status
final Map< Status, List< Task > > map = tasks.stream() .collect( Collectors.groupingBy( Task::getStatus ) );
System.out.println( map );
这个例子的控制台输出如下:
{CLOSED=[[CLOSED, 8]], OPEN=[[OPEN, 5], [OPEN, 13]]}
让我们来计算整个集合中每个task分数(或权重)的平均值来结束task的例子。
// Calculate the weight of each tasks (as percent of total points)
final Collection< String > result = tasks.stream() // Stream< String >
.mapToInt( Task::getPoints ) // IntStream
.asLongStream()  // LongStream
.mapToDouble( points -> points / totalPoints )  // DoubleStream
.boxed() // Stream< Double >
.mapToLong( weigth -> (long)( weigth *100) )// LongStream
.mapToObj( percentage -> percentage +"%")  // Stream< String>
.collect( Collectors.toList() ); // List< String > 
System.out.println( result );
下面是这个例子的控制台输出:
[19%, 50%, 30%]
最后,就像前面提到的,Stream API不仅仅处理Java集合框架。像从文本文件中逐行读取数据这样典型的I/O操作也很适合用Stream API来处理。下面用一个例子来应证这一点。
final Path path =new File( filename ).toPath();
try( Stream< String > lines = Files.lines( path, StandardCharsets.UTF_8 ) ) {lines.onClose( () -> System.out.println("Done!") ).forEach( System.out::println );}
对一个stream对象调用onClose方法会返回一个在原有功能基础上新增了关闭功能的stream对象,当对stream对象调用close()方法时,与关闭相关的处理器就会执行。

还有时间类Clock,并不做过多介绍了,毕竟代码还是熟悉的写起来才快,不是说原生的就是最好的。

如果出现异常或者警告,或者显示不支持lambdas表达式,可以参照这篇博客
http://blog.csdn.net/nicolelili1/article/details/52275263

参考资料:
http://www.importnew.com/11908.html
http://blog.csdn.net/chenleixing/article/details/47802675

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342