设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客
LUPA开源社区 首页 业界资讯 开源资讯 查看内容

Java 8与Apache Ignite

2015-5-21 23:01| 发布者: joejoe0332| 查看: 1020| 评论: 0|原作者: 杨旭钧|来自: csdn

摘要: 从JDK发布的历程来看,JDK1.6添加了对脚本语言:Ruby、Groovy、JavaScript的支持,JDK7添加了对集合(Collections)的增强支持,而Java8在JDK7之上进一步大胆地创新,引入了Lambda框架、Streams、函数式接口模块等。 ...
从JDK发布的历程来看,JDK1.6添加了对脚本语言:Ruby、Groovy、JavaScript的支持,JDK7添加了对集合(Collections)的增强支持,而Java8在JDK7之上进一步大胆地创新,引入了Lambda框架、Streams、函数式接口模块等。

时间过得真快,转眼间十年过去了,而Java都已经二十岁了,《礼记》有云“二十弱冠、三十而立”,我们首先要感谢JamesGosling和他的团队把Java带到这个世界上来,而年方弱冠,这位翩翩少年郎在IT技术的各个领域都取得了举世瞩目的成绩,在二十年这么长的时间里,已经有无数的企业应用、互联网应用和移动应用都是基于Java构建的,甚至包括物联网上的很多应用也依然使用Java编写,而目前各具特色的编程语言也是层出不穷、百花齐放,也确实给Java造成了不小的压力。面对眼前瞬息万变的IT技术世界,我还是坚信Java到了“而立之年”,仍然可以老骥伏枥为我们带来更多的惊喜!


杨旭钧

Java8新功能特性

从JDK发布的历程来看,JDK1.6添加了对脚本语言:Ruby、Groovy、JavaScript的支持,JDK7添加了对集合(Collections)的增强支持,而Java8在JDK7之上进一步大胆地创新,引入了Lambda框架、Streams、函数式接口模块等,这里我们重点讲一下Lambda框架。Java8的最大亮点就是引入了Lambda表达式,通过Lambda表达式提供闭包的方式,使集合(Collection)库更加容易遍历、过滤、从一个集合中抽取数据,特别是集合(Collection)操作充分利用多核编程的特性,能够大幅提升并发操作的性能。

什么是Lambda表达式?

Lambda表达式是一个匿名函数,即没有函数名的函数,通常我们用Lambda表达式表示闭包操作。当开发者在编写一个Lambda表达式时,被编译成函数式接口。

Runnable接口实现

代码1是使用Lambda表达式来写一个Runnable接口。

  1. public class RunnableTest {  
  2.     public static void main(String[] args) {  
  3.     System.out.println("=== RunnableTest ===");  
  4.     // Anonymous Runnable  
  5.     Runnable r1 = new Runnable(){  
  6.     @Override  
  7.     public void run(){  
  8.     System.out.println("Hello world one!");  
  9.     }  
  10.       };  
  11.     // Lambda Runnable  
  12.     Runnable r2 = () -> System.out.println("Hello world two!");  
  13.     // Run em!  
  14.     r1.run();  
  15.     r2.run();  
  16. }  
  17. }  

代码1

Comparator接口实现

代码2是使用Lambda表达式来写一个Comparator接口。Comparator类被用于筛选集合。在下面的例子中,Person对象通过surName筛选出来一个ArrayList列表。如下是包含Person类的域值。

  1. public class Person {   
  2.   private String givenName;   
  3.   private String surName;   
  4.   private int age;   
  5.   private Gender gender;   
  6.   private String eMail;   
  7.   private String phone;   
  8.   private String address;  
  9. }  

代码2

代码3通过使用匿名内部类和两个Lambda表达式来应用Comparator接口。

  1. public class ComparatorTest {   
  2.     
  3.   public static void main(String[] args) {   
  4.        
  5.     List<Person> personList = Person.createShortList();   
  6.       
  7.     // Sort with Inner Class   
  8.     Collections.sort(personList, new Comparator<Person>(){   
  9.       public int compare(Person p1, Person p2){   
  10.         return p1.getSurName().compareTo(p2.getSurName());   
  11.       }   
  12.     });   
  13.         
  14.     System.out.println("=== Sorted Asc SurName ===");   
  15.     for(Person p:personList){   
  16.       p.printName();   
  17.     }   
  18.         
  19.     // Use Lambda instead   
  20.         
  21.     // Print Asc   
  22.     System.out.println("=== Sorted Asc SurName ===");   
  23.     Collections.sort(personList, (Person p1, Person p2) -> p1.getSurName().compareTo(p2.getSurName()));   
  24.     
  25.     for(Person p:personList){   
  26.       p.printName();   
  27.     }   
  28.         
  29.     // Print Desc   
  30.     System.out.println("=== Sorted Desc SurName ===");   
  31.     Collections.sort(personList, (p1,  p2) -> p2.getSurName().compareTo(p1.getSurName()));   
  32.     
  33.     for(Person p:personList){   
  34.       p.printName();   
  35.     }   
  36.         
  37.   }   
  38. }  

代码3

我们在后面两个Collections集合中引用了Lambda表达式,Lambda表达式声明了参数类型传递给了表达式。然而,我们从第二个Lambda表达式可以看到,这个参数传递是可选的,Lambda支持“targettyping”,可以智能地从上下文中引用对象类型。因为我们正在分配一个结果给Comparator,而编译器能够将这两个参数作为Person类型来引用。

Listner接口实现

代码4是使用Lambda表达式来写一个Listener接口。

  1. public class ListenerTest {   
  2.   public static void main(String[] args) {   
  3.            
  4.     JButton testButton = new JButton("Test Button");   
  5.     testButton.addActionListener(new ActionListener(){   
  6.     @Override public void actionPerformed(ActionEvent ae){   
  7.         System.out.println("Click Detected by Anon Class");   
  8.      }   
  9. });   
  10.         
  11.     testButton.addActionListener(e -> System.out.println("Click Detected by Lambda Listner"));         
  12.     // Swing stuff   
  13.     JFrame frame = new JFrame("Listener Test");   
  14.     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);   
  15.     frame.add(testButton, BorderLayout.CENTER);   
  16.     frame.pack();   
  17.     frame.setVisible(true);   
  18.         
  19.   }   
  20. }  

代码4

根据示例,Lambda表达式作为一个参数被传递,“targettyping”可用于如下的上下文中:

  • 变量声明
  • 分配
  • 返回语句
  • 数组初始化
  • 方法或构造器参数
  • Lambda表达式方法体
  • 条件表达式
  • Cast表达式

在ApacheIgnite中使用Lambda函数上面我们简单介绍了一下Lambda的基本用法,而在Apache开源项目ApacheIgnite上也支持Lambda方法的使用。在ApacheIgnite的分布式网格中,创建GridInstance实例,grid通过Broadcast(广播)的方式来执行GridRunnable方法中的操作,如代码5所示。

  1. try (Grid grid = GridGain.start()) {  
  2.   grid.compute().broadcast((GridRunnable)() ->   
  3.       System.out.println("Hello World")).get();  
  4. }  

代码5

在ApacheIgnite中使用时空索引ApacheIgnite能够轻松地使用带有内存索引的SQL语句查询内存中的数据,并且能够扩展SQL到时空查询。例如,代码6的查询将找到地图中的特定平方区域内所有的点:

  1. Polygon square = factory.createPolygon(new Coordinate[] {  
  2.     new Coordinate(00),  
  3.     new Coordinate(0100),  
  4.     new Coordinate(100100),  
  5.     new Coordinate(1000),  
  6.     new Coordinate(00)  
  7. });  
  8.    
  9. cache.queries().  
  10.     createSqlQuery(MapPoint.class"select * from MapPoint where location && ?").  
  11.         queryArguments(square).  
  12.         execute().get();  
  13. }  

代码6

什么是JavaStreaming?

Java8Stream是元素的集合,这点让Stream看起来用些类似Iterator,可以支持顺序和并行的对原Stream进行汇聚的操作。

大家可以把Stream当成一个高级版本的Iterator。用户只要给出需要对其包含的元素执行什么操作,比如“过滤掉长度大于10的字符串”、“获取每个字符串的首字母”等,具体这些操作如何应用到每个元素上。Java8的并行流处理特性也是一大创新亮点,能够让你更简单地使用JavaAPI进行更复杂的数据处理查询,进而优化传统的数据处理查询的性能。

Stream接口和Collect接口

Java8并行流处理类位于java.util.stream包中。主要的流处理接口有两个:Stream接口和Collect接口。Stream接口定义了典型的流处理应该具备的基本操作,如filter方法、map方法和reduce方法,这三个方法是函数式编程的标志。另外,Stream接口还定义了创建Stream的static方法,Stream或者是有限的、或者是无限的,其中无限的Stream通过Iterate()来实现。

  • IntStream、LongStream和DoubleStream接口。上述接口是基于原生类型int、long和double的Stream,提供了很多关于流的操作方法。例如,sum()、min()/max()、average()方法等,这些方法都是汇聚过程中的基本操作。
  • Collect接口。Collect接口是Reduce类的抽象接口,提供了很多常用的Reduce()操作方法。其中Reduce()操作有并行和串行两种实现方式,BaseStream接口中的parallel()、sequential()、unordered()方法,大多数应用程序都使用parallel()方法进行并行流处理操作。
  • Collectors类。Collectors接口提供了很多可以直接使用的Reduce操作方法。比较典型的方法,例如GroupingBy、PartitioningBy操作。它们都可以通过parallel()、sequential()来执行,例如groupingByConcurrent会使用Parallel()进行grouping操作。
  • StreamSupport类。StreamSupport类提供了一些底层用于操作Stream的方法,如果不需要创建自己的Stream,一般不需要使用它。JavaStream处理示例代码7是使用JavaStream并行处理和Lambda闭包函数的特性来计算证券投资中资产组合的信用风险,CodeA使用传统的循环迭代方法进行计算,而CodeB使用IntStream调用parallel()方法来执行Integer数据类型的并行流处理操作。

Code A

  1. double[] losses = new double[num];  
  2.     for (int i = 0; i < num; i++)  
  3.     {  
  4.         for (Credit crd : portfolio)   
  5.         {  
  6.             int remDays = Math.min(crd.getRemainingTerm(), horizon);  
  7.   
  8.             if (rndGen.nextDouble() >= 1 - crd.getDefaultProbability(remDays))  
  9.                 losses[i] += (1 + crd.getAnnualRate() * Math.min(horizon, crd.getRemainingTerm()) / 365)  
  10.                     * crd.getRemainingAmount();  
  11.             else  
  12.                 losses[i] -= crd.getAnnualRate() * Math.min(horizon, crd.getRemainingTerm()) / 365 *  
  13.                     crd.getRemainingAmount();  
  14.         }  
  15.     }<b>  
  16. </b>  

Code B

  1. IntStream.range(0, num).parallel().forEach(i ->   
  2.     {  
  3.         for (Credit crd : portfolio)   
  4.         {  
  5.             int remDays = Math.min(crd.getRemainingTerm(), horizon);  
  6.   
  7.             if (rndGen.nextDouble() >= 1 - crd.getDefaultProbability(remDays))  
  8.                 losses[i] += (1 + crd.getAnnualRate() * Math.min(horizon, crd.getRemainingTerm()) / 365)  
  9.                     * crd.getRemainingAmount();  
  10.             else  
  11.                 losses[i] -= crd.getAnnualRate() * Math.min(horizon, crd.getRemainingTerm()) / 365 *  
  12.                     crd.getRemainingAmount();  
  13.         }  
  14.     }  
  15.     );  

代码7

CodeB中,我们通过parallel()并行执行任务操作,利用多核操作的优势,将获得更多的并发优势。从编程角度上看减少了大量冗余代码,同时也提升了代码执行的效率。ApacheIgnite特性介绍ApacheIgnite目前是Apache组织孵化器下的一个开源项目,由GridGain公司领导,是一个高性能、集成度高的分布式内存平台,能够实时地对大量数据集进行计算和事务处理,同时在最新版本中引入了对Java8Lambda和Streaming的支持。它将数据缓存在内存当中,因此比传统关系型数据库的处理速度更快。

主要功能特性如下:

  • 分布式内存缓存(兼容JSR-107)
  • 数据操作速度超快
  • 弹性扩展
  • 分布式事务
  • 分布式SQL查询(兼容SQL-99)
  • JDBC驱动
  • 分布式内存队列和其他数据结构
  • 分层Off-Heap存储
  • WebSeesion集群
  • HibernateL2缓存集成
  • 兼容Memcached
  • 基于HTTP的RESTAPI访问
  • Java8Lambda函数
  • Java8Streaming

Java8发展展望

Java从诞生到现在为止经历了20年的漫长发展历程,Java固有的编程模式看似不可能会有太大的变化,然而Java8的横空出世使这一情况有了极大改观,JavaLambda和Stream两大特性为垂垂老矣的Java平台注入了强大的活力,更加符合Java开发者们的热切期望,让他能够更自信地迎接云计算和移动应用时代的到来。目前在开源世界中支持Java8新特性的应用框架和软件平台逐渐增多(例如ApacheIgnite工程),相信未来会有越来越多的Java应用迁移到Java8平台上,充分享受Java8新特性带来的舒适体验感。

作者简介:杨旭钧多年的银行、保险行业的金融系统的规划、设计和开发经验,参与过多个国内外银行、互联网电商与移动支付领域项目。曾就职于VMware和Accenture两家公司,服务客户包括花旗银行、中国外汇交易中心、中国央行、中国银行等。目前正在创办一家提供大数据分析处理服务的公司。


酷毙

雷人

鲜花

鸡蛋

漂亮
  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部