一点杂感 以及 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中能找到类似的。就在希望快要转为失望之时,看到了这篇文章。


LINQ一直是.net程序系统中的一个非常棒的东东. Visual Studio 2008 已经引入了lambda 表达式和monads, 而同一时间Java6版本还在讨论要不要去掉泛型数据类型. 这一成果要归功于荷兰计算机科学家Erik Meijer, 他已经全停止掉别的项目.

- Java的现状?

即将要发布的Java8和JSR-355,我们还需要LINQ?在过去的十几年中人们一直在尝试用LINQ给Java带来性能的改良。当时,Quaere和Lambdaj似乎在研究一种很有前途的库(非语言级别). 事实上,StackOverflow上有很多Java的使用者提出的有没有与LINQ等价的Java做法(到现在依然) :

LINQ的Java实现?

LINQ的Java工具

Java中有跟LINQ类似的东西么?

Java等效LINQ和实体框架是什么?

有趣的是, "LINQ"已经发展到EL 3.0版本了!<br>

- 我们真的需要LINQ么?

LINQ的高级特性存在重大缺陷, 从我们角度看来, 将会导致 "next big impedance mismatch". LINQ来源于SQL,这不是一件完美的事情. LINQ流行的LINQ-to-Objects,在.NET下是一种很好的查询方式.Haskell或Scala的成功已表明,真正的函数式编程可以忽略SELECT,WHERE,GROUP BY, 或者HAVING等来进行集合查询。他们使用"fold", "map", "flatMap", "reduce",来获得更高的性能.另一方面LINQ用 "skip", "take"使用混合式GROUP BY(不是OFFSET和FETCH).

事实上, 没有一种函数式查询方法可以超越那老旧但好用的SQL外部链接, 分组设置,或 框架窗口功能. 这些结构仅仅是一个SQL开发人员希望看到的结果的声明。他们不是自足的功能,这实际上包含在任何给定的情况下被执行的逻辑。此外,窗口功能,可以只用在SELECT和ORDER BY子句,这是一种明显声明方式,但是如果你没有SQL上下文这也是非常奇怪的。具体来说,SELECT子句中的窗口函数采用正确的数据预取影响整个执行计划和索引的方式。

相反,函数式编程可以在内存中就做到SQL的这些功能。使用SQLesque API 进行集合查询是用函数式方式狡猾的欺骗 了"传统"的人。这样的实现方式是不能将集合数据与SQL表查询的数据合并在一起的,也不会产生预期的SQL查询结果。

- 我该如何做?

相当简单,你如果使用SQL,你就有两个基本选择:

自上而下,专注你的Java模型. 使用Hibernate / JPA查询并且使用Java8 Streams API 转化Hibernate的查询结果.

自下而上,专注你的SQL关系模型. 继续使用JDBC或者jOOQ, 使用Java8 Streams API 转化的查询结果.

- 不能回头.拥抱未来!

虽然 .NET "领先" Java了一些,但这并不是LINQ的问题. 这主要是由于引入了lambda表达式并且支持lambdas的很多APIs. LINQ仅仅只是如何构建这样API的例子.

但我更加兴奋的期望Java 8中的 new Streams API, 以及它给Java生态系统带来的函数式编程. 这是一个由Informatech illustrates写的很棒的一篇博文:如何将常见的LINQ表达式转换为Java 8 Streams API表达式.

所以,不能回头.你可以不用再对.NET开发者眼馋嫉妒. 因为Java 8,我们已经不需要LINQ或者其他API模仿LINQ的"unified querying", 有一个更好的称呼,像"query target impedance mismatch".我们需要真正的SQL关系型数据库查询,我们需要Java 8 Streams API函数式编程查询内存集合数据. 给力 Java 8!

上面这篇文章中,对 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 和缺失相当多部分的函数式,更会阻止自身进步的步伐,不能给使用者带来的便利,可以说是一种对尝试初心的背反。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/290553.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

svn之迁移代码技巧

1、问题 之前客户做了很多定制,加起来有10几个,每个项目里面4分代码,需要迁移到高版本里面去。我特么傻逼了看每次svn记录然后一个一个的修改,日了狗一样。 2、解决办法 点击到当前目录 svn showlog 然后 ctrl A 然后点击鼠标右…

《编译与反编译技术》—第1章1.7节C语言程序的编译流程

本节书摘来自华章出版社《编译与反编译技术》一书中的第1章,第1.7节C语言程序的编译流程,作者庞建民,陶红伟,刘晓楠,岳峰,更多章节内容可以访问云栖社区“华章计算机”公众号查看。1.7 C语言程序的编译流程…

Base64

2019独角兽企业重金招聘Python工程师标准>>> Base64是一种基于64个可打印字符来表示二进制数据的表示方法。由于2的6次方等于64,所以每6个比特为一个单元,对应某个可打印字符。三个字节有24个比特,对应于4个Base64单元&#xff0c…

字符编码总结

字符编码精华总结 文件或字符串乱码相信大家都没少遇到, 今天主要就来搞清楚字符串的编码到底是怎 么一回事. 首先, 我们放把自己置空, 假设现在从来没有字符编码, 刚有一台计算机产生, 让我 们来设计一套方案, 目标是让在计算机屏幕上看到我们平时所书写的字符. 你会怎么 做?…

软件配置管理(六)常用配置软件配置工具指令

文章目录软件配置管理工具的主要功能两种版本控制模型Lock-Modify-UnlockCopy-Modify-MergeSubversionGit软件配置管理工具的主要功能 版本控制变更管理配置审核配置状态统计问题跟踪访问控制和安全控制 两种版本控制模型 Lock-Modify-Unlock “加锁-修改-解锁”模型 对于版…

.NET 6 攻略大全(一)

点击上方蓝字关注我们(本文阅读时间:15分钟)欢迎使用 .NET 6。今天的版本是.NET 团队和社区一年多努力的结果。C# 10 和 F# 6 提供了语言改进,使您的代码更简单、更好、性能大幅提升,我们已经看到微软降低了托管云服务的成本。.NE…

http和https和ssl和tcp/ip之间的关系和区别

1、http解释 超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。所有的WWW文件都必须遵守这个标准,HTTP是客户端浏览器或其他程序与Web服务器之间的应用层通信协议。在Internet上的Web服务器上存放的都是超文本信息,客户机需要通过HT…

Win7下JDK环境变量的设置

JDK并不像Microsoft阵营vs那样智能,安装好后所有的东西都给你配置好了,我们还没需要手动配置很多东西 首先说为什么要配置JDK的环境变量在任何路径下识别java命令和java类 配置分为2个部分,1,java命令路径。2,java加载类 分为3个步…

简单模拟实现简单的当登录延时的效果

①、先建立一个activaty去部署我们的登陆界面 1 package com.example.administrator.actionbardemo;2 3 import android.app.Activity;4 import android.content.Intent;5 import android.os.Bundle;6 import android.view.View;7 import android.widget.Button;8 import andro…

《音乐达人秀:Adobe Audition实战200例》——实例11 录制任意音量音乐

本节书摘来自异步社区《音乐达人秀:Adobe Audition实战200例》一书中的第2章,实例11 ,作者 健逗,更多章节内容可以访问云栖社区“异步社区”公众号查看。 实例11 录制任意音量音乐 这个实例将讲解如何任意控制录音过程中的音量。你…

软件项目组织管理(四)项目集成管理

文章目录什么是集成管理集成管理的主要工作SWOT方法筛选信息技术项目过程项目章程集成变更控制变更控制委员会利益相关者分析什么是集成管理 在项目生命周期中协调所有其他项目管理知识领域所涉及的过程,确保项目所有组成要素在恰当的时间、正确的地方、合适的人物…

我的技术回顾2019不止技术的一年

这篇本想具体说下ABP的商业模式的演进与变化,因为愿意像我这样花费心力去研究他的人不多。写着的时候,就得没必要。真有这种想法的人,也会自己研究,我何必去写呢。2019年初,因为各种原因,加上企业资源的调整…

linux之在当前目录下删除不包含aa的文件

1、问题 1、当前目录下删除不包含aa的文件和文件夹2、解决办法 1、rm -rf ls -al | grep -v "aa"

设计模式(1)--简单工厂模式、策略模式

设计模式(1)--简单工厂模式、策略模式 1. 简单工厂模式 在阎宏博士的《JAVA与模式》一书中开头是这样描述简单工厂模式的:简单工厂模式是类的创建模式,又叫做静态工厂方法(Static Factory Method)模式。简单…

hql Hibernate.gethibernatetemplate()

1. find(String hql); //普通查询 示例:this.gethibernateTemplate().find("from User"); 2. find(String hql,Object value);//一个查询条件 示例:this.gethibernateTemplate().find("from User u where u.name?","test&quo…

软件项目组织管理(五)项目范围管理

范围管理的重要性 软件企业与IT项目应用企业信息化成功的基本保证是对项目范围的确切圈定,维持必须强调: 三类人的获取 需求专家咨询专家概要设计专家 三要素的把握 企业需求管理理论竞争压力 什么是范围 指开展项目产品所包括的所有工作及产生这些…

kmp算法讲解

转自——http://blog.csdn.net/v_july_v/article/details/7041827 看到kmp是不是立即想到(*ο*) 哇~,那个东西啊,就是拿来放电影的那个啊! 哦,但是这里我们说的并不是那个东西,身为一名C选手,我…

TLS/SSL协议工作原理

1、TLS/SSL的功能实现原理简单介绍 HTTPS协议的主要功能基本都依赖于TLS/SSL协议,TLS/SSL的功能实现主要依赖于三类基本算法:散列函数 Hash、对称加密和非对称加密,其利用非对称加密实现身份认证和密钥协商,对称加密算法采用协商的密钥对数据加密,基于散列函数验证信息的…

实现DDD领域驱动设计: Part 4

原文链接: https://dev.to/salah856/implementing-domain-driven-design-part-iv-29m2对象到对象映射当两个对象具有相同或相似的属性时,自动对象到对象映射是一种将值从一个对象复制到另一个对象的有用方法。DTO和实体类通常具有相同/相似的属性,你通常…

输入输出及注意事项

输入输出命令: 输入函数scanf:在控制台接收指定格式的键盘输入,并将输入内容置于指定变量内存地址中;【格式:scanf(“格式化说明符”, 指定变量内存地址);】 格式: scanf(“%d”,&x);注意&…