繁体   English   中英

Apache CollectionUtils的良好用法

[英]Good uses for Apache CollectionUtils

我在一年前左右发现CollectionUtils类,并且其中一些方法(如收集,转换)看起来确实很酷,但是,我还没有找到一种在语法上不会更干净和/或更容易编写它的方法的用途。一个简单的循环逻辑。

有没有发现这些方法(transform,predicatedCollection,collect等)的唯一\\有用用法,例如以转换器或谓词为参数的方法?

我认为关键是设计/编码的灵活性。

如果您只有一个用例(例如,选择满足某些特定条件的集合的成员),则可以手动编写相对简单的循环。 另一方面...

假设这组可能的条件变大了,或者甚至可以在运行时动态地组成(甚至基于用户输入/交互而动态地组成)。 或者假设存在一些可能由运算符组成的非常复杂的条件(例如,A和B,C而不是D等)甚至更多情况。

假设已经做出选择,还需要对结果集合进行一些其他处理。

现在,考虑一下用强力的嵌入式方法编写上述代码可能会导致的代码结构:一个外部循环,其中包含一个复杂的决策过程来确定要执行的测试,并与执行一个测试的代码混合在一起集合中“尚存”成员的更多或更多内容。 这样的代码往往难以理解(尤其是随着维护时间的流逝),并且很难在没有引入缺陷风险的情况下进行修改。

因此,关键是要在每个方面都采取一种策略:

  • 基本的“选择内容”过程
  • 表达基本标准的谓词,
  • 组合构成谓词的运算符,以及
  • 根据值运行的变压器

可以独立进行编码和测试,然后根据需要合并在一起。

当您有可能的对象替代表示形式时,collect()很有用。

例如,最近我正在处理一段代码,该代码需要匹配来自两个不同来源的对象列表。 这些对象属于不同的类,因为它们在代码中的不同点使用,但出于我的目的,它们具有相同的相关概念(即,它们都有一个ID,都有一个属性路径,都有一个“级联”标志等)。 。

我发现,定义这些属性的简单中间表示(作为内部类),为两个具体对象类定义转换器(再次非常简单,因为它只是使用相关的访问器方法来获取属性)要容易得多,然后使用collect()将我的传入对象转换为中间表示形式。 一旦它们存在,我就可以使用标准的Collections方法来比较和操纵这两个集合。

因此,作为一个(半)具体示例,我需要一种方法来检查表示层中的对象集是否是数据层中缓存的对象的子集。 使用上面概述的方法,将执行以下操作:

public boolean isColumnSubset(PresSpec pres, CachedDataSpec dataSpec)
{
   final List<IntermediateRepresentation> presObjects = CollectionUtils.collect(pres.getObjects(), PRES_TRANSFORMER);
   final List<IntermediateRepresentation> dataObjects = CollectionUtils.collect(dataSpec.getCached(), DATA_TRANSFORMER);

   return dataObjects.containsAll(presObjects);
}

对我来说,这是更加易读,到最后一行输送什么样的方法做的 ,比用循环相当于一个真正意义上的:

public boolean isColumnSubset(PresSpec pres, CachedDataSpec dataSpec)
{
   for (PresSpecificObject presObj : pres.getObjects())
   {
      boolean matched = false;
      for (CachedDataObject dataObj : dataSpec.getCached())
      {
         if (areObjectsEquivalent(presObj, dataObj)) // or do the tests inline but a method is cleaner
         {
            matched = true;
            break;
         }
      }

      if (matched == false)
      {
         return false;
      }
   }

   // Every column must have matched
   return true;
}

两者可能差不多有效,但是就可读性而言,我会说第一个更容易立即理解。 尽管总体上出现了更多的代码行(由于定义了一个内部类和两个转换器),但是将遍历实现与实际的“真或假”逻辑分开可以使后者更加清晰。 另外,如果您有任何KLOC指标,它也不能成为珠。 ;-)

尽管我在原则上同意Uri,但没有闭包,函数文字或其他内容,但Java实际使用诸如collect,transform等方法会带来很高的语法成本。在很多情况下,实际的代码行相同或更大比起您编写了简单的循环。 不过,addAll,removeAll及其所有不将函数对象作为参数的朋友都是必不可少的。

所有这些同样适用于同样出色的Google Collections API

令人遗憾的是,Sun能够解决Java 7中的这些问题,但看来并没有解决这些问题。 懦夫。

我不确定我是否同意你的说法...

一个简单的循环增加了复杂性,并且比具有明智名称的调用的“可读性和明显性”低。

重构传福音者会声称,您的目标通常应该是创建调用其他操作的简单函数和简短函数。 尽管addAll,find和此类方法很容易实现,但要避免它们,将要求读者掌握比单个单词更复杂的内容,并可能导致代码复制。

恕我直言,CollectionUtils实际上提供了比标准Java集合库更简洁的操作。

尽管我们不使用CollctionUtils,但我们已经实现了一些类似的实用程序,这些实用程序是我们自己以及经常使用的实用程序

空(集合c)

测试集合,字符串等是否为空

拥有(...)

只返回!empty(...)

mapToProperty(Collection c,String属性,类newType)

这会使用反射将T1的集合映射到T2的集合以调用“属性”

内爆(Collection c,String sep)

带c元素的分隔字符串

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM