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

Google Guava比Apache Collections更难使用吗?[关闭]

  •  26
  • tpdi  · 技术社区  · 14 年前

    我正在考虑让我的团队,混合技能水平,使用谷歌番石榴。在Guava之前,我会使用Apache集合(或其泛化版本)。

    与Apache集合相比,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集合相比,函数.compose(g,f)颠倒了“直观的”顺序:函数从右到左应用,而不是从左到右的“明显的”变压器直到链式变压器.

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

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

    但我的变换集中可能有空值,所以我不能这么做。我可以把它倒进垃圾桶里java.util.Collection集合,当然。

    但这对我的(经验较少的)团队来说并不明显,即使在我解释了它之后,在编码的热度中也可能会被忽略。我希望也许Iterables.contains包含()会“做正确的事情”,并且知道一些魔术的例子来区分实时视图代理和普通的旧集合,但事实并非如此。这使得Guava可能更难使用。

    也许我在我的实用程序类中编写了一个静态方法来处理这个问题?

    // 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 在番石榴中,我想答案是,“好吧,总是把它返回的东西转储到一个新的集合中,或者写你自己的转换来实现”。

    2 回复  |  直到 14 年前
        1
  •  58
  •   ColinD    14 年前

    我要说的是,Guava绝对不比Apache Collections更难使用。实际上,我想说这要容易得多。

    Guava的优点之一是它不会暴露太多新的对象类型。。。它喜欢将使用的大多数实际实现类型整齐地隐藏在只公开接口的静态工厂方法后面。以各种 Predicate s、 例如。在Apache集合中,有顶级公共实现类,如:

    NullPredicate
    NotNullPredicate
    NotPredicate
    AllPredicate
    AndPredicate
    AnyPredicate
    OrPredicate
    

    在番石榴,它们被整齐地包装在一个顶级班级里, Predicates

    Predicates.isNull()
    Predicates.notNull()
    Predicates.not(...)
    Predicates.and(...)
    Predicates.or(...)
    

    他们都没有公开他们的实现类,因为你不需要知道它!而Apache集合确实有一个等价的 PredicateUtils 事实上,它暴露了 谓语 s使其更难使用。我把Apache作为一个整体来使用,而不是把它作为一个不必要的部分来使用。当您查看这两个库公开的类和接口的数量时,差别就很明显了:

    • Apache集合公开了309个类型。
    • Guava,包括它的所有包(不仅仅是集合)只公开了191种类型。

    要解决您的一些具体问题:

    我真的认为番石榴选择的菜 Functions.compose 更多 朝向 get 方法转换为其他类型。番石榴的优点 compose 在一排 Transformer 在apachecommons示例中 组成

    视图优于副本:

    Collections2.transform Collection 进入一个新的世界 实际上效率要高得多!下面是你打电话时会发生的事情 集合2.0 然后打电话 contains 收藏 它返回:

    • 收藏 正在创建包装原始文件。。。原版和原版 Function 两者都简单地分配给其中的字段。
    • 这个 收藏 检索的迭代器。
    • 对于 Iterator
    • 当第一个元素 equals 包含 会回来的。您只需迭代(并应用 功能 )直到找到匹配的!这个 每个元素最多应用一次!

    以下是Apache Collections版本的功能:

    • 创建新的 ArrayList 存储转换后的值。
    • 收藏 的迭代器。
    • 的迭代器,应用函数并将结果添加到新的 收藏 每个元素 原版的 收藏 变压器 到第一个元素就可以匹配我们要找的对象了!
    • , 包含 将迭代新 收藏 寻找结果。

    使用两个库的大小为N。最佳情况是第一个元素的转换值 等于 你要找的东西 包含 在转换的集合中不存在。

    • 番石榴 :
      • :迭代1个元素,应用 1次,存储0个附加元素。
      • 最坏的情况 :迭代N个元素,应用 N次,存储0个附加元素。
    • 阿帕奇 :
      • 最佳案例 变压器 N次,存储N个附加元素(转换的集合)。
      • 最坏的情况 :迭代2N个元素,应用 变压器

    非常

    作为最后一个小音符, Iterables.contains 只允许您检查 Iterable 你不知道要成为一个 包含一个值。如果 可迭代的 你给它实际上是一个 收藏 contains() 为您提供更好的性能(如果是 Set ,比如说)。

        2
  •  19
  •   Jared Levy    14 年前

    在实时视图方面,ColinD描述了一些用例的性能优势。此外,有时您希望对视图的更改更改原始集合,反之亦然。