我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Clojure与Java对比实例分析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Clojure与Java对比实例分析

这篇文章主要介绍“Clojure与Java对比实例分析”,在日常操作中,相信很多人在Clojure与Java对比实例分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Clojure与Java对比实例分析”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

    问题所在

    我一直在写一个代理,接收javax.servlet.http.HttpServletRequest 并通过Apache HttpClientorg.apache.http.client.methods.HttpUriRequest,然后从org.apache.http.HttpResponsejavax.servlet.http.HttpServletResponse,尤其是关于(一个子集)头的响应。

    这是一件痛苦的事,因为每个人都有自己的头表示和使用headers的API:

    // javax.servlet.http.HttpServletRequest:Enumeration<String> getHeaderNames();Enumeration<String> getHeaders(String name);// org.apache.http.client.methods.RequestBuilder:RequestBuilder addHeader(String name, String value);//-------------// javax.servlet.http.HttpServletResponse:void addHeader(String name, String value);// org.apache.http.HttpResponse:Header[] getAllHeaders();// Header:String getName();String getValue();

    这里,枚举和数组是通用的数据结构,但头和请求对getHeaderNamesgetHeaders的拆分需要特定的代码。

    因此,我必须编写translation函数,如:

    def copyRequestHeaders(HttpServletRequest source, RequestBuilder target) {    source.getHeaderNames().each { String hdr ->        source.getHeaders(hdr).each { String val ->            if (undesirable(hdr)) return            target.addHeader(hdr, val)        }    }}

    static void copyResponseHeaders(HttpResponse source, HttpServletResponse target) {    source.allHeaders.each { Header hdr ->        if (target.getHeader(hdr.name.toLowerCase()) == hdr.value) return // avoid duplicates        if (undesirable(hdr.name)) return        target.addHeader(hdr.name, hdr.value)    }}

    理想情况下,我希望能够像target这样做target.request.headers = omitKeys(undesirable, source.request.headers)。但这是不可能的,我必须从一组类型映射到另一组类型。这里的主要问题是servlet请求被拆分为getHeaderNamesgetHeaders,而不是返回例如Map<String,String[]>,还有RequestBuilder,它有addHeader,但无法一次添加所有头(除非我们首先将它们包装在其域类中,即Header中)。

    (可以说,我可以找到一个更好的例子来说明这一点。在这里,我们仍然主要(但不总是)使用枚举、字符串、数组等基元/泛型类型,而不是嵌套的自定义类型层次结构。)

    Clojure解决方案

    在Clojure中,请求只是一个映射,标题很可能是列表的映射。即使这两个库(服务器、客户端)在密钥名称或数据结构上不一致,也没有“API”可学习-您只需使用相同的旧已知函数从一个数据结构转换到另一个数据结构,这是您在每个Clojure项目、web、数据或任何其他领域中所做的事情。唯一改变的是地图中关键点的名称。

    注意:如果您不知道Clojure,那么一些示例可能很难阅读,例如assocreduce-kv (key-value)函数以及偶尔的单字母名称。请记住,Clojure程序员反复使用相同的100个函数,并且非常熟悉它们。与其他一些语言相反,Clojure有意识地选择为有经验的开发人员进行优化。这对我来说很好。

    案例1:相同的Keys

    最简单的情况是,使用相同的key,我们只想选择一个子集:

    (assoc  target-request  :headers  (select-keys (:headers source-request) [:pragma :content-type ...]))

    唯一区分大小写的部分是keys。在Java中,您不能像我们在这里使用通用选择键那样一次选择所有所需的keys,您需要通过类特定的getHeaders(name)逐个选择它们。

    案例2:不同的Key名,相同的数据结构

    (assoc  target-request  :headersX  (clojure.set/rename-keys    (select-keys (:headersY source-request) [:Pragma :ContentType ...])    {:Pragma :pragma, :ContentType :content-type}))

    如果需要更复杂的key转换,我们可以使用例如map:

    (defn transform-key [k] ...)(let [hdrs (->> (select-keys headers [:a])                (map (fn [[k v]] [(transform-key k) v]))                (into {}))]    (assoc target-request :headersX hdrs))

    关键是,在从一个数据结构映射到另一个数据结构的过程中,我们仍然使用我们所知道和喜爱的相同功能,唯一针对具体情况的部分是键和键转换函数。我们可以简单地映射头映射,这在HttpServletRequest的头上是不可能的。

    案例3:不同的数据结构

    headers作为name-value对列表(可能有重复的名称)进入name-value映射:

    (def headers-in [["pragma" "no-cache"] ["accept" "X"] ["accept" "Y"]])(->> headers-in     (group-by first)     (reduce-kv       (fn [m k vs]         (assoc           m           k           (map second vs)))       {})); => {"pragma" ("no-cache"), "accept" ("X" "Y")}

    案例4:Reality

    实际上,我们可能会使用Ring作为服务器,并将Clojure包装器clj-http用于Apache HttpClient。

    请求如下所示:

    {:headers {"accept" "x,y", "pragma" "no-cache"}}

    (我们可以添加ring-request-headers-middleware,将连接的值转换为单个值的列表。)

    Clj-http遵循Ring规范,因此支持相同的格式,但更为宽松:

    clj http对头的处理比ring规范指定的要宽松一些。

    clj http允许任何大小写的字符串或关键字,而不是强制所有请求头都是小写字符串。关键字将转换为它们的规范表示形式,因此:content-md5标头将作为“content-md5”发送到服务器。但是,请求头中的字符串键将被发送到服务器,其大小写保持不变。

    响应标题可以作为任何大小写的关键字或字符串读取。如果服务器以“Date”标头响应,则可以访问该标头的值,如:Date、“Date”、“Date”等。

    这就是上面第1种情况。

    Java Vs Clojure

    我想指出的一点是,Clojure在解决两个问题方面更为有效:数据选择和转换,这要归功于对其使用通用数据结构和函数。

    选择

    在Clojure中,通过选择另一个映射的子集来创建映射非常简单(assoc将键与值关联,select keys返回映射):

    (assoc  request  :headers  (select-keys    (:headers other-request)    [:pragma ...]))

    使用典型的Java数据类(还记得DTOs吗?)您需要逐个获取和设置各个属性。即使我们使用Groovy便利:

    new Person(  firstName: employee.firstName,  lastName: employee.lastName,  ...)

    这里的重点并不是键入的数量,而是在Clojure中,我们可以使用现有函数(并将它们组合成新的可重用函数)来完成这项工作,而在Java中,您必须编写(更多)自定义的一次性代码。(或者使用映射器库、注释和其他黑魔法:-))

    转换

    如上所述,在Clojure中,将头从一个请求复制到另一个请求是微不足道的。在典型的Java中,标头将由它们自己的类型(可能是标头)表示,因此,即使它们在两个库中具有相同的形状,它们仍然是不同的类型,我们需要从一种类型转换为另一种类型:

    // fake code <img class="lazy" data-src="https://file.lsjlt.com/upload/202306/28/f0by3zntb4l.gif" alt=":-)" />def toClientHdr(servlet.Header hdr) {  return new httpclient.Header(    name: hdr.name,    values: hdr.values)}clientRequest.headers =  servletRequest.headers    .map(toClientHdr)

    在Clojure中,toClientHdr是不必要的,因为我们只有映射,没有要从/映射到的类型。我们在这里的前提是,数据的“形状”在两端都是相同的,但即使不是,也更容易从一个转换到另一个,因为数据转换是FP的主要优势之一,尤其是Clojure。核心库中有许多有用的数据选择和转换功能,旨在以多种强大的方式进行组合。

    验证、封装?

    即使您同意使用一些具有强大功能的通用数据结构比将数据包装在类型中更有效,您也可能会担心类的其他好处,例如封装和数据验证。这超出了本文的范围,但请确保FP/Clojure具有满足这些需求的解决方案,尽管它们明显不同于OOP。

    到此,关于“Clojure与Java对比实例分析”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

    免责声明:

    ① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

    ② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

    Clojure与Java对比实例分析

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档

    猜你喜欢

    Clojure与Java对比实例分析

    这篇文章主要介绍“Clojure与Java对比实例分析”,在日常操作中,相信很多人在Clojure与Java对比实例分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Clojure与Java对比实例分析”的疑
    2023-07-02

    Kotlin与Java主客观对比的示例分析

    这篇文章将为大家详细讲解有关Kotlin与Java主客观对比的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。KotlinKotlin是一门相对比较新的JVM语言,JetBrains自2011年以来
    2023-05-30

    Java中观察者模式与委托的实例对比分析

    这篇文章主要介绍“Java中观察者模式与委托的实例对比分析”,在日常操作中,相信很多人在Java中观察者模式与委托的实例对比分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java中观察者模式与委托的实例对
    2023-06-30

    java中关于对象的实例比较分析

    本篇内容主要讲解“java中关于对象的实例比较分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“java中关于对象的实例比较分析”吧!同类型对象的比较三个维度去比较同一性相等性相似性样例引入想象
    2023-06-26

    Java中对象比较的示例分析

    这篇文章主要介绍了Java中对象比较的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。元素比较基本类型的比较在Java中,基本类型的对象可以直接比较大小public c
    2023-06-29

    Java对象实例分析

    这篇文章主要介绍“Java对象实例分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java对象实例分析”文章能帮助大家解决问题。1、寒冬的蛰伏这里的工作很繁忙,一年365天, 一天24小时几乎不停
    2023-06-04

    Android Coil和Glide实例对比分析

    这篇文章主要介绍“Android Coil和Glide实例对比分析”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Android Coil和Glide实例对比分析”文章能帮助大家解决问题。Coil概述
    2023-07-05

    java静态和动态绑定的实例对比分析

    这篇文章主要介绍了java静态和动态绑定的实例对比分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇java静态和动态绑定的实例对比分析文章都会有所收获,下面我们一起来看看吧。不同绑定的比较1、静态绑定发生在编
    2023-06-30

    C++类与对象实例分析

    这篇“C++类与对象实例分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C++类与对象实例分析”文章吧。运算符重载C++语
    2023-06-30

    Java中对HashMap的深度分析与比较(转)

    Java中对HashMap的深度分析与比较(转)[@more@]在Java的世界里,无论类还是各种数据,其结构的处理是整个程序的逻辑以及性能的关键。由于本人接触了一个有关性能与逻辑同时并存的问题,于是就开始研究这方面的问题。找遍了大大小小的
    2023-06-03

    Python中Sync与Async执行速度快慢实例对比分析

    这篇文章主要讲解了“Python中Sync与Async执行速度快慢实例对比分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python中Sync与Async执行速度快慢实例对比分析”吧!1
    2023-07-05

    TypeScript与JavaScript对比及打包工具对比分析

    这篇文章主要介绍了TypeScript与JavaScript对比及打包工具对比分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇TypeScript与JavaScript对比及打包工具对比分析文章都会有所收获,
    2023-07-05

    VB.NET语言与VB语言对比的示例分析

    小编给大家分享一下VB.NET语言与VB语言对比的示例分析,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!VB.NET语法对比旧语法 新语法 说明窗体装载事件,类初始化事件 Sub New procedure Sub New
    2023-06-17

    Java 输入输出 IO NIO AIO三兄弟对比分析对比分析

    这篇文章主要为大家介绍了Java 输入输出 IO NIO AIO三兄弟对比分析对比分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-15

    Component与PureComponent对比源码分析

    这篇文章主要介绍了Component与PureComponent对比源码分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Component与PureComponent对比源码分析文章都会有所收获,下面我们一起
    2023-07-05

    Java中类与对象的示例分析

    这篇文章主要介绍Java中类与对象的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!类和对象在面向对象中,类和对象是最基本、最重要的组成单元。类实际上是表示一个客观世界某类群体的一些基本特征抽象。对象就是表示一
    2023-06-20

    编程热搜

    • Python 学习之路 - Python
      一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
      Python 学习之路 - Python
    • chatgpt的中文全称是什么
      chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
      chatgpt的中文全称是什么
    • C/C++中extern函数使用详解
    • C/C++可变参数的使用
      可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
      C/C++可变参数的使用
    • css样式文件该放在哪里
    • php中数组下标必须是连续的吗
    • Python 3 教程
      Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
      Python 3 教程
    • Python pip包管理
      一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
      Python pip包管理
    • ubuntu如何重新编译内核
    • 改善Java代码之慎用java动态编译

    目录