为什么我们需要来自JOOQ的JOOL?

Vin*_*ati 1 java java-8 functional-interface jool-library

通过JOOLJOOQ,Streams上提供了许多功能接口和实用程序类.

我的问题是这个库支持1-16个参数功能接口.这有道理吗?因为我一直在练习中将方法中的参数数量减少到3.虽然可接受的数量根据不同的思想领袖而变化.但没有人说16.

请参阅StackOverflow本身的参考链接:

java方法应具有的标准参数数量是多少?

此外,它提供了一个实用程序类Seq,它看起来仅限于顺序处理.

使用JOOL具有良好过去经验的人可以回答为什么我应该使用JOOL看起来像它包含的很多东西是没用的吗?

Luk*_*der 10

乔?作者在这里。

您似乎遇到的困难是业务逻辑中的普通方法与特定库函数有些相关的想法。他们不是。让我解释:

业务逻辑中的一个普通方法...

...确实不应该使用超过三个参数,因为一旦超过该数量,您的一些参数很可能以某种方式紧密相连,值得将它们重新设计为一个类。

这是面向对象的基础知识,适用于各种用例。

更具技术性的库中的特定方法/功能......

...另一方面,不限于这种面向对象的设计原则。在 jOO? 的情况下,该库实际上解决了(几个)语言限制,特别是缺乏一流的元组支持。

许多语言(SQL 是最突出的语言之一)支持元组,它们就像 Java 中的类,区别在于:

  • 结构类型,而不是名义上类型
  • 将它们的属性排序(可按名称索引访问),而不是按随机顺序(仅可按名称访问)

将 aTuple16<T1, T2, ..., T16>视为与具有 16 个命名属性(以及 getter/setter,如果您愿意)的 Java 类相同的东西。将 aFunction16<T1, T2, ..., T16, R>视为与接受此类具有 16 个命名属性的类的 Java 方法相同的事物。

因此,这些差异主要是文体性质的。一般来说,一种方法相对于另一种方法并没有真正的严格优势。

现在,如果您是一名碰巧使用 Java 的函数式/声明式程序员,那么 Java 语言和 JDK API 的局限性会限制您对程序进行推理的方式。这是jOO的原因之一?存在,以帮助这些人假装 Java 语言实际上具有应用于元组的元组和函数,并且为了模拟那个,嗯,jOO?必须“重载”相同类型的函数 16 次 - 16 是任意上限(.NET 将元组限制为 8 级,Scala 将它们限制为 22)。

回答您的具体问题

我的问题是这个库支持 1-16 个参数函数接口。这有意义吗?

是的,即使你通常只使用程度较低的那些,你偶尔也会发现一个Tuple16<T1, T2, ..., T16>有用的,就像你设计类时,大多数只有几个属性,你会发现自己偶尔会写一个具有 16 个以上属性的类。

虽然可接受的数字因不同的思想领袖而异。但是没有人说16。

将您的思想从面向对象的教条中解放出来。思想领袖说些什么总是有原因的。它在上下文中是正确的,但从来都不是普遍正确的。你有没有写过一个 16 列的 SQL 查询?当然你有。为什么它在 SQL 中可以接受,而在 Java 中不可以?

此外,它还提供了一个实用程序类 Seq,它看起来仅限于顺序处理。

是的,这是主要的设计目标。顺序处理允许相当多的附加功能在并行处理中没有意义,但在 JDK 的 Stream API 中却严重缺失。

过去使用 JOOL 的经验丰富的人能否回答为什么我应该使用 JOOL,因为它包含的很多东西看起来都没用?

如果您看不到它的用途,请不要使用它。但是从您的评论(您似乎更喜欢传递Object[]键入的元组),我认为您确实了解它的用法,您只是不想写下类型,因为什么是Object[],如果不是穷人的,带有随机的无类型元组程度?


Mon*_*Kin 5

函数中没有一定数量的参数我认为是最佳实践,我认为你应该使用你需要的东西而不会走极端,造成效率低下或使你的代码难以阅读.如果你发现自己有一个带有10个参数的函数,那么请三思而后行(或许它有意义).

有几个库使用接收10多个参数的函数:

其原因主要是编译时类型检查.此外,您可以争论提高效率和感知清洁度.

以Guava的of功能为例:

ImmutableMap<K,V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4)
Run Code Online (Sandbox Code Playgroud)

这是这样使用的:

Map<String, Integer> m = ImmutableMap.of("Ashlyn", 127, 
                                         "Abigaile", 128,
                                         "Alexis", 132,
                                         "Ashlynn", 132);
Run Code Online (Sandbox Code Playgroud)

该函数接收8个参数,提供:

类型安全

因为在编译时检查"奇数"参数是否为String"偶数"参数Integer.您无法使用vararg函数执行此操作,因为您需要将varargs参数声明为Object...,从而丢失编译时类型检查.

效率

您可以通过使用如下的中间对象来获得编译时类型安全性:

Map.ofEntries(entry("Ashlyn", 27), 
              entry("Abigaile", 28),
              entry("Alexis", 32),
              entry("Ashlynn", 32))
Run Code Online (Sandbox Code Playgroud)

顺便说一下,Java 9中存在哪种方式,但随后您将创建4个8参数版本不需要的中间对象.您还将创建一个额外的数组对象来保存varargs对象.

清洁度

比较前两个代码片段,包含entry()更多字母来键入和读取.这可能是一种主观的,但至少我更喜欢代码看起来没有包含entries.

为什么jOOλ?

jOOλ起到了解决这些Java API缺陷的作用:

  • 你有功能和BiFunction,但你不能做类似的事情 TriFunction<Integer, String, Boolean, Double>.除非你使用jOOλ,否则你必须牺牲一个参数(或类型安全).

  • Java完全缺少元组,你需要使用javatuples或jOOλ,除非你想再次牺牲类型安全性.

  • Java的API中存在与此问题无关的其他缺陷,但是jOOλ(我最喜欢的那个)能够传递一个抛出已检查异常的lambda.

  • @VinayPrajapati我同意这些方法有20个参数并不理想,因为它是由Java的限制造成的.但到目前为止,这是人们发现的最佳解决方法(不仅仅是在Java中,我所知道的语言对于同样的问题没有完美的解决方案),而且我们现在仍然坚持使用该解决方案.此外,关于11"K,V"对,在这种情况下,您将使用`Map.ofEntries`方法,该方法对对的数量没有限制. (2认同)