【问题标题】:Cleaner way to filter collections in Java 7/Guava?在 Java 7/Guava 中过滤集合的更清洁方法?
【发布时间】:2015-07-29 14:17:06
【问题描述】:

我有以下课程:

class ServiceSnapshot {
    List<ExchangeSnapshot> exchangeSnapshots = ...
    ...
}

class ExchangeSnapshot{
    Map<String, String> properties = ...
    ...
}

假设我有一组 ServiceSnapshot,如下所示:

Collection<ServiceSnapshot> serviceSnapshots = ...

我想过滤集合,以便生成的 ServiceSnapshots 集合仅包含包含 ExchangeSnapshots 的 ServiceSnapshots,其中 ExchangeSnapshots 上的属性与给定字符串匹配。

我有以下未经测试的代码,只是想知道是否有更清洁/更易读的方法来执行此操作,使用 Java 7,如有必要,可能使用 Google Guava?

更新:另请注意,我在下面提供的代码示例不适合我的目的,因为我使用 iterator.remove() 来过滤集合。事实证明我不能这样做,因为它正在修改底层集合,这意味着对下面我的方法的后续调用会导致越来越少的快照,因为之前的调用将它们从集合中删除 - 这不是我想要的。

    public Collection<ServiceSnapshot> getServiceSnapshotsForComponent(final String serviceId, final String componentInstanceId) {
        final Collection<ServiceSnapshot> serviceSnapshots = getServiceSnapshots(serviceId);
        final Iterator<ServiceSnapshot> serviceSnapshotIterator = serviceSnapshots.iterator();
        while (serviceSnapshotIterator.hasNext()) {
            final ServiceSnapshot serviceSnapshot = (ServiceSnapshot) serviceSnapshotIterator.next();
            final Iterator<ExchangeSnapshot> exchangeSnapshotIterator = serviceSnapshot.getExchangeSnapshots().iterator();
            while (exchangeSnapshotIterator.hasNext()) {
                final ExchangeSnapshot exchangeSnapshot = (ExchangeSnapshot) exchangeSnapshotIterator.next();
                final String foundComponentInstanceId = exchangeSnapshot.getProperties().get("ComponentInstanceId");
                if (foundComponentInstanceId == null || !foundComponentInstanceId.equals(componentInstanceId)) {
                    exchangeSnapshotIterator.remove();
                }
            }
            if (serviceSnapshot.getExchangeSnapshots().isEmpty()) {
                serviceSnapshotIterator.remove();
            }
        }
        return serviceSnapshots;
    }

【问题讨论】:

  • 我会检查 Java 8 lambdas 是否可以简化这一点。
  • 无论如何都不会工作。并发修改。显式使用 Iterator 以便能够调用 remove()。
  • @duffymo,抱歉,仅限 java 7。
  • 对你来说太糟糕了。 JDK 7 的支持生命周期已经结束。
  • 即使编写的代码似乎也不符合规定的要求。编写的代码似乎试图过滤 ExchangeSnapshot 对象,但声明的要求是过滤 ServiceSnapshot 对象。

标签: java refactoring guava code-readability


【解决方案1】:

使用番石榴:

Iterables.removeIf(serviceSnapshots, new Predicate<ServiceSnapshot>() {
    @Override
    public boolean apply(ServiceSnapshot serviceSnapshot) {
        return !Iterables.any(serviceSnapshot.getExchangeSnapshots(), new Predicate<ExchangeSnapshot>() {
            @Override
            public boolean apply(ExchangeSnapshot exchangeSnapshot) {
                String foundComponentInstanceId = exchangeSnapshot.getProperties().get("ComponentInstanceId");
                return foundComponentInstanceId != null && foundComponentInstanceId.equals(componentInstanceId);
            }
        });
    }
});

我可能有一个! 在某处丢失或倒置,但基本策略是删除没有任何ExchangeSnapshot 的ID 匹配的任何ServiceSnapshot 对象。

【讨论】:

  • 谢谢 Paul,虽然我还需要从返回的 ServiceSnapshots 中完全删除任何 ID 不匹配的 ExchangeSnapshots - 请参阅我的示例,我在其中进行了 exchangeSnapshotIterator.remove(),您的示例是否涵盖了这一点?
  • 这个例子不包括那个,那不是我解释需求的方式,原始代码示例没有这样做。此代码可以更新为也以类似的方式执行此操作。我很快就会更新我的答案。
  • 再看一遍,如果不循环两次或使用Iterator 方法,我想不出一个从两个列表中删除的好方法。
猜你喜欢
  • 1970-01-01
  • 2016-05-09
  • 2013-06-06
  • 1970-01-01
  • 2012-03-29
  • 2013-10-10
  • 1970-01-01
  • 2014-05-25
  • 1970-01-01
相关资源
最近更新 更多