千家信息网

怎么理解Java中Linq4j

发表于:2024-11-28 作者:千家信息网编辑
千家信息网最后更新 2024年11月28日,这篇文章给大家介绍怎么理解Java中Linq4j,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。开发JAVA一段时间,面临的一大问题就是集合操作,习惯了LINQ的简洁语法,对JAV
千家信息网最后更新 2024年11月28日怎么理解Java中Linq4j

这篇文章给大家介绍怎么理解Java中Linq4j,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

开发JAVA一段时间,面临的一大问题就是集合操作,习惯了LINQ的简洁语法,对JAVA的集合操作实在是无甚好感,只能通过C系的循环实现筛选等操作,由于没有延迟执行特性,内存占用实在不敢恭维。因此便在网上找到了linq4j, 一个针对JAVA的linq移植版本。

一. 安装

该项目的Github地址是:https://github.com/julianhyde/linq4j. 显然是一个个人项目,向作者致敬。

它并没有部署在标准的maven库里,因此需要手动编译生成。使用标准命令行:

git clone git://github.com/julianhyde/linq4j.git linq4j    #git克隆到linq4j目录下        mvn compile  #编译        mvn test #测试        mvn jar:jar  #生成jar包

使用了maven以后,工作效率大大提升,.当然NET下也有类似的工具nuget.

二. Linq4j的扩展功能

由于JAVA目前还没有匿名函数和扩展函数,而且内置的标准迭代器接口Iterator功能偏弱。 因此Linq4j增加了一个一系列泛型接口和函数:

1. 新迭代器接口: Enumerable,它扩展了Iterator的功能

2. 一组类似"委托"性质的函数:

(1)返回R的泛型委托:public interface Function {}

(2)接收T, 返回R的泛型委托:public interface Function1 {}

(3)接收T1,T2, 返回R的泛型委托,定义如下:

/**    * Function with two parameters.    *    * @param  result type    * @param  type of parameter 1    * @param  type of parameter 2    */   public interface Function2 extends Function {     R apply(T1 v1, T2 v2);   }

当然,内置的函数不止这些,还有一系列非泛型的委托,包括返回bool型的Predicate函数。由于篇幅限制,此处不一一介绍。

3. 一系列Expressions,具体使用下面有介绍。

三. 使用方法

该库实现了大部分LINQ的功能,其中包括了筛选器,排序器,分组器,类型转换等功能。下面我们以一个实例来介绍它。

先定义一个实体:

public class Person      {      public int Age;      public String     Name;      public boolean Sex;      }

我们的基本任务,是将一个Person集合中,所有性别为男(true)的名字取出来,并按照string的默认降序排列。***得到的应该是List类型。

//Linq4j:  public void Test(ArrayList persList)       {      java.util.List nameStrings=  Linq4j.asEnumerable(persList).where(new Predicate1()      {                    public boolean apply(Person arg0)          {                     return arg0.Sex;          }      }).select(new Function1()      {           public String apply(Person arg0)          {           return arg0.Name;          }      }).orderByDescending(new Function1()      {           public String apply(String arg0)          {          // TODO Auto-generated method stub          return arg0;          }      }).toList();       }

这段代码的风格和C#的很像,由于接口Enumerable可以拼接,因此通过简单的Where,Select和 orderByDescending即可实现。但由于LINQ没有匿名函数,不得不在函数中加入函数,看起来实在是让人头疼。另外,由于没有扩展函数,需要在方法前使用Linq4j的静态方法。

该功能利用标准Linq实现如下:

var userNames = from d in persons where d.Sex orderby d.Name descending select d.Name;

在.NET中,我们可以使用闭包,例如在筛选函数的实现中,访问到外部的数据。但我们可以看如下的例子:

该函数的基本逻辑是找到personList中名字在黑名单里的人。套了两个Linq4j, 但是,注意blacklist数组的final关键字, 如果没有该关键字会报错,JAVA没有闭包,因此blacklist数组就不应该修改,这个语法糖到底是不是利大于弊,还需要读者讨论。

public List SelectBlackList(ArrayList persList)      {      final String[] blackList = { "zhang", "wang", "li" };      return Linq4j.asEnumerable(persList)          .where(new Predicate1()          {               public boolean apply(Person arg0)              {              return Linq4j.asEnumerable(blackList).contains(                  arg0.Name);              }           }).toList();       }

该功能使用标准Linq实现如下:

public  List GetBlacklist(IEnumerable persons)           {               String[] blackList = { "zhang", "wang", "li" };               var result= from d in persons where blackList.Contains(d.Name) select d;               return result.ToList();           }

***讨论一下集合类型转换,例如类Worker继承实现了Person接口.

public class Worker : Person      {          public string Commpay ;      }

那么,一个函数的定义是 void Func(List nodes). 而我要传入的参数类型是List,编译器肯定是要报错的!怎么办?

对于.NET来说,有逆变和协变特性,或者我可以这么做:

public  void Test3(Listworkers )          {              this.Func1(workers); //编译器会报错              this.Func1(workers.OfType());          }          public void Func1(IEnumerablepersons )          {              //只是演示,没有实现功能        }

对于JAVA来说,一般的做法,是在外面加一个转换,通过新建Person集合和foreach迭代器,利用强制类型转换将其转变为List. 这实在是太麻烦了。 利用LiNQ4J, 我们也有类似的语法:

public void Func2(List person)      {      //演示,不实现功能      }      public void Test3(List workers)//1.通过最简单粗暴的循环写法,实现功能,不敢恭维。      {      // Func2(workers); // 此处编译器会报错      List persons = new ArrayList();      for (Person person : workers)      {          persons.add(person);        }                      Func2(persons);      }      public void Test4linq(List workers)  //2.linq4j写法      {      List persons = Linq4j.asEnumerable(workers)          .ofType(Person.class).toList();       Func2(persons);      }

linq4j除了提供了这种显式声明函数的写法,还实现了以下的表达式写法,看起来真是高端洋气上档次:

// use lambda, this time call whereN      ParameterExpression parameterE =          Expressions.parameter(Employee.class);      ParameterExpression parameterN =          Expressions.parameter(Integer.TYPE);      final Queryable nh4 =          Linq4j.asEnumerable(emps)              .asQueryable()              .whereN(                  Expressions.lambda(                      Predicate2.class,                      Expressions.andAlso(                          Expressions.equal(                              Expressions.field(                                  parameterE,                                  Employee.class,                                  "deptno"),                              Expressions.constant(10)),                          Expressions.lessThan(                              parameterN,                              Expressions.constant(3))),                      parameterE,                      parameterN));

看起来很唬人,但想起来其实不难。该功能利用Expressions类的静态方法,提供了一系列现成的函数供调用,一定程度上进一步提升了可用性。具体细节可以参照linq4j的源码,此处不打算深入讨论。

四. 总结

Linq4j实现了标准Linq的绝大多数功能,同时利用Expression类简化了很多简单函数的实现。使用起来还是很方便的,但我没有时间做具体的性能测试,因此在性能上没有发言权。但不论如何,膜拜一下作者的技术水平。如果大家有空,可以看看linq4j的源码,一定会有很多收获。

集合操作是应用开发中最普遍的开发情形,可惜JAVA本身在该处并无太大建树,linq4j能不能用在大型项目上很难说,如果能在语言本身享受这种便利,那是***不过的了,.NET系同学应该感到幸福。我们只能期待JAVA8带来的lamda表达式新特性,能更好的解决这个问题,当然这只能在2014年了。

为了方便那些不用maven的同学,附件加上linq4j的jar包下载。 注意下载后改后缀名为jar.

关于怎么理解Java中Linq4j就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

函数 功能 标准 接口 类型 委托 编译 写法 方法 特性 编译器 语法 会报 开发 迭代 作者 关键 关键字 内容 同学 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 校园网络安全防范论文 则杨某年内不得从事网络安全 日照戴尔服务器代理测评 怎么知道网页的数据库账号密码 构建网络安全风险事前防护能力 信息网络安全的第三个c 宜昌贝库互联网科技有限公司座机 hp服务器ilo管理硬盘 盘龙区品牌软件开发价格实惠 珍爱生命网络安全的文章 七件事软件开发怎么样 网络安全工程师网络存储工程师 埃森哲 网络安全 中国临床试验注册中心数据库 巨人通力电梯的服务器怎么用 护航冬奥网络安全在行动工作总结 女孩子学网络安全与执法专业好 jpa 数据库字段排序 电脑服务器时间不准无法上网 基于服务器局域网搭建 第三方网络技术服务要求 石家庄丰和网络技术有限公司 数据库技能与技术 软件开发学什么好学 网络安全挖洞语言 动车组网络技术第二版 腾讯云服务器装win2008 心理健康教学设计网络安全 电脑桌面管理软件开发 网络安全对cpu要求
0