一点杂感 以及 java8 Streams API 与 C# Linq 简要对比分析

一点杂感 以及 java8 Streams API 与 C# Linq 简要对比分析

写在前面的一点小吐槽、一点杂感

学 Haskell 学了一段时间之后,虽说拿他来写东西还是完全不行,但是看别的语言特性时,总是会带着一种“诶,这玩意在哪哪见过”的蜜汁既视感。且不说几乎成为现代编程语言标配的 Lambda 、闭包,就是 Monad 都有不少引入了。

这段时间,出于学校项目需要,又在学习 java 。不知为什么,感觉看起 java 来真的是格外的蛋疼,觉得这玩意语法和某些特性的设计简直是糟糕,整洁度和美感还不如复杂和妥协的 C++,更别说以语法优雅著称的 C#。

虽说自己水平渣,但是这样一门满是历史局限性与不优雅的语言,网上不少 java 程序员倒是对这个饱受诟病的语法、api本身一股迷之优越感,完全不知道到底是不知道还是仅仅不想承认 —— java高占有的关键 —— 设计思想符合当时的时代进程、社区化的成功、当下的路径依赖。

到了什么程度呢?大名鼎鼎的《java core》作者,在书中都对其他的语言有一些优势(有些甚至 —— 个人认为—— 并非优势只是设计的不同)就大加赞扬,而对被对比方字里行间饱含嘲讽。而对 java 设计缺陷就不甚明显的提一下。

几个例子

  • 一次编写,到处调试(误)
  • 混乱的标准库设计
  • 难用的时间、日期库
  • 孱弱的以擦除实现的泛型系统
  • 偏执的完全不加入隐式类型声明
  • 只能传值、不允许运算符重载(这两个见仁见智)
  • Linq(后文将会讨论)
  • 不支持拓展方法
  • 没有部分类,导致的写 GUI 自动代码生成蛋疼至极
  • throws
  • final – sealed
  • final – const (说实话你 final 不就是一表层 const 么)
  • delegate (java core 作者说 java 的 method invoke 比 C#的 delegate 更好,完全不能理解)
  • 没有原生 tuple,pair
  • 其他语法糖的缺乏(如await\asyc)

当然其它语言也有各自的不足,这里只是提这些来印证前文

语言明明只是工具,是为表述思想服务的。如果说像《java core》作者这样一门语言的布道者尚可说是怀揣着对自己工作的热爱,是可以理解的。某些明明是格局有限或者单纯跟风的人,只能说是可悲了。

就杂感而起的 java8 Streams API 与 C# Linq 简要对比分析

起因

前段时间给某位老师写一个系统,api 路由是 node 实现的,一不做二不休干脆全上 node 了。因为要求数据安全,不敢用 mongodb,遂上 mysql,又因为需求不是很复杂,没想那么多就直接裸写 sql 了,写得简直了,既丑又容易给注入…… 写完之后才想起来为啥不用 ORM,看了看,那几个火的 ORM 库要不太大,要不文档太简陋或者相当于设计了一套自己的sql方言。这时候才怀念起c#的linq,太好用了。

项目暂时告一段落后的现在,因为在学习 java 的、听说c#、java的相似性高的缘故,想要在java中能找到类似的。就在希望快要转为失望之时,看到了这篇文章。

上面这篇文章中,对 java8 Streams API 的溢美之词,刚看到标题,仿佛心中顿时像遇到氧气的带火星木条似得——一下子复燃了。

然而真的是这样吗?或者说真的可以这样简单的等价么

正如文中提到,是的,Linq是起源于对强烈的对改善 sql 在某些方面缺陷的渴望。但是,这并不等于说 Linq 是一种简单 ORM 或者说是用 Lambda 来进行sql查询的包装或者说仅仅是语法糖。

linq-to-object的实现

让我们从相对“表层”的因素因素谈起:该文作者在文中谈到了 Linq-to-object 的速度,实际上,Linq-to-object在内核的层面就是使用btree的方式实现的,这就相当程度上决定了其效率,从复杂性上说,仅就这一项就可以说明绝不仅是某些开源 java linq 查询库那样的简单包装。

让我们再谈一谈深层次:

linq的组成

Linq ,或者说一个完整的 Linq ,是由以下几个部分组成的:

  • Lambda 表达式
  • Query 表达式
  • 拓展方法
  • 表达式树
  • 匿名类型

我们按条目分析:

  1. 正如文中提到,java的新版本也加入了lambda特性。
  2. java没有query表达式,这意味着不能写成monad形式,而monad作为函数式的重中之重。可以说让java引入函数式的举动徒有其表。关于monad,请点击该链接阅读
  3. 前面说到,java新版本实现了lambda,然而设计者们不知何故的没有支持标准的iterator和iterable,而是选择引入了一套streams api,试图实现c# 使用拓展方法实现的功能;结果是又增加了一套steams模型,iostream表示泪流满地。这样一来,其效用也仅仅可以用在设计的这些方面,难以拓展。
  4. 没有表达式树,限制了无法表达语句结构,也限制了动态编译函数。
  5. java没有匿名类型,限制了它借助临时结构减少计算,更使得难以借此增强表达能力。

总结

streams api 是处于语法落后的 java 在函数式上的一次勇敢尝试和追赶,然而从结果上看,是比较失败的。或许是某种情结在作怪,怕得到“抄袭”的罪名。然而,这种结果上的残次 linq 和缺失相当多部分的函数式,更会阻止自身进步的步伐,不能给使用者带来的便利,可以说是一种对尝试初心的背反。

Tagged with:

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据