代码之家  ›  专栏  ›  技术社区  ›  javamonkey79

Apache CollectionUtils的良好用途

  •  2
  • javamonkey79  · 技术社区  · 16 年前

    我找到了 CollectionUtils

    是否发现这些方法(transform、predicatedCollection、collect等)有独特的\有用的用途,例如将转换器或谓词作为参数的方法?

    5 回复  |  直到 16 年前
        1
  •  2
  •   joel.neely    16 年前

    我认为关键问题在于设计/编码的灵活性。

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

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

    现在考虑代码的结构,该代码可能是由一个蛮力、在线方法编写的:包含一个复杂的决策过程的外循环来确定要执行哪些测试,与代码一起混合,该代码与集合中的“幸存”成员做一个或多个事情。这样的代码往往难以理解(尤其是随着维护时间的推移变得难以理解),并且在没有引入缺陷风险的情况下很难修改。

    • 基本的“选择某物”过程,
    • 表示基本条件的谓词,
    • 组合构成谓词的运算符,以及
    • 按值运行的变压器,

    可以单独编码和测试,然后根据需要快速组合在一起。

        2
  •  2
  •   Andrzej Doyle    15 年前

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

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

    我发现定义这些属性的简单中间表示(作为内部类),为两个具体对象类定义转换器(同样非常简单,因为它只是使用相关的访问器方法来获取属性),然后使用 collect()

    作为一个(半)具体的例子,假设我需要一个方法来检查表示层中的对象集是否是数据层中缓存的对象的子集。通过上述方法,可以这样做:

    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指标,则也不能使用它。;-)

        3
  •  1
  •   Dave Ray    16 年前

    虽然我原则上同意Uri,但在没有闭包或函数文本或其他东西的情况下,Java实际使用collect、transform等方法会带来相当高的语法成本。在很多情况下,实际的代码行数与编写简单循环时的代码行数相同或更多。addAll、removeAll和他们所有不以函数对象为参数的朋友都是不可或缺的。

    所有这些同样适用于同样好的人 Google Collections API .

    令人遗憾的是,Sun有能力在Java7中解决这些问题,但是 appears they won't . 胆小鬼。

        4
  •  0
  •   Uri    16 年前

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

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

    重构传道者会声称,您的目标通常应该是创建调用其他操作的简单而简短的函数。虽然addAll、find等方法很容易自己实现,但避免它们需要读者掌握比单个单词更复杂的内容,并可能导致代码复制。

    依我看,CollectionUtils实际上提供了比标准Java集合库更干净的操作。

        5
  •  0
  •   John Nilsson    16 年前

    虽然我们不使用collectionutils,但我们自己和经常使用的工具实现了一些类似的实用程序

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

    那只会回来!空(…)

    MapTopProperty(集合c、字符串属性、类newType)

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

    内爆(集合c,字符串sep)