静态Lists.transform标记为错误,但Collections.transform使用相同的变量工作

时间:2016-07-11 18:33:41

标签: java arraylist guava jooq

我正在尝试使用Guava静态Collections2.transform和Lists.transform方法基于jooq Record类创建一个ArrayList。下面是生成result3 Record的查询。

    final Table<Record3<Key<Store>, Key<Campaign>, String>> c1 = sql.dsl()
            .select(CAMPAIGN.STORE_KEY, CAMPAIGN.CAMPAIGN_KEY, tag)
            .from(CAMPAIGN)
            .where(CAMPAIGN.CAMPAIGN_KEY.equal(campaignKey))
            .asTable("c1");

    final Table<Record3<Key<Store>, Key<Campaign>, String>> c2 = sql.dsl()
            .select(CAMPAIGN.STORE_KEY, CAMPAIGN.CAMPAIGN_KEY, tag)
            .from(CAMPAIGN)
            .asTable("c2");

    final Result<Record2<Key, Integer>> result3 = sql.dsl()
            .select(c1Campaign, count(c2Tag))
            .from(c1, c2)
            .where(c1.field("tag", String.class).equal(c2.field("tag", String.class)))
            .and(c1.field("store_key", Key.class).equal(c2.field("store_key", Key.class)))
            .and(c1.field("campaign_key", Key.class).notEqual(c2.field("campaign_key", Key.class)))
            .groupBy(c2.field("campaign_key", Key.class))
            .orderBy(inline(2).desc())
            .fetch();

以前我有以下代码正常工作,直到我意识到我需要稍后为集合添加值,而创建的集合对象不支持这些值。

    final Collection<Key<Campaign>> keys = Collections2.transform(result3, Record2::value1);

由于这个问题,我试图切换到创建一个ArrayList,但是当我添加以下内容时,我得到一个错误说&#34;非静态方法无法从静态上下文中引用&#34;

    final ArrayList<Key<Campaign>> keys2 = Lists.transform(result3, Record2::value1);

令人困惑的是,转换方法都是静态的,它们是在完全相同的对象上运行的,为什么第一个工作而不是另一个?如果第二种方法不起作用,我怎样才能以这种方式完成ArrayList的生成?

2 个答案:

答案 0 :(得分:0)

我发现编译时遇到的第二个错误指​​向了答案。我没有从Lists.transform创建一个ArrayList,而是将其更改为List并正确编译

答案 1 :(得分:0)

在实际处理问题之前,您需要了解有关Java和Guava的基本知识:

  1. 在Java中,public void RefreshAll() { // Get all objects in statemanager with entityKey // (context.Refresh will throw an exception otherwise) var refreshableObjects = (from entry in context.ObjectStateManager.GetObjectStateEntries( EntityState.Deleted | EntityState.Modified | EntityState.Unchanged) where entry.EntityKey != null select entry.Entity); context.Refresh(RefreshMode.StoreWins, refreshableObjects); } 不是List<Key>(但情况恰恰相反) - ArrayList<Key>是接口的实现(很多可能之一) ArrayList
  2. 您无法将List分配给List(至少没有强制转换,但这不是解决方案,也不是此处的选项)。
  3. 即使您创建了ArrayList,在代码中使用具体实现也不是最佳做法,而是坚持使用接口(此处:ArrayList)。
  4. Guava的ListCollections2.transform返回用于创建视图的集合的 lazy views from javadoc,强调我的):

      

    返回的列表是fromList 的转换视图;对fromList的更改将反映在返回的列表中,反之亦然。   (...)

         

    懒惰地应用该函数,在需要时调用。这对于返回的列表是视图是必要的,但这意味着该函数将多次应用于List.contains(java.lang.Object)和List.hashCode()等批量操作。为了表现良好,功能应该很快。要在返回的列表不需要是视图时避免延迟评估,请将返回的列表复制到您选择的新列表中。

  5. 尽管如此,Lists.transform在你的情况下不会评估任何东西,直到复制到某个集合/列表或消费,所以有效的方法是:

    keys

    final Collection<Key<Campaign>> keys = Collections2.transform(result3, Record2::value1);
    // later:
    final List<Key<Campaign>> keys2 = new ArrayList<>(keys); // here the function is applied
    

    困扰我的是你使用方法引用(final List<Key<Campaign>> keys2 = new ArrayList<>(Lists.transform(result3, Record2::value1)); )表明你已经在使用Java 8.如果你这样做,请使用Streams API

    Record2::value1