Google Guava比Apache Collections“更难”使用吗?

时间:2010-10-16 03:29:53

标签: java collections guava

我正在考虑让我的团队使用混合技能级别来使用Google Guava。在Guava之前,我已经使用了Apache Collections(或它的通用版本)。

与Apache Collections相反,Guava在某些方面似乎更强大,但对于经验不足的程序员来说可能不太容易使用。这是我认为可以举例说明的一个领域。

我继承的代码包含大量循环,这些循环基本上是异构值的映射,探测它们的值,进行空检查,然后做一些微不足道的事情:

boolean foo( final List< MapLike > stuff, final String target ) {
  final String upperCaseTarget = target.toUpperCase(0;

  for( MapLike m : stuff ) {
     final Maplike n = (MapLike) m.get( "hard coded string" );
     if( n != null ) {
         final String s = n.get( "another hard code string" );
         if( s != null && s.toUpperCase().equals( upperCaseTarget ) ) {
            return true ;
         }
     }
   return false ;
}

我最初的想法是使用Apache Collections Transformers:

boolean foo( final List< MapLike > stuff, final String target ) {
   Collection< String> sa = (Collection< String >) CollectionUtils.collect( stuff, 
     TransformerUtils.chainedTransformer( new Transformer[] { 
        AppUtils.propertyTransformer("hard coded string"),
        AppUtils.propertyTransformer("another hard coded string"),
        AppUtils.upperCaseTransformer()
         } ) );

    return sa.contains( target.toUpperCase() ) ;        

}

使用番石榴,我可能会采取两种方式:

boolean foo( final List< MapLike > stuff, final String target ) {
   Collection< String > sa = Collections2.transform( stuff,
       Functions.compose( AppUtils.upperCaseFunction(), 
       Functions.compose( AppUtils.propertyFunction("another hard coded string"), 
                          AppUtils.propertyFunction("hard coded string") ) ) );

    return sa.contains( target.toUpperCase() ) ;    
    // or
    // Iterables.contains( sa, target.toUpperCase() );
    // which actually doesn't buy me much

}

与Apache Collections相比,Functions.compose(g,f)颠倒了“直观”的顺序:函数从右向左应用,而不是从TransformerUtils.chainedTransformer的“显而易见”的从左到右。

一个更微妙的问题是,当Guava返回实时视图时,在实时视图上调用contains可能会多次应用(组合)函数,所以我真的应该做的是:

   return ImmutableSet.copy( sa ).contains( target.toUpperCase() ) ;

但我可能在我的变换集中有空值,所以我不能那样做。我当然可以将它转储到java.util.Collection中。

但对于我的(经验较少的)团队而言,这并不是很明显,即使在我解释之后,也很可能会在编码的热度中错过。我希望也许Iterables.contains()可以“做正确的事”并且知道一些魔法实例来区分实时视图代理和普通的旧代理,但事实并非如此。这使得番石榴可能更难使用。

也许我在实用程序类中编写类似静态方法的东西来处理它?<​​/ p>

// List always uses linear search? So no value in copying?
// or perhaps I should copy it into a set?
boolean contains( final List list, final Object target ) {
  return list.contains( target ) ;
}

// Set doesn't use linear search, so copy?
boolean contains( final Set set, final Object target ) {
  //return ImmutableSet.copy( set ).contains( target ) ;
  // whoops, I might have nulls
  return Sets.newHashSet( set ).contains( target ) ;
}

或者可能只复制超过一定大小的集合?

// Set doesn't use linear search, so copy?
boolean contains( final Set set, final Object target ) {
  final Set search = set.size() > 16 : Sets.newHashSet( set ) : set ;
  return search.contains( target ) ;
}

我想我要问,“为什么在番石榴中没有'更容易'transform,我想答案是,”很好,只是总是将它返回到新的集合中,或编写你自己的变换“。

但如果我需要这样做,可能不是Guava库的其他客户吗?也许在番石榴中有一种更好的方式,我不知道?

2 个答案:

答案 0 :(得分:57)

答案 1 :(得分:19)

作为番石榴的开发者之一,我显然有偏见,但这里有一些评论。

易用性是Guava设计背后的主要目标之一。总是有改进的余地,我们渴望听到任何建议或疑虑。设计决策背后通常有一个理由,尽管每个人都可能找到他们个人不同意的事情。

就实时视图而言,ColinD描述了某些用例存在的性能优势。此外,有时您希望对视图进行更改以更改原始集合,反之亦然。

现在,在某些情况下,复制集合可以提供更好的性能,但只需要一行代码即可。虽然Guava可以包含transformAndCopy()方法,但我们省略了单行方法,除了极其常见的情况,如Maps.newHashMap()。存在的方法越多,找到所需方法就越困难。