我在大约一年前找到了CollectionUtils类,并且收集和转换等一些方法看起来很酷,但是,我还没有找到一种在语法上更清洁的方法。 \或者更简单地用简单的循环编写逻辑。
是否找到了这些方法的唯一\有用用途(transform,predicatedCollection,collect等),例如:将变换器或谓词作为参数的方法?
答案 0 :(得分:2)
我认为关键问题是设计/编写灵活性。
如果您有一个用例(例如,选择满足某些特定条件的集合的成员),则手动编码相对简单的循环。另一方面......
假设可能条件的集合变大,或者甚至可以在运行时即时组合(甚至动态地,基于用户输入/交互)。或者假设有一些非常复杂的条件可以由操作员(例如A和B,C而不是D等)组成甚至更多的情况。
假设在做出选择之后,还会对结果集合进行一些其他处理。
现在考虑一下代码的结构,这种代码结构可能来自一个强力的,内联的方法来编写上面的内容:一个包含复杂决策过程的外部循环,用于确定要执行哪些测试,与代码混合在一起与集合中“幸存”成员做一件事或多件事。这样的代码往往(并且特别是随着时间的推移而变得难以理解)难以理解并且难以修改而没有引入缺陷的风险。
所以关键是要追求每个方面的策略:
可以独立编码和测试,然后根据需要拼接在一起。
答案 1 :(得分:2)
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指标,它也不能成为珠子。 ; - )
答案 2 :(得分:1)
虽然我原则上同意Uri,没有闭包或函数文字等等,但Java实际上使用了诸如collect,transform等方法的语法成本相当高。在很多情况下,实际的代码行是与编写简单循环相同或更大。 addAll,removeAll以及所有不将函数对象作为参数的朋友都是必不可少的。
所有这些也适用于同样优秀的Google Collections API。
令人遗憾的是,Sun有能力在Java 7中解决这些问题,但它appears they won't。懦夫。
答案 3 :(得分:0)
我不确定我同意你的陈述......
一个简单的循环增加了复杂性,并且比具有合理名称的调用更不“可读和明显”。
重构福音传道者会声称你的目标通常应该是创建平局和短线函数来调用其他操作。虽然addAll,find和这些方法很容易自己实现,但是避免它们需要读者掌握比单个单词更复杂的东西,并且可能导致代码复制。
恕我直言,CollectionUtils实际上提供了比标准Java集合库更清晰的操作。
答案 4 :(得分:0)
虽然我们不使用CollctionUtils,但我们已经实现了一些类似的实用工具以及我们经常使用的实用工具
空(收藏c)
测试集合,字符串等是否为空白
具有(...)
只返回!empty(...)
mapToProperty(Collection c,String property,Class newType)
这将T1的集合映射到T2的集合,使用反射来调用“property”
implode(Collection c,String sep)
包含c
元素的sep分隔字符串